20
21
Functions for easy reading of records, possible through a cache
24
#include <drizzled/drizzled.h>
25
#include <drizzled/error.h>
26
#include <drizzled/internal/iocache.h>
27
#include <drizzled/internal/my_sys.h>
28
#include <drizzled/optimizer/range.h>
29
#include <drizzled/plugin/storage_engine.h>
30
#include <drizzled/records.h>
31
#include <drizzled/session.h>
32
#include <drizzled/table.h>
37
static int rr_sequential(ReadRecord *info);
38
static int rr_quick(ReadRecord *info);
39
static int rr_from_tempfile(ReadRecord *info);
40
static int rr_unpack_from_tempfile(ReadRecord *info);
41
static int rr_unpack_from_buffer(ReadRecord *info);
42
static int rr_from_pointers(ReadRecord *info);
43
static int rr_from_cache(ReadRecord *info);
44
static int rr_cmp(unsigned char *a,unsigned char *b);
45
static int rr_index_first(ReadRecord *info);
46
static int rr_index(ReadRecord *info);
48
void ReadRecord::init_reard_record_sequential()
50
read_record= rr_sequential;
53
int ReadRecord::init_read_record_idx(Session *,
58
table_arg->emptyRecord();
60
cursor= table->cursor;
61
record= table->getInsertRecord();
62
print_error= print_error_arg;
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,
56
THD *thd __attribute__((__unused__)),
58
bool print_error, uint idx)
61
bzero((char*) info,sizeof(*info));
63
info->file= table->file;
64
info->record= table->record[0];
65
info->print_error= print_error;
64
67
table->status=0; /* And it's always found */
65
if (not table->cursor->inited)
67
int error= table->cursor->startIndexScan(idx, 1);
68
if (!table->file->inited)
69
table->file->ha_index_init(idx, 1);
71
70
/* read_record will be changed to rr_index in rr_index_first */
72
read_record= rr_index_first;
71
info->read_record= rr_index_first;
78
int ReadRecord::init_read_record(Session *session_arg,
80
optimizer::SqlSelect *select_arg,
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.
92
The temporary file is also used when performing an update where a key is
95
Methods used when ref's are in memory (using rr_from_pointers):
96
rr_unpack_from_buffer:
97
----------------------
98
This method is used when table->sort.addon_field is allocated.
99
This is allocated for most SELECT queries not involving any BLOB's.
100
In this case the records are fetched from a memory buffer.
103
Used when the above is not true, UPDATE, DELETE and so forth and
104
SELECT's involving BLOB's. It is also used when the addon_field
105
buffer is not allocated due to that its size was bigger than the
106
session variable max_length_for_sort_data.
107
In this case the record data is fetched from the handler using the
108
saved reference using the rnd_pos handler call.
110
Methods used when ref's are in a temporary file (using rr_from_tempfile)
111
rr_unpack_from_tempfile:
112
------------------------
113
Same as rr_unpack_from_buffer except that references are fetched from
114
temporary file. Should obviously not really happen other than in
115
strange configurations.
119
Same as rr_from_pointers except that references are fetched from
120
temporary file instead of from
123
This is a special variant of rr_from_tempfile that can be used for
124
handlers that is not using the HA_FAST_KEY_READ table flag. Instead
125
of reading the references one by one from the temporary file it reads
126
a set of them, sorts them and reads all of them into a buffer which
127
is then used for a number of subsequent calls to rr_from_cache.
128
It is only used for SELECT queries and a number of other conditions
131
All other accesses use either index access methods (rr_quick) or a full
132
table scan (rr_sequential).
135
rr_quick uses one of the QUICK_SELECT classes in opt_range.cc to
136
perform an index scan. There are loads of functionality hidden
137
in these quick classes. It handles all index scans of various kinds.
140
This is the most basic access method of a table using rnd_init,
141
rnd_next and rnd_end. No indexes are used.
143
void init_read_record(READ_RECORD *info,THD *thd, TABLE *table,
145
int use_record_cache, bool print_error)
84
internal::IO_CACHE *tempfile;
89
cursor= table->cursor;
90
forms= &table; /* Only one table */
149
bzero((char*) info,sizeof(*info));
152
info->file= table->file;
153
info->forms= &info->table; /* Only one table */
155
if (table->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE &&
156
!table->sort.addon_field)
157
VOID(table->file->extra(HA_EXTRA_MMAP));
92
159
if (table->sort.addon_field)
94
rec_buf= table->sort.addon_buf;
95
ref_length= table->sort.addon_length;
161
info->rec_buf= table->sort.addon_buf;
162
info->ref_length= table->sort.addon_length;
100
record= table->getInsertRecord();
101
ref_length= table->cursor->ref_length;
167
info->record= table->record[0];
168
info->ref_length= table->file->ref_length;
104
print_error= print_error_arg;
105
ignore_not_found_rows= 0;
171
info->print_error=print_error;
172
info->ignore_not_found_rows= 0;
106
173
table->status=0; /* And it's always found */
108
if (select && my_b_inited(select->file))
110
tempfile= select->file;
175
if (select && my_b_inited(&select->file))
176
tempfile= &select->file;
114
178
tempfile= table->sort.io_cache;
117
179
if (tempfile && my_b_inited(tempfile)) // Test if ref-records was used
119
read_record= (table->sort.addon_field ?
120
rr_unpack_from_tempfile : rr_from_tempfile);
123
io_cache->reinit_io_cache(internal::READ_CACHE,0L,0,0);
124
ref_pos=table->cursor->ref;
125
if (!table->cursor->inited)
127
error= table->cursor->startTableScan(0);
181
info->read_record= (table->sort.addon_field ?
182
rr_unpack_from_tempfile : rr_from_tempfile);
183
info->io_cache=tempfile;
184
reinit_io_cache(info->io_cache,READ_CACHE,0L,0,0);
185
info->ref_pos=table->file->ref;
186
if (!table->file->inited)
187
table->file->ha_rnd_init(0);
133
190
table->sort.addon_field is checked because if we use addon fields,
135
192
and table->sort.io_cache is read sequentially
137
194
if (!table->sort.addon_field &&
138
session->variables.read_rnd_buff_size &&
139
!(table->cursor->getEngine()->check_flag(HTON_BIT_FAST_KEY_READ)) &&
140
(table->db_stat & HA_READ_ONLY ||
141
table->reginfo.lock_type <= TL_READ_NO_INSERT) &&
142
(uint64_t) table->getShare()->getRecordLength() * (table->cursor->stats.records+
143
table->cursor->stats.deleted) >
144
(uint64_t) MIN_FILE_LENGTH_TO_USE_ROW_CACHE &&
145
io_cache->end_of_file/ref_length * table->getShare()->getRecordLength() >
146
(internal::my_off_t) MIN_ROWS_TO_USE_TABLE_CACHE &&
147
!table->getShare()->blob_fields &&
148
ref_length <= MAX_REFLENGTH)
195
! (specialflag & SPECIAL_SAFE_MODE) &&
196
thd->variables.read_rnd_buff_size &&
197
!(table->file->ha_table_flags() & HA_FAST_KEY_READ) &&
198
(table->db_stat & HA_READ_ONLY ||
199
table->reginfo.lock_type <= TL_READ_NO_INSERT) &&
200
(uint64_t) table->s->reclength* (table->file->stats.records+
201
table->file->stats.deleted) >
202
(uint64_t) MIN_FILE_LENGTH_TO_USE_ROW_CACHE &&
203
info->io_cache->end_of_file/info->ref_length * table->s->reclength >
204
(my_off_t) MIN_ROWS_TO_USE_TABLE_CACHE &&
205
!table->s->blob_fields &&
206
info->ref_length <= MAX_REFLENGTH)
208
if (! init_rr_cache(thd, info))
152
read_record= rr_from_cache;
210
info->read_record=rr_from_cache;
156
214
else if (select && select->quick)
158
read_record= rr_quick;
216
info->read_record=rr_quick;
160
218
else if (table->sort.record_pointers)
162
error= table->cursor->startTableScan(0);
166
cache_pos=table->sort.record_pointers;
167
cache_end= cache_pos+ table->sort.found_records * ref_length;
168
read_record= (table->sort.addon_field ? rr_unpack_from_buffer : rr_from_pointers);
220
table->file->ha_rnd_init(0);
221
info->cache_pos=table->sort.record_pointers;
222
info->cache_end=info->cache_pos+
223
table->sort.found_records*info->ref_length;
224
info->read_record= (table->sort.addon_field ?
225
rr_unpack_from_buffer : rr_from_pointers);
172
read_record= rr_sequential;
173
error= table->cursor->startTableScan(1);
229
info->read_record=rr_sequential;
230
table->file->ha_rnd_init(1);
177
231
/* We can use record cache if we don't update dynamic length tables */
178
232
if (!table->no_cache &&
179
(use_record_cache > 0 ||
180
(int) table->reginfo.lock_type <= (int) TL_READ_WITH_SHARED_LOCKS ||
181
!(table->getShare()->db_options_in_use & HA_OPTION_PACK_RECORD)))
183
table->cursor->extra_opt(HA_EXTRA_CACHE, session->variables.read_buff_size);
233
(use_record_cache > 0 ||
234
(int) table->reginfo.lock_type <= (int) TL_READ_HIGH_PRIORITY ||
235
!(table->s->db_options_in_use & HA_OPTION_PACK_RECORD) ||
236
(use_record_cache < 0 &&
237
!(table->file->ha_table_flags() & HA_NOT_DELETE_WITH_CACHE))))
238
VOID(table->file->extra_opt(HA_EXTRA_CACHE,
239
thd->variables.read_buff_size));
242
Do condition pushdown for UPDATE/DELETE.
243
TODO: Remove this from here as it causes two condition pushdown calls
244
when we're running a SELECT and the condition cannot be pushed down.
246
if (thd->variables.engine_condition_pushdown &&
247
select && select->cond &&
248
(select->cond->used_tables() & table->map) &&
249
!table->file->pushed_cond)
250
table->file->cond_push(select->cond);
188
253
} /* init_read_record */
191
void ReadRecord::end_read_record()
257
void end_read_record(READ_RECORD *info)
192
258
{ /* free cache if used */
195
global_read_rnd_buffer.sub(session->variables.read_rnd_buff_size);
261
my_free_lock((char*) info->cache,MYF(0));
201
table->filesort_free_buffers();
202
(void) cursor->extra(HA_EXTRA_NO_CACHE);
203
if (read_record != rr_quick) // otherwise quick_range does it
204
(void) cursor->ha_index_or_rnd_end();
266
filesort_free_buffers(info->table,0);
267
(void) info->file->extra(HA_EXTRA_NO_CACHE);
268
if (info->read_record != rr_quick) // otherwise quick_range does it
269
(void) info->file->ha_index_or_rnd_end();
210
static int rr_handle_error(ReadRecord *info, int error)
274
static int rr_handle_error(READ_RECORD *info, int error)
212
276
if (error == HA_ERR_END_OF_FILE)
216
280
if (info->print_error)
217
info->table->print_error(error, MYF(0));
281
info->table->file->print_error(error, MYF(0));
218
282
if (error < 0) // Fix negative BDB errno
224
289
/** Read a record from head-database. */
225
static int rr_quick(ReadRecord *info)
291
static int rr_quick(READ_RECORD *info)
228
294
while ((tmp= info->select->quick->get_next()))
230
if (info->session->getKilled())
296
if (info->thd->killed)
232
298
my_error(ER_SERVER_SHUTDOWN, MYF(0));
397
467
-1 There is no record to be read anymore.
399
static int rr_unpack_from_buffer(ReadRecord *info)
470
static int rr_unpack_from_buffer(READ_RECORD *info)
401
472
if (info->cache_pos == info->cache_end)
402
473
return -1; /* End of buffer */
403
Table *table= info->table;
474
TABLE *table= info->table;
404
475
(*table->sort.unpack)(table->sort.addon_field, info->cache_pos);
405
476
info->cache_pos+= info->ref_length;
480
/* cacheing of records from a database */
410
/* cacheing of records from a database */
411
bool ReadRecord::init_rr_cache()
482
static int init_rr_cache(THD *thd, READ_RECORD *info)
413
uint32_t local_rec_cache_size;
415
struct_length= 3 + MAX_REFLENGTH;
416
reclength= ALIGN_SIZE(table->getShare()->getRecordLength() + 1);
417
if (reclength < struct_length)
418
reclength= ALIGN_SIZE(struct_length);
420
error_offset= table->getShare()->getRecordLength();
421
cache_records= (session->variables.read_rnd_buff_size /
422
(reclength + struct_length));
423
local_rec_cache_size= cache_records * reclength;
424
rec_cache_size= cache_records * ref_length;
426
if (not global_read_rnd_buffer.add(session->variables.read_rnd_buff_size))
428
my_error(ER_OUT_OF_GLOBAL_READRNDMEMORY, MYF(ME_ERROR+ME_WAITTANG));
486
info->struct_length= 3+MAX_REFLENGTH;
487
info->reclength= ALIGN_SIZE(info->table->s->reclength+1);
488
if (info->reclength < info->struct_length)
489
info->reclength= ALIGN_SIZE(info->struct_length);
491
info->error_offset= info->table->s->reclength;
492
info->cache_records= (thd->variables.read_rnd_buff_size /
493
(info->reclength+info->struct_length));
494
rec_cache_size= info->cache_records*info->reclength;
495
info->rec_cache_size= info->cache_records*info->ref_length;
432
497
// We have to allocate one more byte to use uint3korr (see comments for it)
433
if (cache_records <= 2 ||
434
!(cache=(unsigned char*) malloc(local_rec_cache_size + cache_records * struct_length + 1)))
498
if (info->cache_records <= 2 ||
499
!(info->cache=(uchar*) my_malloc_lock(rec_cache_size+info->cache_records*
500
info->struct_length+1,
439
504
// Avoid warnings in qsort
440
memset(cache, 0, local_rec_cache_size + cache_records * struct_length + 1);
505
bzero(info->cache,rec_cache_size+info->cache_records* info->struct_length+1);
442
read_positions= cache + local_rec_cache_size;
443
cache_pos= cache_end= cache;
507
info->read_positions=info->cache+rec_cache_size;
508
info->cache_pos=info->cache_end=info->cache;
446
510
} /* init_rr_cache */
448
static int rr_from_cache(ReadRecord *info)
513
static int rr_from_cache(READ_RECORD *info)
451
internal::my_off_t rest_of_file;
453
unsigned char *position,*ref_position,*record_pos;
517
my_off_t rest_of_file;
519
uchar *position,*ref_position,*record_pos;
460
526
if (info->cache_pos[info->error_offset])
462
shortget(error,info->cache_pos);
463
if (info->print_error)
464
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));
469
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);
471
info->cache_pos+= info->reclength;
538
info->cache_pos+=info->reclength;
472
539
return ((int) error);
474
541
length=info->rec_cache_size;
475
rest_of_file= info->io_cache->end_of_file - my_b_tell(info->io_cache);
476
if ((internal::my_off_t) length > rest_of_file)
478
length= (uint32_t) rest_of_file;
481
if (!length || my_b_read(info->io_cache, info->getCache(), length))
483
return -1; /* End of cursor */
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)
544
length= (ulong) rest_of_file;
545
if (!length || my_b_read(info->io_cache,info->cache,length))
547
return -1; /* End of file */
486
550
length/=info->ref_length;
487
position=info->getCache();
551
position=info->cache;
488
552
ref_position=info->read_positions;
489
for (uint32_t i= 0 ; i < length ; i++,position+=info->ref_length)
553
for (i=0 ; i < length ; i++,position+=info->ref_length)
491
555
memcpy(ref_position,position,(size_t) info->ref_length);
492
556
ref_position+=MAX_REFLENGTH;
493
557
int3store(ref_position,(long) i);
496
internal::my_qsort(info->read_positions, length, info->struct_length,
560
my_qsort(info->read_positions, length, info->struct_length,
499
563
position=info->read_positions;
500
for (uint32_t i= 0 ; i < length ; i++)
564
for (i=0 ; i < length ; i++)
502
memcpy(info->ref_pos, position, (size_t)info->ref_length);
566
memcpy(info->ref_pos,position,(size_t) info->ref_length);
503
567
position+=MAX_REFLENGTH;
504
568
record=uint3korr(position);
506
record_pos= info->getCache() + record * info->reclength;
507
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) info->file->rnd_pos(record_pos,info->ref_pos)))
509
record_pos[info->error_offset]=1;
510
shortstore(record_pos,error);
573
record_pos[info->error_offset]=1;
574
shortstore(record_pos,error);
513
record_pos[info->error_offset]=0;
577
record_pos[info->error_offset]=0;
515
info->cache_end= (info->cache_pos= info->getCache())+length*info->reclength;
579
info->cache_end=(info->cache_pos=info->cache)+length*info->reclength;
517
581
} /* rr_from_cache */
519
static int rr_cmp(unsigned char *a,unsigned char *b)
584
static int rr_cmp(uchar *a,uchar *b)
521
586
if (a[0] != b[0])
522
587
return (int) a[0] - (int) b[0];