~ubuntu-branches/ubuntu/saucy/drizzle/saucy-proposed

« back to all changes in this revision

Viewing changes to plugin/heap/hp_record.cc

  • Committer: Bazaar Package Importer
  • Author(s): Monty Taylor
  • Date: 2010-03-18 12:12:31 UTC
  • Revision ID: james.westby@ubuntu.com-20100318121231-k6g1xe6cshbwa0f8
Tags: upstream-2010.03.1347
ImportĀ upstreamĀ versionĀ 2010.03.1347

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2000-2002 MySQL AB
 
2
   Copyright (C) 2008 eBay, Inc
 
3
 
 
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.
 
7
 
 
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.
 
12
 
 
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 */
 
16
 
 
17
/* Implements various base record-related functions, such as encode and decode into chunks */
 
18
 
 
19
#include "heap_priv.h"
 
20
 
 
21
#include <drizzled/common.h>
 
22
 
 
23
#include <string.h>
 
24
#include <algorithm>
 
25
 
 
26
using namespace std;
 
27
using namespace drizzled;
 
28
 
 
29
/**
 
30
  Calculate size of the record for the purpose of storing in chunks
 
31
 
 
32
  Walk through the fields of the record and calculates the exact space
 
33
  needed in chunks as well the the total chunk count
 
34
 
 
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
 
38
 
 
39
  @return The size of the required storage in bytes
 
40
*/
 
41
 
 
42
uint32_t hp_get_encoded_data_length(HP_SHARE *info, const unsigned char *record, uint32_t *chunk_count)
 
43
{
 
44
  uint32_t i, dst_offset;
 
45
 
 
46
  dst_offset= info->fixed_data_length;
 
47
 
 
48
  if (!info->recordspace.is_variable_size)
 
49
  {
 
50
    /* Nothing more to copy */
 
51
    *chunk_count= 1;
 
52
    return dst_offset;
 
53
  }
 
54
 
 
55
  for (i= info->fixed_column_count; i < info->column_count; i++)
 
56
  {
 
57
    uint32_t src_offset, length;
 
58
 
 
59
    HP_COLUMNDEF* column= info->column_defs + i;
 
60
 
 
61
    if (column->null_bit)
 
62
    {
 
63
      if (record[column->null_pos] & column->null_bit)
 
64
      {
 
65
        /* Skip all NULL values */
 
66
        continue;
 
67
      }
 
68
    }
 
69
 
 
70
    src_offset= column->offset;
 
71
    if (column->type == DRIZZLE_TYPE_VARCHAR)
 
72
    {
 
73
      uint32_t pack_length;
 
74
 
 
75
      /* >= 5.0.3 true VARCHAR */
 
76
 
 
77
      pack_length= column->length_bytes;
 
78
      length= pack_length + (pack_length == 1 ?
 
79
        (uint) *(unsigned char*) (record + src_offset) : uint2korr(record + src_offset));
 
80
    }
 
81
    else
 
82
    {
 
83
      length= column->length;
 
84
    }
 
85
 
 
86
    dst_offset+= length;
 
87
  }
 
88
 
 
89
  *chunk_count= get_chunk_count(&info->recordspace, dst_offset);
 
90
 
 
91
  return dst_offset;
 
92
}
 
93
 
 
94
 
 
95
/*static void dump_chunk(HP_SHARE *info, const unsigned char* curr_chunk)
 
96
{
 
97
  uint32_t i;
 
98
  fprintf(stdout, "Chunk dump at 0x%lx: ", (long)curr_chunk);
 
99
  for (i= 0; i < info->chunk_dataspace_length; i++)
 
100
  {
 
101
    uint32_t b= *((unsigned char*)(curr_chunk + i));
 
102
    if (b < 0x10)
 
103
    {
 
104
      fprintf(stdout, "0");
 
105
    }
 
106
    fprintf(stdout, "%lx ", (long)b);
 
107
  }
 
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))));
 
111
}*/
 
112
 
 
113
 
 
114
/**
 
115
  Encodes or compares record
 
116
 
 
117
  Copies data from original unpacked record into the preallocated chunkset,
 
118
  or performs data comparison
 
119
 
 
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
 
124
 
 
125
  @return  Status of comparison
 
126
    @retval  non-zero  if comparison fond data differences
 
127
    @retval  zero      otherwise
 
128
*/
 
129
 
 
130
uint32_t hp_process_record_data_to_chunkset(HP_SHARE *info, const unsigned char *record,
 
131
                                      unsigned char *pos, uint32_t is_compare)
 
132
{
 
133
  uint32_t i, dst_offset;
 
134
  unsigned char* curr_chunk= pos;
 
135
 
 
136
  if (is_compare)
 
137
  {
 
138
    if (memcmp(curr_chunk, record, (size_t) info->fixed_data_length))
 
139
    {
 
140
      return 1;
 
141
    }
 
142
  }
 
143
  else
 
144
  {
 
145
    memcpy(curr_chunk, record, (size_t) info->fixed_data_length);
 
146
  }
 
147
 
 
148
  if (!info->recordspace.is_variable_size)
 
149
  {
 
150
    /* Nothing more to copy */
 
151
    return 0;
 
152
  }
 
153
 
 
154
  dst_offset= info->fixed_data_length;
 
155
 
 
156
  for (i= info->fixed_column_count; i < info->column_count; i++)
 
157
  {
 
158
    uint32_t src_offset, length;
 
159
 
 
160
    HP_COLUMNDEF* column= info->column_defs + i;
 
161
 
 
162
    if (column->null_bit)
 
163
    {
 
164
      if (record[column->null_pos] & column->null_bit)
 
165
      {
 
166
        /* Skip all NULL values */
 
167
        continue;
 
168
      }
 
169
    }
 
170
 
 
171
    src_offset= column->offset;
 
172
    if (column->type == DRIZZLE_TYPE_VARCHAR)
 
173
    {
 
174
      uint32_t pack_length;
 
175
 
 
176
      /* >= 5.0.3 true VARCHAR */
 
177
 
 
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));
 
182
    }
 
183
    else
 
184
    {
 
185
      length= column->length;
 
186
    }
 
187
 
 
188
    while (length > 0)
 
189
    {
 
190
      uint32_t to_copy;
 
191
 
 
192
      to_copy= info->recordspace.chunk_dataspace_length - dst_offset;
 
193
      if (to_copy == 0)
 
194
      {
 
195
        /* Jump to the next chunk */
 
196
        /*dump_chunk(info, curr_chunk);*/
 
197
        curr_chunk= *((unsigned char**) (curr_chunk + info->recordspace.offset_link));
 
198
        dst_offset= 0;
 
199
        continue;
 
200
      }
 
201
 
 
202
      to_copy= min(length, to_copy);
 
203
 
 
204
      if (is_compare)
 
205
      {
 
206
        if (memcmp(curr_chunk + dst_offset, record + src_offset, (size_t) to_copy))
 
207
        {
 
208
          return 1;
 
209
        }
 
210
      }
 
211
      else
 
212
      {
 
213
        memcpy(curr_chunk + dst_offset, record + src_offset, (size_t) to_copy);
 
214
      }
 
215
 
 
216
      src_offset+= to_copy;
 
217
      dst_offset+= to_copy;
 
218
      length-= to_copy;
 
219
    }
 
220
  }
 
221
 
 
222
  /*dump_chunk(info, curr_chunk);*/
 
223
  return 0;
 
224
}
 
225
 
 
226
 
 
227
/**
 
228
  Stores record in the heap table chunks
 
229
 
 
230
  Copies data from original unpacked record into the preallocated chunkset
 
231
 
 
232
  @param  info         the hosting table
 
233
  @param  record       the record in standard unpacked format
 
234
  @param  pos          the target chunkset
 
235
*/
 
236
 
 
237
void hp_copy_record_data_to_chunkset(HP_SHARE *info, const unsigned char *record, unsigned char *pos)
 
238
{
 
239
 
 
240
  hp_process_record_data_to_chunkset(info, record, pos, 0);
 
241
 
 
242
  return;
 
243
}
 
244
 
 
245
 
 
246
/*
 
247
  Macro to switch curr_chunk to the next chunk in the chunkset and reset src_offset
 
248
*/
 
249
#define SWITCH_TO_NEXT_CHUNK_FOR_READ(info, curr_chunk, src_offset) \
 
250
      { \
 
251
        curr_chunk= *((unsigned char**) (curr_chunk + info->recordspace.offset_link)); \
 
252
        src_offset= 0; \
 
253
        /*dump_chunk(info, curr_chunk);*/ \
 
254
      }
 
255
 
 
256
 
 
257
/**
 
258
  Copies record data from storage to unpacked record format
 
259
 
 
260
  Copies data from chunkset into its original unpacked record
 
261
 
 
262
  @param       info         the hosting table
 
263
  @param[out]  record       the target record in standard unpacked format
 
264
  @param       pos          the source chunkset
 
265
*/
 
266
 
 
267
void hp_extract_record(HP_SHARE *info, unsigned char *record, const unsigned char *pos)
 
268
{
 
269
  uint32_t i, src_offset;
 
270
  const unsigned char* curr_chunk= pos;
 
271
 
 
272
 
 
273
  /*if (info->is_variable_size)
 
274
  {
 
275
    dump_chunk(info, curr_chunk);
 
276
  }*/
 
277
 
 
278
  memcpy(record, curr_chunk, (size_t) info->fixed_data_length);
 
279
 
 
280
  if (!info->recordspace.is_variable_size)
 
281
  {
 
282
    /* Nothing more to copy */
 
283
    return;
 
284
  }
 
285
 
 
286
  src_offset= info->fixed_data_length;
 
287
 
 
288
  for (i= info->fixed_column_count; i < info->column_count; i++)
 
289
  {
 
290
    uint32_t dst_offset, length, is_null = 0;
 
291
 
 
292
    HP_COLUMNDEF* column= info->column_defs + i;
 
293
 
 
294
    if (column->null_bit)
 
295
    {
 
296
      if (record[column->null_pos] & column->null_bit)
 
297
      {
 
298
        is_null = 1;
 
299
      }
 
300
    }
 
301
 
 
302
    dst_offset= column->offset;
 
303
    if (column->type == DRIZZLE_TYPE_VARCHAR)
 
304
    {
 
305
      uint32_t pack_length, byte1, byte2;
 
306
 
 
307
      /* >= 5.0.3 true VARCHAR */
 
308
 
 
309
      if (is_null)
 
310
      {
 
311
        /* TODO: is memset really needed? */
 
312
        memset(record + column->offset, 0, column->length);
 
313
        continue;
 
314
      }
 
315
 
 
316
      pack_length= column->length_bytes;
 
317
 
 
318
      if (src_offset == info->recordspace.chunk_dataspace_length)
 
319
      {
 
320
        SWITCH_TO_NEXT_CHUNK_FOR_READ(info, curr_chunk, src_offset);
 
321
      }
 
322
      byte1= *(unsigned char*) (curr_chunk + src_offset++);
 
323
      *(record + dst_offset++)= byte1;
 
324
 
 
325
      if (pack_length == 1)
 
326
      {
 
327
        length= byte1;
 
328
      }
 
329
      else
 
330
      {
 
331
        if (src_offset == info->recordspace.chunk_dataspace_length)
 
332
        {
 
333
          SWITCH_TO_NEXT_CHUNK_FOR_READ(info, curr_chunk, src_offset);
 
334
        }
 
335
        byte2= *(unsigned char*) (curr_chunk + src_offset++);
 
336
        *(record + dst_offset++)= byte2;
 
337
 
 
338
        /* We copy byte-by-byte and then use uint2korr to combine bytes in the right order */
 
339
        length= uint2korr(record + dst_offset - 2);
 
340
      }
 
341
    }
 
342
    else
 
343
    {
 
344
      if (is_null)
 
345
      {
 
346
        /* TODO: is memset really needed? */
 
347
        memset(record + column->offset, 0, column->length);
 
348
        continue;
 
349
      }
 
350
 
 
351
      length= column->length;
 
352
    }
 
353
 
 
354
    while (length > 0)
 
355
    {
 
356
      uint32_t to_copy;
 
357
 
 
358
      to_copy= info->recordspace.chunk_dataspace_length - src_offset;
 
359
      if (to_copy == 0)
 
360
      {
 
361
        SWITCH_TO_NEXT_CHUNK_FOR_READ(info, curr_chunk, src_offset);
 
362
        to_copy= info->recordspace.chunk_dataspace_length;
 
363
      }
 
364
 
 
365
      to_copy= min(length, to_copy);
 
366
 
 
367
      memcpy(record + dst_offset, curr_chunk + src_offset, (size_t) to_copy);
 
368
      src_offset+= to_copy;
 
369
      dst_offset+= to_copy;
 
370
      length-= to_copy;
 
371
    }
 
372
  }
 
373
 
 
374
  return;
 
375
}