13
13
along with this program; if not, write to the Free Software
14
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
20
21
Functions for easy reading of records, possible through a cache
23
#include "drizzled/error.h"
24
#include "drizzled/table.h"
25
#include "drizzled/session.h"
26
#include "drizzled/records.h"
27
#include "drizzled/optimizer/range.h"
28
#include "drizzled/internal/my_sys.h"
29
#include "drizzled/internal/iocache.h"
34
static int rr_sequential(ReadRecord *info);
35
static int rr_quick(ReadRecord *info);
36
static int rr_from_tempfile(ReadRecord *info);
37
static int rr_unpack_from_tempfile(ReadRecord *info);
38
static int rr_unpack_from_buffer(ReadRecord *info);
39
static int rr_from_pointers(ReadRecord *info);
40
static int rr_from_cache(ReadRecord *info);
23
#include <drizzled/server_includes.h>
24
#include <drizzled/error.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(Session *session, READ_RECORD *info);
41
34
static int rr_cmp(unsigned char *a,unsigned char *b);
42
static int rr_index_first(ReadRecord *info);
43
static int rr_index(ReadRecord *info);
45
void ReadRecord::init_reard_record_sequential()
47
read_record= rr_sequential;
50
void ReadRecord::init_read_record_idx(Session *,
55
table_arg->emptyRecord();
57
cursor= table->cursor;
58
record= table->getInsertRecord();
59
print_error= print_error_arg;
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 session 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, Session *, Table *table,
56
bool print_error, uint32_t idx)
59
memset(info, 0, sizeof(*info));
61
info->file= table->file;
62
info->record= table->record[0];
63
info->print_error= print_error;
61
65
table->status=0; /* And it's always found */
62
if (not table->cursor->inited)
63
table->cursor->startIndexScan(idx, 1);
66
if (!table->file->inited)
67
table->file->ha_index_init(idx, 1);
64
68
/* read_record will be changed to rr_index in rr_index_first */
65
read_record= rr_index_first;
69
info->read_record= rr_index_first;
69
void ReadRecord::init_read_record(Session *session_arg,
71
optimizer::SqlSelect *select_arg,
74
init_read_record is used to scan by using a number of different methods.
75
Which method to use is set-up in this call so that later calls to
76
the info->read_record will call the appropriate method using a function
79
There are five methods that relate completely to the sort function
80
filesort. The result of a filesort is retrieved using read_record
81
calls. The other two methods are used for normal table access.
83
The filesort will produce references to the records sorted, these
84
references can be stored in memory or in a temporary file.
86
The temporary file is normally used when the references doesn't fit into
87
a properly sized memory buffer. For most small queries the references
88
are stored in the memory buffer.
90
The temporary file is also used when performing an update where a key is
93
Methods used when ref's are in memory (using rr_from_pointers):
94
rr_unpack_from_buffer:
95
----------------------
96
This method is used when table->sort.addon_field is allocated.
97
This is allocated for most SELECT queries not involving any BLOB's.
98
In this case the records are fetched from a memory buffer.
101
Used when the above is not true, UPDATE, DELETE and so forth and
102
SELECT's involving BLOB's. It is also used when the addon_field
103
buffer is not allocated due to that its size was bigger than the
104
session variable max_length_for_sort_data.
105
In this case the record data is fetched from the handler using the
106
saved reference using the rnd_pos handler call.
108
Methods used when ref's are in a temporary file (using rr_from_tempfile)
109
rr_unpack_from_tempfile:
110
------------------------
111
Same as rr_unpack_from_buffer except that references are fetched from
112
temporary file. Should obviously not really happen other than in
113
strange configurations.
117
Same as rr_from_pointers except that references are fetched from
118
temporary file instead of from
121
This is a special variant of rr_from_tempfile that can be used for
122
handlers that is not using the HA_FAST_KEY_READ table flag. Instead
123
of reading the references one by one from the temporary file it reads
124
a set of them, sorts them and reads all of them into a buffer which
125
is then used for a number of subsequent calls to rr_from_cache.
126
It is only used for SELECT queries and a number of other conditions
129
All other accesses use either index access methods (rr_quick) or a full
130
table scan (rr_sequential).
133
rr_quick uses one of the QUICK_SELECT classes in opt_range.cc to
134
perform an index scan. There are loads of functionality hidden
135
in these quick classes. It handles all index scans of various kinds.
138
This is the most basic access method of a table using rnd_init,
139
rnd_next and rnd_end. No indexes are used.
141
void init_read_record(READ_RECORD *info,Session *session, Table *table,
143
int use_record_cache, bool print_error)
75
internal::IO_CACHE *tempfile;
79
cursor= table->cursor;
80
forms= &table; /* Only one table */
147
memset(info, 0, sizeof(*info));
148
info->session=session;
150
info->file= table->file;
151
info->forms= &info->table; /* Only one table */
153
if (table->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE &&
154
!table->sort.addon_field)
155
table->file->extra(HA_EXTRA_MMAP);
82
157
if (table->sort.addon_field)
84
rec_buf= table->sort.addon_buf;
85
ref_length= table->sort.addon_length;
159
info->rec_buf= table->sort.addon_buf;
160
info->ref_length= table->sort.addon_length;
90
record= table->getInsertRecord();
91
ref_length= table->cursor->ref_length;
165
info->record= table->record[0];
166
info->ref_length= table->file->ref_length;
94
print_error= print_error_arg;
95
ignore_not_found_rows= 0;
169
info->print_error=print_error;
170
info->ignore_not_found_rows= 0;
96
171
table->status=0; /* And it's always found */
98
if (select && my_b_inited(select->file))
100
tempfile= select->file;
173
if (select && my_b_inited(&select->file))
174
tempfile= &select->file;
104
176
tempfile= table->sort.io_cache;
107
177
if (tempfile && my_b_inited(tempfile)) // Test if ref-records was used
109
read_record= (table->sort.addon_field ?
110
rr_unpack_from_tempfile : rr_from_tempfile);
113
reinit_io_cache(io_cache,internal::READ_CACHE,0L,0,0);
114
ref_pos=table->cursor->ref;
115
if (!table->cursor->inited)
116
table->cursor->startTableScan(0);
179
info->read_record= (table->sort.addon_field ?
180
rr_unpack_from_tempfile : rr_from_tempfile);
181
info->io_cache=tempfile;
182
reinit_io_cache(info->io_cache,READ_CACHE,0L,0,0);
183
info->ref_pos=table->file->ref;
184
if (!table->file->inited)
185
table->file->ha_rnd_init(0);
119
188
table->sort.addon_field is checked because if we use addon fields,
121
190
and table->sort.io_cache is read sequentially
123
192
if (!table->sort.addon_field &&
124
session->variables.read_rnd_buff_size &&
125
!(table->cursor->getEngine()->check_flag(HTON_BIT_FAST_KEY_READ)) &&
126
(table->db_stat & HA_READ_ONLY ||
127
table->reginfo.lock_type <= TL_READ_NO_INSERT) &&
128
(uint64_t) table->getShare()->getRecordLength() * (table->cursor->stats.records+
129
table->cursor->stats.deleted) >
130
(uint64_t) MIN_FILE_LENGTH_TO_USE_ROW_CACHE &&
131
io_cache->end_of_file/ref_length * table->getShare()->getRecordLength() >
132
(internal::my_off_t) MIN_ROWS_TO_USE_TABLE_CACHE &&
133
!table->getShare()->blob_fields &&
134
ref_length <= MAX_REFLENGTH)
193
session->variables.read_rnd_buff_size &&
194
!(table->file->ha_table_flags() & HA_FAST_KEY_READ) &&
195
(table->db_stat & HA_READ_ONLY ||
196
table->reginfo.lock_type <= TL_READ_NO_INSERT) &&
197
(uint64_t) table->s->reclength* (table->file->stats.records+
198
table->file->stats.deleted) >
199
(uint64_t) MIN_FILE_LENGTH_TO_USE_ROW_CACHE &&
200
info->io_cache->end_of_file/info->ref_length * table->s->reclength >
201
(my_off_t) MIN_ROWS_TO_USE_TABLE_CACHE &&
202
!table->s->blob_fields &&
203
info->ref_length <= MAX_REFLENGTH)
205
if (! init_rr_cache(session, info))
138
read_record= rr_from_cache;
207
info->read_record=rr_from_cache;
142
211
else if (select && select->quick)
144
read_record= rr_quick;
213
info->read_record=rr_quick;
146
215
else if (table->sort.record_pointers)
148
table->cursor->startTableScan(0);
149
cache_pos=table->sort.record_pointers;
150
cache_end= cache_pos+ table->sort.found_records * ref_length;
151
read_record= (table->sort.addon_field ? rr_unpack_from_buffer : rr_from_pointers);
217
table->file->ha_rnd_init(0);
218
info->cache_pos=table->sort.record_pointers;
219
info->cache_end=info->cache_pos+
220
table->sort.found_records*info->ref_length;
221
info->read_record= (table->sort.addon_field ?
222
rr_unpack_from_buffer : rr_from_pointers);
155
read_record= rr_sequential;
156
table->cursor->startTableScan(1);
226
info->read_record=rr_sequential;
227
table->file->ha_rnd_init(1);
157
228
/* We can use record cache if we don't update dynamic length tables */
158
229
if (!table->no_cache &&
159
(use_record_cache > 0 ||
160
(int) table->reginfo.lock_type <= (int) TL_READ_WITH_SHARED_LOCKS ||
161
!(table->getShare()->db_options_in_use & HA_OPTION_PACK_RECORD)))
163
table->cursor->extra_opt(HA_EXTRA_CACHE, session->variables.read_buff_size);
230
(use_record_cache > 0 ||
231
(int) table->reginfo.lock_type <= (int) TL_READ_HIGH_PRIORITY ||
232
!(table->s->db_options_in_use & HA_OPTION_PACK_RECORD) ||
233
(use_record_cache < 0 &&
234
!(table->file->ha_table_flags() & HA_NOT_DELETE_WITH_CACHE))))
235
table->file->extra_opt(HA_EXTRA_CACHE, session->variables.read_buff_size);
238
Do condition pushdown for UPDATE/DELETE.
239
TODO: Remove this from here as it causes two condition pushdown calls
240
when we're running a SELECT and the condition cannot be pushed down.
242
if (session->variables.engine_condition_pushdown &&
243
select && select->cond &&
244
(select->cond->used_tables() & table->map) &&
245
!table->file->pushed_cond)
246
table->file->cond_push(select->cond);
168
249
} /* init_read_record */
171
void ReadRecord::end_read_record()
253
void end_read_record(READ_RECORD *info)
172
254
{ /* free cache if used */
257
free((char*) info->cache);
180
table->filesort_free_buffers();
181
(void) cursor->extra(HA_EXTRA_NO_CACHE);
182
if (read_record != rr_quick) // otherwise quick_range does it
183
(void) cursor->ha_index_or_rnd_end();
262
filesort_free_buffers(info->table,0);
263
(void) info->file->extra(HA_EXTRA_NO_CACHE);
264
if (info->read_record != rr_quick) // otherwise quick_range does it
265
(void) info->file->ha_index_or_rnd_end();
189
static int rr_handle_error(ReadRecord *info, int error)
270
static int rr_handle_error(READ_RECORD *info, int error)
191
272
if (error == HA_ERR_END_OF_FILE)
195
276
if (info->print_error)
196
info->table->print_error(error, MYF(0));
277
info->table->file->print_error(error, MYF(0));
197
278
if (error < 0) // Fix negative BDB errno
203
285
/** Read a record from head-database. */
204
static int rr_quick(ReadRecord *info)
287
static int rr_quick(READ_RECORD *info)
207
290
while ((tmp= info->select->quick->get_next()))
479
/* cacheing of records from a database */
389
/* cacheing of records from a database */
390
bool ReadRecord::init_rr_cache()
481
static int init_rr_cache(Session *session, READ_RECORD *info)
392
uint32_t local_rec_cache_size;
394
struct_length= 3 + MAX_REFLENGTH;
395
reclength= ALIGN_SIZE(table->getShare()->getRecordLength() + 1);
396
if (reclength < struct_length)
397
reclength= ALIGN_SIZE(struct_length);
399
error_offset= table->getShare()->getRecordLength();
400
cache_records= (session->variables.read_rnd_buff_size /
401
(reclength + struct_length));
402
local_rec_cache_size= cache_records * reclength;
403
rec_cache_size= cache_records * ref_length;
483
uint32_t rec_cache_size;
485
info->struct_length= 3+MAX_REFLENGTH;
486
info->reclength= ALIGN_SIZE(info->table->s->reclength+1);
487
if (info->reclength < info->struct_length)
488
info->reclength= ALIGN_SIZE(info->struct_length);
490
info->error_offset= info->table->s->reclength;
491
info->cache_records= (session->variables.read_rnd_buff_size /
492
(info->reclength+info->struct_length));
493
rec_cache_size= info->cache_records*info->reclength;
494
info->rec_cache_size= info->cache_records*info->ref_length;
405
496
// We have to allocate one more byte to use uint3korr (see comments for it)
406
if (cache_records <= 2 ||
407
!(cache=(unsigned char*) malloc(local_rec_cache_size + cache_records * struct_length + 1)))
497
if (info->cache_records <= 2 ||
498
!(info->cache=(unsigned char*) my_malloc_lock(rec_cache_size+info->cache_records*
499
info->struct_length+1,
411
502
#ifdef HAVE_purify
412
503
// Avoid warnings in qsort
413
memset(cache, 0, local_rec_cache_size + cache_records * struct_length + 1);
504
memset(info->cache, 0,
505
rec_cache_size+info->cache_records* info->struct_length+1);
415
read_positions= cache + local_rec_cache_size;
416
cache_pos= cache_end= cache;
507
info->read_positions=info->cache+rec_cache_size;
508
info->cache_pos=info->cache_end=info->cache;
419
510
} /* init_rr_cache */
421
static int rr_from_cache(ReadRecord *info)
513
static int rr_from_cache(READ_RECORD *info)
424
internal::my_off_t rest_of_file;
517
my_off_t rest_of_file;
426
519
unsigned char *position,*ref_position,*record_pos;
433
526
if (info->cache_pos[info->error_offset])
435
shortget(error,info->cache_pos);
436
if (info->print_error)
437
info->table->print_error(error,MYF(0));
528
shortget(error,info->cache_pos);
529
if (info->print_error)
530
info->table->file->print_error(error,MYF(0));
442
memcpy(info->record,info->cache_pos, (size_t) info->table->getShare()->getRecordLength());
535
memcpy(info->record,info->cache_pos,
536
(size_t) info->table->s->reclength);
444
info->cache_pos+= info->reclength;
538
info->cache_pos+=info->reclength;
445
539
return ((int) error);
447
541
length=info->rec_cache_size;
448
rest_of_file= info->io_cache->end_of_file - my_b_tell(info->io_cache);
449
if ((internal::my_off_t) length > rest_of_file)
542
rest_of_file=info->io_cache->end_of_file - my_b_tell(info->io_cache);
543
if ((my_off_t) length > rest_of_file)
451
544
length= (uint32_t) rest_of_file;
454
if (!length || my_b_read(info->io_cache, info->getCache(), length))
545
if (!length || my_b_read(info->io_cache,info->cache,length))
456
return -1; /* End of cursor */
547
return -1; /* End of file */
459
550
length/=info->ref_length;
460
position=info->getCache();
551
position=info->cache;
461
552
ref_position=info->read_positions;
462
for (uint32_t i= 0 ; i < length ; i++,position+=info->ref_length)
553
for (i=0 ; i < length ; i++,position+=info->ref_length)
464
555
memcpy(ref_position,position,(size_t) info->ref_length);
465
556
ref_position+=MAX_REFLENGTH;
466
557
int3store(ref_position,(long) i);
469
internal::my_qsort(info->read_positions, length, info->struct_length,
560
my_qsort(info->read_positions, length, info->struct_length,
472
563
position=info->read_positions;
473
for (uint32_t i= 0 ; i < length ; i++)
564
for (i=0 ; i < length ; i++)
475
memcpy(info->ref_pos, position, (size_t)info->ref_length);
566
memcpy(info->ref_pos,position,(size_t) info->ref_length);
476
567
position+=MAX_REFLENGTH;
477
568
record=uint3korr(position);
479
record_pos= info->getCache() + record * info->reclength;
480
if ((error=(int16_t) info->cursor->rnd_pos(record_pos,info->ref_pos)))
570
record_pos=info->cache+record*info->reclength;
571
if ((error=(int16_t) info->file->rnd_pos(record_pos,info->ref_pos)))
482
record_pos[info->error_offset]=1;
483
shortstore(record_pos,error);
573
record_pos[info->error_offset]=1;
574
shortstore(record_pos,error);
486
record_pos[info->error_offset]=0;
577
record_pos[info->error_offset]=0;
488
info->cache_end= (info->cache_pos= info->getCache())+length*info->reclength;
579
info->cache_end=(info->cache_pos=info->cache)+length*info->reclength;
490
581
} /* rr_from_cache */
492
584
static int rr_cmp(unsigned char *a,unsigned char *b)
494
586
if (a[0] != b[0])