1
/* Copyright (C) 2000-2002 MySQL AB
2
Copyright (C) 2008 eBay, Inc
4
This program is free software; you can redistribute it and/or modify
5
it under the terms of the GNU General Public License as published by
6
the Free Software Foundation; version 2 of the License.
8
This program is distributed in the hope that it will be useful,
9
but WITHOUT ANY WARRANTY; without even the implied warranty of
10
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
GNU General Public License for more details.
13
You should have received a copy of the GNU General Public License
14
along with this program; if not, write to the Free Software
15
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
17
/* Implements various base record-related functions, such as encode and decode into chunks */
19
#include "heap_priv.h"
21
#include <drizzled/common.h>
27
using namespace drizzled;
30
Calculate size of the record for the purpose of storing in chunks
32
Walk through the fields of the record and calculates the exact space
33
needed in chunks as well the the total chunk count
35
@param info the hosting table
36
@param record the record in standard unpacked format
37
@param[out] chunk_count the number of chunks needed for this record
39
@return The size of the required storage in bytes
42
uint32_t hp_get_encoded_data_length(HP_SHARE *info, const unsigned char *record, uint32_t *chunk_count)
44
uint32_t i, dst_offset;
46
dst_offset= info->fixed_data_length;
48
if (!info->recordspace.is_variable_size)
50
/* Nothing more to copy */
55
for (i= info->fixed_column_count; i < info->column_count; i++)
57
uint32_t src_offset, length;
59
HP_COLUMNDEF* column= info->column_defs + i;
63
if (record[column->null_pos] & column->null_bit)
65
/* Skip all NULL values */
70
src_offset= column->offset;
71
if (column->type == DRIZZLE_TYPE_VARCHAR)
75
/* >= 5.0.3 true VARCHAR */
77
pack_length= column->length_bytes;
78
length= pack_length + (pack_length == 1 ?
79
(uint) *(unsigned char*) (record + src_offset) : uint2korr(record + src_offset));
83
length= column->length;
89
*chunk_count= get_chunk_count(&info->recordspace, dst_offset);
95
/*static void dump_chunk(HP_SHARE *info, const unsigned char* curr_chunk)
98
fprintf(stdout, "Chunk dump at 0x%lx: ", (long)curr_chunk);
99
for (i= 0; i < info->chunk_dataspace_length; i++)
101
uint32_t b= *((unsigned char*)(curr_chunk + i));
104
fprintf(stdout, "0");
106
fprintf(stdout, "%lx ", (long)b);
108
fprintf(stdout, ". Next = 0x%lx, Status = %d\n",
109
(long)(*((unsigned char**) (curr_chunk + info->offset_link))),
110
(uint)(*((unsigned char*) (curr_chunk + info->offset_status))));
115
Encodes or compares record
117
Copies data from original unpacked record into the preallocated chunkset,
118
or performs data comparison
120
@param info the hosting table
121
@param record the record in standard unpacked format
122
@param pos the target chunkset
123
@param is_compare flag indicating whether we should compare data or store it
125
@return Status of comparison
126
@retval non-zero if comparison fond data differences
127
@retval zero otherwise
130
uint32_t hp_process_record_data_to_chunkset(HP_SHARE *info, const unsigned char *record,
131
unsigned char *pos, uint32_t is_compare)
133
uint32_t i, dst_offset;
134
unsigned char* curr_chunk= pos;
138
if (memcmp(curr_chunk, record, (size_t) info->fixed_data_length))
145
memcpy(curr_chunk, record, (size_t) info->fixed_data_length);
148
if (!info->recordspace.is_variable_size)
150
/* Nothing more to copy */
154
dst_offset= info->fixed_data_length;
156
for (i= info->fixed_column_count; i < info->column_count; i++)
158
uint32_t src_offset, length;
160
HP_COLUMNDEF* column= info->column_defs + i;
162
if (column->null_bit)
164
if (record[column->null_pos] & column->null_bit)
166
/* Skip all NULL values */
171
src_offset= column->offset;
172
if (column->type == DRIZZLE_TYPE_VARCHAR)
174
uint32_t pack_length;
176
/* >= 5.0.3 true VARCHAR */
178
/* Make sure to copy length indicator and actuals string bytes */
179
pack_length= column->length_bytes;
180
length= pack_length + (pack_length == 1 ?
181
(uint) *(unsigned char*) (record + src_offset) : uint2korr(record + src_offset));
185
length= column->length;
192
to_copy= info->recordspace.chunk_dataspace_length - dst_offset;
195
/* Jump to the next chunk */
196
/*dump_chunk(info, curr_chunk);*/
197
curr_chunk= *((unsigned char**) (curr_chunk + info->recordspace.offset_link));
202
to_copy= min(length, to_copy);
206
if (memcmp(curr_chunk + dst_offset, record + src_offset, (size_t) to_copy))
213
memcpy(curr_chunk + dst_offset, record + src_offset, (size_t) to_copy);
216
src_offset+= to_copy;
217
dst_offset+= to_copy;
222
/*dump_chunk(info, curr_chunk);*/
228
Stores record in the heap table chunks
230
Copies data from original unpacked record into the preallocated chunkset
232
@param info the hosting table
233
@param record the record in standard unpacked format
234
@param pos the target chunkset
237
void hp_copy_record_data_to_chunkset(HP_SHARE *info, const unsigned char *record, unsigned char *pos)
240
hp_process_record_data_to_chunkset(info, record, pos, 0);
247
Macro to switch curr_chunk to the next chunk in the chunkset and reset src_offset
249
#define SWITCH_TO_NEXT_CHUNK_FOR_READ(info, curr_chunk, src_offset) \
251
curr_chunk= *((unsigned char**) (curr_chunk + info->recordspace.offset_link)); \
253
/*dump_chunk(info, curr_chunk);*/ \
258
Copies record data from storage to unpacked record format
260
Copies data from chunkset into its original unpacked record
262
@param info the hosting table
263
@param[out] record the target record in standard unpacked format
264
@param pos the source chunkset
267
void hp_extract_record(HP_SHARE *info, unsigned char *record, const unsigned char *pos)
269
uint32_t i, src_offset;
270
const unsigned char* curr_chunk= pos;
273
/*if (info->is_variable_size)
275
dump_chunk(info, curr_chunk);
278
memcpy(record, curr_chunk, (size_t) info->fixed_data_length);
280
if (!info->recordspace.is_variable_size)
282
/* Nothing more to copy */
286
src_offset= info->fixed_data_length;
288
for (i= info->fixed_column_count; i < info->column_count; i++)
290
uint32_t dst_offset, length, is_null = 0;
292
HP_COLUMNDEF* column= info->column_defs + i;
294
if (column->null_bit)
296
if (record[column->null_pos] & column->null_bit)
302
dst_offset= column->offset;
303
if (column->type == DRIZZLE_TYPE_VARCHAR)
305
uint32_t pack_length, byte1, byte2;
307
/* >= 5.0.3 true VARCHAR */
311
/* TODO: is memset really needed? */
312
memset(record + column->offset, 0, column->length);
316
pack_length= column->length_bytes;
318
if (src_offset == info->recordspace.chunk_dataspace_length)
320
SWITCH_TO_NEXT_CHUNK_FOR_READ(info, curr_chunk, src_offset);
322
byte1= *(unsigned char*) (curr_chunk + src_offset++);
323
*(record + dst_offset++)= byte1;
325
if (pack_length == 1)
331
if (src_offset == info->recordspace.chunk_dataspace_length)
333
SWITCH_TO_NEXT_CHUNK_FOR_READ(info, curr_chunk, src_offset);
335
byte2= *(unsigned char*) (curr_chunk + src_offset++);
336
*(record + dst_offset++)= byte2;
338
/* We copy byte-by-byte and then use uint2korr to combine bytes in the right order */
339
length= uint2korr(record + dst_offset - 2);
346
/* TODO: is memset really needed? */
347
memset(record + column->offset, 0, column->length);
351
length= column->length;
358
to_copy= info->recordspace.chunk_dataspace_length - src_offset;
361
SWITCH_TO_NEXT_CHUNK_FOR_READ(info, curr_chunk, src_offset);
362
to_copy= info->recordspace.chunk_dataspace_length;
365
to_copy= min(length, to_copy);
367
memcpy(record + dst_offset, curr_chunk + src_offset, (size_t) to_copy);
368
src_offset+= to_copy;
369
dst_offset+= to_copy;