21
21
Functions for easy reading of records, possible through a cache
23
#include <drizzled/server_includes.h>
24
#include <drizzled/error.h>
25
#include <drizzled/table.h>
26
#include <drizzled/session.h>
24
#include "mysql_priv.h"
28
26
static int rr_quick(READ_RECORD *info);
29
27
int rr_sequential(READ_RECORD *info);
32
30
static int rr_unpack_from_buffer(READ_RECORD *info);
33
31
static int rr_from_pointers(READ_RECORD *info);
34
32
static int rr_from_cache(READ_RECORD *info);
35
static int init_rr_cache(Session *session, READ_RECORD *info);
36
static int rr_cmp(unsigned char *a,unsigned char *b);
33
static int init_rr_cache(THD *thd, READ_RECORD *info);
34
static int rr_cmp(uchar *a,uchar *b);
37
35
static int rr_index_first(READ_RECORD *info);
38
36
static int rr_index(READ_RECORD *info);
47
45
join_read_first/next functions.
49
47
@param info READ_RECORD structure to initialize.
50
@param session Thread handle
48
@param thd Thread handle
51
49
@param table Table to be accessed
52
50
@param print_error If true, call table->file->print_error() if an error
53
51
occurs (except for end-of-records error)
54
52
@param idx index to scan
57
void init_read_record_idx(READ_RECORD *info, Session *, Table *table,
58
bool print_error, uint32_t idx)
55
void init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table,
56
bool print_error, uint idx)
60
58
empty_record(table);
61
memset(info, 0, sizeof(*info));
59
bzero((char*) info,sizeof(*info));
62
60
info->table= table;
63
61
info->file= table->file;
64
62
info->record= table->record[0];
140
138
This is the most basic access method of a table using rnd_init,
141
139
rnd_next and rnd_end. No indexes are used.
143
void init_read_record(READ_RECORD *info,Session *session, Table *table,
141
void init_read_record(READ_RECORD *info,THD *thd, TABLE *table,
144
142
SQL_SELECT *select,
145
143
int use_record_cache, bool print_error)
147
145
IO_CACHE *tempfile;
146
DBUG_ENTER("init_read_record");
149
memset(info, 0, sizeof(*info));
150
info->session=session;
148
bzero((char*) info,sizeof(*info));
151
150
info->table=table;
152
151
info->file= table->file;
153
152
info->forms= &info->table; /* Only one table */
155
154
if (table->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE &&
156
155
!table->sort.addon_field)
157
table->file->extra(HA_EXTRA_MMAP);
156
VOID(table->file->extra(HA_EXTRA_MMAP));
159
158
if (table->sort.addon_field)
161
160
info->rec_buf= table->sort.addon_buf;
178
177
tempfile= table->sort.io_cache;
179
178
if (tempfile && my_b_inited(tempfile)) // Test if ref-records was used
180
DBUG_PRINT("info",("using rr_from_tempfile"));
181
181
info->read_record= (table->sort.addon_field ?
182
182
rr_unpack_from_tempfile : rr_from_tempfile);
183
183
info->io_cache=tempfile;
192
192
and table->sort.io_cache is read sequentially
194
194
if (!table->sort.addon_field &&
195
session->variables.read_rnd_buff_size &&
195
! (specialflag & SPECIAL_SAFE_MODE) &&
196
thd->variables.read_rnd_buff_size &&
196
197
!(table->file->ha_table_flags() & HA_FAST_KEY_READ) &&
197
198
(table->db_stat & HA_READ_ONLY ||
198
199
table->reginfo.lock_type <= TL_READ_NO_INSERT) &&
199
(uint64_t) table->s->reclength* (table->file->stats.records+
200
(ulonglong) table->s->reclength* (table->file->stats.records+
200
201
table->file->stats.deleted) >
201
(uint64_t) MIN_FILE_LENGTH_TO_USE_ROW_CACHE &&
202
(ulonglong) MIN_FILE_LENGTH_TO_USE_ROW_CACHE &&
202
203
info->io_cache->end_of_file/info->ref_length * table->s->reclength >
203
204
(my_off_t) MIN_ROWS_TO_USE_TABLE_CACHE &&
204
205
!table->s->blob_fields &&
205
206
info->ref_length <= MAX_REFLENGTH)
207
if (! init_rr_cache(session, info))
208
if (! init_rr_cache(thd, info))
210
DBUG_PRINT("info",("using rr_from_cache"));
209
211
info->read_record=rr_from_cache;
213
215
else if (select && select->quick)
217
DBUG_PRINT("info",("using rr_quick"));
215
218
info->read_record=rr_quick;
217
220
else if (table->sort.record_pointers)
222
DBUG_PRINT("info",("using record_pointers"));
219
223
table->file->ha_rnd_init(0);
220
224
info->cache_pos=table->sort.record_pointers;
221
info->cache_end=info->cache_pos+
225
info->cache_end=info->cache_pos+
222
226
table->sort.found_records*info->ref_length;
223
227
info->read_record= (table->sort.addon_field ?
224
228
rr_unpack_from_buffer : rr_from_pointers);
232
DBUG_PRINT("info",("using rr_sequential"));
228
233
info->read_record=rr_sequential;
229
234
table->file->ha_rnd_init(1);
230
235
/* We can use record cache if we don't update dynamic length tables */
234
239
!(table->s->db_options_in_use & HA_OPTION_PACK_RECORD) ||
235
240
(use_record_cache < 0 &&
236
241
!(table->file->ha_table_flags() & HA_NOT_DELETE_WITH_CACHE))))
237
table->file->extra_opt(HA_EXTRA_CACHE, session->variables.read_buff_size);
242
VOID(table->file->extra_opt(HA_EXTRA_CACHE,
243
thd->variables.read_buff_size));
240
246
Do condition pushdown for UPDATE/DELETE.
241
TODO: Remove this from here as it causes two condition pushdown calls
247
TODO: Remove this from here as it causes two condition pushdown calls
242
248
when we're running a SELECT and the condition cannot be pushed down.
244
if (session->variables.engine_condition_pushdown &&
245
select && select->cond &&
250
if (thd->variables.engine_condition_pushdown &&
251
select && select->cond &&
246
252
(select->cond->used_tables() & table->map) &&
247
253
!table->file->pushed_cond)
248
254
table->file->cond_push(select->cond);
251
257
} /* init_read_record */
358
363
int rr_sequential(READ_RECORD *info)
361
while ((tmp= info->file->rnd_next(info->record)))
366
while ((tmp=info->file->rnd_next(info->record)))
363
if (info->session->killed)
368
if (info->thd->killed)
365
info->session->send_kill_message();
370
info->thd->send_kill_message();
369
TODO> Fix this so that engine knows how to behave on its own.
370
374
rnd_next can return RECORD_DELETED for MyISAM when one thread is
371
375
reading and another deleting without locks.
406
408
Read a result set record from a temporary file after sorting.
408
410
The function first reads the next sorted record from the temporary file.
409
into a buffer. If a success it calls a callback function that unpacks
411
into a buffer. If a success it calls a callback function that unpacks
410
412
the fields values use in the result set from this buffer into their
411
413
positions in the regular record buffer.
423
425
if (my_b_read(info->io_cache, info->rec_buf, info->ref_length))
425
Table *table= info->table;
427
TABLE *table= info->table;
426
428
(*table->sort.unpack)(table->sort.addon_field, info->rec_buf);
457
459
Read a result set record from a buffer after sorting.
459
461
The function first reads the next sorted record from the sort buffer.
460
If a success it calls a callback function that unpacks
462
If a success it calls a callback function that unpacks
461
463
the fields values use in the result set from this buffer into their
462
464
positions in the regular record buffer.
474
476
if (info->cache_pos == info->cache_end)
475
477
return -1; /* End of buffer */
476
Table *table= info->table;
478
TABLE *table= info->table;
477
479
(*table->sort.unpack)(table->sort.addon_field, info->cache_pos);
478
480
info->cache_pos+= info->ref_length;
482
484
/* cacheing of records from a database */
484
static int init_rr_cache(Session *session, READ_RECORD *info)
486
static int init_rr_cache(THD *thd, READ_RECORD *info)
486
uint32_t rec_cache_size;
489
DBUG_ENTER("init_rr_cache");
488
491
info->struct_length= 3+MAX_REFLENGTH;
489
492
info->reclength= ALIGN_SIZE(info->table->s->reclength+1);
491
494
info->reclength= ALIGN_SIZE(info->struct_length);
493
496
info->error_offset= info->table->s->reclength;
494
info->cache_records= (session->variables.read_rnd_buff_size /
497
info->cache_records= (thd->variables.read_rnd_buff_size /
495
498
(info->reclength+info->struct_length));
496
499
rec_cache_size= info->cache_records*info->reclength;
497
500
info->rec_cache_size= info->cache_records*info->ref_length;
499
502
// We have to allocate one more byte to use uint3korr (see comments for it)
500
503
if (info->cache_records <= 2 ||
501
!(info->cache=(unsigned char*) malloc(rec_cache_size+info->cache_records*
502
info->struct_length+1)))
504
!(info->cache=(uchar*) my_malloc_lock(rec_cache_size+info->cache_records*
505
info->struct_length+1,
504
508
#ifdef HAVE_purify
505
509
// Avoid warnings in qsort
506
memset(info->cache, 0,
507
rec_cache_size+info->cache_records* info->struct_length+1);
510
bzero(info->cache,rec_cache_size+info->cache_records* info->struct_length+1);
512
DBUG_PRINT("info",("Allocated buffert for %d records",info->cache_records));
509
513
info->read_positions=info->cache+rec_cache_size;
510
514
info->cache_pos=info->cache_end=info->cache;
512
516
} /* init_rr_cache */
515
519
static int rr_from_cache(READ_RECORD *info)
519
523
my_off_t rest_of_file;
521
unsigned char *position,*ref_position,*record_pos;
525
uchar *position,*ref_position,*record_pos;
543
547
length=info->rec_cache_size;
544
548
rest_of_file=info->io_cache->end_of_file - my_b_tell(info->io_cache);
545
549
if ((my_off_t) length > rest_of_file)
546
length= (uint32_t) rest_of_file;
550
length= (ulong) rest_of_file;
547
551
if (!length || my_b_read(info->io_cache,info->cache,length))
553
DBUG_PRINT("info",("Found end of file"));
549
554
return -1; /* End of file */
570
575
record=uint3korr(position);
572
577
record_pos=info->cache+record*info->reclength;
573
if ((error=(int16_t) info->file->rnd_pos(record_pos,info->ref_pos)))
578
if ((error=(int16) info->file->rnd_pos(record_pos,info->ref_pos)))
575
580
record_pos[info->error_offset]=1;
576
581
shortstore(record_pos,error);
582
DBUG_PRINT("error",("Got error: %d:%d when reading row",
579
586
record_pos[info->error_offset]=0;