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"
30
#include "drizzled/drizzled.h"
35
static int rr_sequential(ReadRecord *info);
36
static int rr_quick(ReadRecord *info);
37
static int rr_from_tempfile(ReadRecord *info);
38
static int rr_unpack_from_tempfile(ReadRecord *info);
39
static int rr_unpack_from_buffer(ReadRecord *info);
40
static int rr_from_pointers(ReadRecord *info);
41
static int rr_from_cache(ReadRecord *info);
23
#include <drizzled/server_includes.h>
24
#include <drizzled/error.h>
25
#include <drizzled/table.h>
26
#include <drizzled/session.h>
28
static int rr_quick(READ_RECORD *info);
29
int rr_sequential(READ_RECORD *info);
30
static int rr_from_tempfile(READ_RECORD *info);
31
static int rr_unpack_from_tempfile(READ_RECORD *info);
32
static int rr_unpack_from_buffer(READ_RECORD *info);
33
static int rr_from_pointers(READ_RECORD *info);
34
static int rr_from_cache(READ_RECORD *info);
35
static int init_rr_cache(Session *session, READ_RECORD *info);
42
36
static int rr_cmp(unsigned char *a,unsigned char *b);
43
static int rr_index_first(ReadRecord *info);
44
static int rr_index(ReadRecord *info);
46
void ReadRecord::init_reard_record_sequential()
48
read_record= rr_sequential;
51
void ReadRecord::init_read_record_idx(Session *,
56
table_arg->emptyRecord();
58
cursor= table->cursor;
59
record= table->getInsertRecord();
60
print_error= print_error_arg;
37
static int rr_index_first(READ_RECORD *info);
38
static int rr_index(READ_RECORD *info);
42
Initialize READ_RECORD structure to perform full index scan (in forward
43
direction) using read_record.read_record() interface.
45
This function has been added at late stage and is used only by
46
UPDATE/DELETE. Other statements perform index scans using
47
join_read_first/next functions.
49
@param info READ_RECORD structure to initialize.
50
@param session Thread handle
51
@param table Table to be accessed
52
@param print_error If true, call table->file->print_error() if an error
53
occurs (except for end-of-records error)
54
@param idx index to scan
57
void init_read_record_idx(READ_RECORD *info, Session *, Table *table,
58
bool print_error, uint32_t idx)
61
memset(info, 0, sizeof(*info));
63
info->file= table->file;
64
info->record= table->record[0];
65
info->print_error= print_error;
62
67
table->status=0; /* And it's always found */
63
if (not table->cursor->inited)
64
table->cursor->startIndexScan(idx, 1);
68
if (!table->file->inited)
69
table->file->ha_index_init(idx, 1);
65
70
/* read_record will be changed to rr_index in rr_index_first */
66
read_record= rr_index_first;
71
info->read_record= rr_index_first;
70
void ReadRecord::init_read_record(Session *session_arg,
72
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,Session *session, Table *table,
145
int use_record_cache, bool print_error)
76
internal::IO_CACHE *tempfile;
80
cursor= table->cursor;
81
forms= &table; /* Only one table */
149
memset(info, 0, sizeof(*info));
150
info->session=session;
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
table->file->extra(HA_EXTRA_MMAP);
83
159
if (table->sort.addon_field)
85
rec_buf= table->sort.addon_buf;
86
ref_length= table->sort.addon_length;
161
info->rec_buf= table->sort.addon_buf;
162
info->ref_length= table->sort.addon_length;
91
record= table->getInsertRecord();
92
ref_length= table->cursor->ref_length;
167
info->record= table->record[0];
168
info->ref_length= table->file->ref_length;
95
print_error= print_error_arg;
96
ignore_not_found_rows= 0;
171
info->print_error=print_error;
172
info->ignore_not_found_rows= 0;
97
173
table->status=0; /* And it's always found */
99
if (select && my_b_inited(select->file))
101
tempfile= select->file;
175
if (select && my_b_inited(&select->file))
176
tempfile= &select->file;
105
178
tempfile= table->sort.io_cache;
108
179
if (tempfile && my_b_inited(tempfile)) // Test if ref-records was used
110
read_record= (table->sort.addon_field ?
111
rr_unpack_from_tempfile : rr_from_tempfile);
114
io_cache->reinit_io_cache(internal::READ_CACHE,0L,0,0);
115
ref_pos=table->cursor->ref;
116
if (!table->cursor->inited)
117
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);
120
190
table->sort.addon_field is checked because if we use addon fields,
122
192
and table->sort.io_cache is read sequentially
124
194
if (!table->sort.addon_field &&
125
session->variables.read_rnd_buff_size &&
126
!(table->cursor->getEngine()->check_flag(HTON_BIT_FAST_KEY_READ)) &&
127
(table->db_stat & HA_READ_ONLY ||
128
table->reginfo.lock_type <= TL_READ_NO_INSERT) &&
129
(uint64_t) table->getShare()->getRecordLength() * (table->cursor->stats.records+
130
table->cursor->stats.deleted) >
131
(uint64_t) MIN_FILE_LENGTH_TO_USE_ROW_CACHE &&
132
io_cache->end_of_file/ref_length * table->getShare()->getRecordLength() >
133
(internal::my_off_t) MIN_ROWS_TO_USE_TABLE_CACHE &&
134
!table->getShare()->blob_fields &&
135
ref_length <= MAX_REFLENGTH)
195
session->variables.read_rnd_buff_size &&
196
!(table->file->ha_table_flags() & HA_FAST_KEY_READ) &&
197
(table->db_stat & HA_READ_ONLY ||
198
table->reginfo.lock_type <= TL_READ_NO_INSERT) &&
199
(uint64_t) table->s->reclength* (table->file->stats.records+
200
table->file->stats.deleted) >
201
(uint64_t) MIN_FILE_LENGTH_TO_USE_ROW_CACHE &&
202
info->io_cache->end_of_file/info->ref_length * table->s->reclength >
203
(my_off_t) MIN_ROWS_TO_USE_TABLE_CACHE &&
204
!table->s->blob_fields &&
205
info->ref_length <= MAX_REFLENGTH)
207
if (! init_rr_cache(session, info))
139
read_record= rr_from_cache;
209
info->read_record=rr_from_cache;
143
213
else if (select && select->quick)
145
read_record= rr_quick;
215
info->read_record=rr_quick;
147
217
else if (table->sort.record_pointers)
149
table->cursor->startTableScan(0);
150
cache_pos=table->sort.record_pointers;
151
cache_end= cache_pos+ table->sort.found_records * ref_length;
152
read_record= (table->sort.addon_field ? rr_unpack_from_buffer : rr_from_pointers);
219
table->file->ha_rnd_init(0);
220
info->cache_pos=table->sort.record_pointers;
221
info->cache_end=info->cache_pos+
222
table->sort.found_records*info->ref_length;
223
info->read_record= (table->sort.addon_field ?
224
rr_unpack_from_buffer : rr_from_pointers);
156
read_record= rr_sequential;
157
table->cursor->startTableScan(1);
228
info->read_record=rr_sequential;
229
table->file->ha_rnd_init(1);
158
230
/* We can use record cache if we don't update dynamic length tables */
159
231
if (!table->no_cache &&
160
(use_record_cache > 0 ||
161
(int) table->reginfo.lock_type <= (int) TL_READ_WITH_SHARED_LOCKS ||
162
!(table->getShare()->db_options_in_use & HA_OPTION_PACK_RECORD)))
164
table->cursor->extra_opt(HA_EXTRA_CACHE, session->variables.read_buff_size);
232
(use_record_cache > 0 ||
233
(int) table->reginfo.lock_type <= (int) TL_READ_HIGH_PRIORITY ||
234
!(table->s->db_options_in_use & HA_OPTION_PACK_RECORD) ||
235
(use_record_cache < 0 &&
236
!(table->file->ha_table_flags() & HA_NOT_DELETE_WITH_CACHE))))
237
table->file->extra_opt(HA_EXTRA_CACHE, session->variables.read_buff_size);
240
Do condition pushdown for UPDATE/DELETE.
241
TODO: Remove this from here as it causes two condition pushdown calls
242
when we're running a SELECT and the condition cannot be pushed down.
244
if (session->variables.engine_condition_pushdown &&
245
select && select->cond &&
246
(select->cond->used_tables() & table->map) &&
247
!table->file->pushed_cond)
248
table->file->cond_push(select->cond);
169
251
} /* init_read_record */
172
void ReadRecord::end_read_record()
255
void end_read_record(READ_RECORD *info)
173
256
{ /* free cache if used */
176
global_read_rnd_buffer.sub(session->variables.read_rnd_buff_size);
259
free((char*) info->cache);
182
table->filesort_free_buffers();
183
(void) cursor->extra(HA_EXTRA_NO_CACHE);
184
if (read_record != rr_quick) // otherwise quick_range does it
185
(void) cursor->ha_index_or_rnd_end();
264
filesort_free_buffers(info->table,0);
265
(void) info->file->extra(HA_EXTRA_NO_CACHE);
266
if (info->read_record != rr_quick) // otherwise quick_range does it
267
(void) info->file->ha_index_or_rnd_end();
191
static int rr_handle_error(ReadRecord *info, int error)
272
static int rr_handle_error(READ_RECORD *info, int error)
193
274
if (error == HA_ERR_END_OF_FILE)
197
278
if (info->print_error)
198
info->table->print_error(error, MYF(0));
279
info->table->file->print_error(error, MYF(0));
199
280
if (error < 0) // Fix negative BDB errno
205
287
/** Read a record from head-database. */
206
static int rr_quick(ReadRecord *info)
289
static int rr_quick(READ_RECORD *info)
209
292
while ((tmp= info->select->quick->get_next()))
211
if (info->session->getKilled())
294
if (info->session->killed)
213
296
my_error(ER_SERVER_SHUTDOWN, MYF(0));
481
/* cacheing of records from a database */
391
/* cacheing of records from a database */
392
bool ReadRecord::init_rr_cache()
483
static int init_rr_cache(Session *session, READ_RECORD *info)
394
uint32_t local_rec_cache_size;
396
struct_length= 3 + MAX_REFLENGTH;
397
reclength= ALIGN_SIZE(table->getShare()->getRecordLength() + 1);
398
if (reclength < struct_length)
399
reclength= ALIGN_SIZE(struct_length);
401
error_offset= table->getShare()->getRecordLength();
402
cache_records= (session->variables.read_rnd_buff_size /
403
(reclength + struct_length));
404
local_rec_cache_size= cache_records * reclength;
405
rec_cache_size= cache_records * ref_length;
407
if (not global_read_rnd_buffer.add(session->variables.read_rnd_buff_size))
409
my_error(ER_OUT_OF_GLOBAL_READRNDMEMORY, MYF(ME_ERROR+ME_WAITTANG));
485
uint32_t rec_cache_size;
487
info->struct_length= 3+MAX_REFLENGTH;
488
info->reclength= ALIGN_SIZE(info->table->s->reclength+1);
489
if (info->reclength < info->struct_length)
490
info->reclength= ALIGN_SIZE(info->struct_length);
492
info->error_offset= info->table->s->reclength;
493
info->cache_records= (session->variables.read_rnd_buff_size /
494
(info->reclength+info->struct_length));
495
rec_cache_size= info->cache_records*info->reclength;
496
info->rec_cache_size= info->cache_records*info->ref_length;
413
498
// We have to allocate one more byte to use uint3korr (see comments for it)
414
if (cache_records <= 2 ||
415
!(cache=(unsigned char*) malloc(local_rec_cache_size + cache_records * struct_length + 1)))
499
if (info->cache_records <= 2 ||
500
!(info->cache=(unsigned char*) malloc(rec_cache_size+info->cache_records*
501
info->struct_length+1)))
420
504
// Avoid warnings in qsort
421
memset(cache, 0, local_rec_cache_size + cache_records * struct_length + 1);
505
memset(info->cache, 0,
506
rec_cache_size+info->cache_records* info->struct_length+1);
423
read_positions= cache + local_rec_cache_size;
424
cache_pos= cache_end= cache;
508
info->read_positions=info->cache+rec_cache_size;
509
info->cache_pos=info->cache_end=info->cache;
427
511
} /* init_rr_cache */
429
static int rr_from_cache(ReadRecord *info)
514
static int rr_from_cache(READ_RECORD *info)
432
internal::my_off_t rest_of_file;
518
my_off_t rest_of_file;
434
520
unsigned char *position,*ref_position,*record_pos;
441
527
if (info->cache_pos[info->error_offset])
443
shortget(error,info->cache_pos);
444
if (info->print_error)
445
info->table->print_error(error,MYF(0));
529
shortget(error,info->cache_pos);
530
if (info->print_error)
531
info->table->file->print_error(error,MYF(0));
450
memcpy(info->record,info->cache_pos, (size_t) info->table->getShare()->getRecordLength());
536
memcpy(info->record,info->cache_pos,
537
(size_t) info->table->s->reclength);
452
info->cache_pos+= info->reclength;
539
info->cache_pos+=info->reclength;
453
540
return ((int) error);
455
542
length=info->rec_cache_size;
456
rest_of_file= info->io_cache->end_of_file - my_b_tell(info->io_cache);
457
if ((internal::my_off_t) length > rest_of_file)
543
rest_of_file=info->io_cache->end_of_file - my_b_tell(info->io_cache);
544
if ((my_off_t) length > rest_of_file)
459
545
length= (uint32_t) rest_of_file;
462
if (!length || my_b_read(info->io_cache, info->getCache(), length))
546
if (!length || my_b_read(info->io_cache,info->cache,length))
464
return -1; /* End of cursor */
548
return -1; /* End of file */
467
551
length/=info->ref_length;
468
position=info->getCache();
552
position=info->cache;
469
553
ref_position=info->read_positions;
470
for (uint32_t i= 0 ; i < length ; i++,position+=info->ref_length)
554
for (i=0 ; i < length ; i++,position+=info->ref_length)
472
556
memcpy(ref_position,position,(size_t) info->ref_length);
473
557
ref_position+=MAX_REFLENGTH;
474
558
int3store(ref_position,(long) i);
477
internal::my_qsort(info->read_positions, length, info->struct_length,
561
my_qsort(info->read_positions, length, info->struct_length,
480
564
position=info->read_positions;
481
for (uint32_t i= 0 ; i < length ; i++)
565
for (i=0 ; i < length ; i++)
483
memcpy(info->ref_pos, position, (size_t)info->ref_length);
567
memcpy(info->ref_pos,position,(size_t) info->ref_length);
484
568
position+=MAX_REFLENGTH;
485
569
record=uint3korr(position);
487
record_pos= info->getCache() + record * info->reclength;
488
if ((error=(int16_t) info->cursor->rnd_pos(record_pos,info->ref_pos)))
571
record_pos=info->cache+record*info->reclength;
572
if ((error=(int16_t) info->file->rnd_pos(record_pos,info->ref_pos)))
490
record_pos[info->error_offset]=1;
491
shortstore(record_pos,error);
574
record_pos[info->error_offset]=1;
575
shortstore(record_pos,error);
494
record_pos[info->error_offset]=0;
578
record_pos[info->error_offset]=0;
496
info->cache_end= (info->cache_pos= info->getCache())+length*info->reclength;
580
info->cache_end=(info->cache_pos=info->cache)+length*info->reclength;
498
582
} /* rr_from_cache */
500
585
static int rr_cmp(unsigned char *a,unsigned char *b)
502
587
if (a[0] != b[0])