~drizzle-trunk/drizzle/development

244.1.1 by Harrison Fisk
Port Ebay/Google memory storage engine variable width columns.
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
1130.3.28 by Monty Taylor
Moved heapdef.h and myisamdef.h to *_priv.h for easier filtering for include guard check.
19
#include "heap_priv.h"
612.2.13 by Monty Taylor
Work on removing global.h from headers that should be installed.
20
543 by Monty Taylor
Renamed drizzle_common again. Removed sql_common. (empty)
21
#include <drizzled/common.h>
244.1.1 by Harrison Fisk
Port Ebay/Google memory storage engine variable width columns.
22
612.2.13 by Monty Taylor
Work on removing global.h from headers that should be installed.
23
#include <string.h>
1067.4.8 by Nathan Williams
Converted all usages of cmin/cmax in plugin directory to std::min/max.
24
#include <algorithm>
25
26
using namespace std;
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
27
using namespace drizzled;
244.1.1 by Harrison Fisk
Port Ebay/Google memory storage engine variable width columns.
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
482 by Brian Aker
Remove uint.
42
uint32_t hp_get_encoded_data_length(HP_SHARE *info, const unsigned char *record, uint32_t *chunk_count)
244.1.1 by Harrison Fisk
Port Ebay/Google memory storage engine variable width columns.
43
{
482 by Brian Aker
Remove uint.
44
  uint32_t i, dst_offset;
244.1.1 by Harrison Fisk
Port Ebay/Google memory storage engine variable width columns.
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
  {
482 by Brian Aker
Remove uint.
57
    uint32_t src_offset, length;
244.1.1 by Harrison Fisk
Port Ebay/Google memory storage engine variable width columns.
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
    {
482 by Brian Aker
Remove uint.
73
      uint32_t pack_length;
244.1.1 by Harrison Fisk
Port Ebay/Google memory storage engine variable width columns.
74
75
      /* >= 5.0.3 true VARCHAR */
76
77
      pack_length= column->length_bytes;
78
      length= pack_length + (pack_length == 1 ?
481 by Brian Aker
Remove all of uchar.
79
        (uint) *(unsigned char*) (record + src_offset) : uint2korr(record + src_offset));
244.1.1 by Harrison Fisk
Port Ebay/Google memory storage engine variable width columns.
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
481 by Brian Aker
Remove all of uchar.
95
/*static void dump_chunk(HP_SHARE *info, const unsigned char* curr_chunk)
244.1.1 by Harrison Fisk
Port Ebay/Google memory storage engine variable width columns.
96
{
482 by Brian Aker
Remove uint.
97
  uint32_t i;
244.1.1 by Harrison Fisk
Port Ebay/Google memory storage engine variable width columns.
98
  fprintf(stdout, "Chunk dump at 0x%lx: ", (long)curr_chunk);
99
  for (i= 0; i < info->chunk_dataspace_length; i++)
100
  {
482 by Brian Aker
Remove uint.
101
    uint32_t b= *((unsigned char*)(curr_chunk + i));
244.1.1 by Harrison Fisk
Port Ebay/Google memory storage engine variable width columns.
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",
481 by Brian Aker
Remove all of uchar.
109
    (long)(*((unsigned char**) (curr_chunk + info->offset_link))),
110
    (uint)(*((unsigned char*) (curr_chunk + info->offset_status))));
244.1.1 by Harrison Fisk
Port Ebay/Google memory storage engine variable width columns.
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
482 by Brian Aker
Remove uint.
130
uint32_t hp_process_record_data_to_chunkset(HP_SHARE *info, const unsigned char *record,
131
                                      unsigned char *pos, uint32_t is_compare)
244.1.1 by Harrison Fisk
Port Ebay/Google memory storage engine variable width columns.
132
{
482 by Brian Aker
Remove uint.
133
  uint32_t i, dst_offset;
481 by Brian Aker
Remove all of uchar.
134
  unsigned char* curr_chunk= pos;
244.1.1 by Harrison Fisk
Port Ebay/Google memory storage engine variable width columns.
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
  {
482 by Brian Aker
Remove uint.
158
    uint32_t src_offset, length;
244.1.1 by Harrison Fisk
Port Ebay/Google memory storage engine variable width columns.
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
    {
482 by Brian Aker
Remove uint.
174
      uint32_t pack_length;
244.1.1 by Harrison Fisk
Port Ebay/Google memory storage engine variable width columns.
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 ?
481 by Brian Aker
Remove all of uchar.
181
        (uint) *(unsigned char*) (record + src_offset) : uint2korr(record + src_offset));
244.1.1 by Harrison Fisk
Port Ebay/Google memory storage engine variable width columns.
182
    }
183
    else
184
    {
185
      length= column->length;
186
    }
187
188
    while (length > 0)
189
    {
482 by Brian Aker
Remove uint.
190
      uint32_t to_copy;
244.1.1 by Harrison Fisk
Port Ebay/Google memory storage engine variable width columns.
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);*/
481 by Brian Aker
Remove all of uchar.
197
        curr_chunk= *((unsigned char**) (curr_chunk + info->recordspace.offset_link));
244.1.1 by Harrison Fisk
Port Ebay/Google memory storage engine variable width columns.
198
        dst_offset= 0;
199
        continue;
200
      }
201
1067.4.8 by Nathan Williams
Converted all usages of cmin/cmax in plugin directory to std::min/max.
202
      to_copy= min(length, to_copy);
244.1.1 by Harrison Fisk
Port Ebay/Google memory storage engine variable width columns.
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
481 by Brian Aker
Remove all of uchar.
237
void hp_copy_record_data_to_chunkset(HP_SHARE *info, const unsigned char *record, unsigned char *pos)
244.1.1 by Harrison Fisk
Port Ebay/Google memory storage engine variable width columns.
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
      { \
481 by Brian Aker
Remove all of uchar.
251
        curr_chunk= *((unsigned char**) (curr_chunk + info->recordspace.offset_link)); \
244.1.1 by Harrison Fisk
Port Ebay/Google memory storage engine variable width columns.
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
481 by Brian Aker
Remove all of uchar.
267
void hp_extract_record(HP_SHARE *info, unsigned char *record, const unsigned char *pos)
244.1.1 by Harrison Fisk
Port Ebay/Google memory storage engine variable width columns.
268
{
482 by Brian Aker
Remove uint.
269
  uint32_t i, src_offset;
481 by Brian Aker
Remove all of uchar.
270
  const unsigned char* curr_chunk= pos;
244.1.1 by Harrison Fisk
Port Ebay/Google memory storage engine variable width columns.
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
  {
482 by Brian Aker
Remove uint.
290
    uint32_t dst_offset, length, is_null = 0;
244.1.1 by Harrison Fisk
Port Ebay/Google memory storage engine variable width columns.
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
    {
482 by Brian Aker
Remove uint.
305
      uint32_t pack_length, byte1, byte2;
244.1.1 by Harrison Fisk
Port Ebay/Google memory storage engine variable width columns.
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
      }
481 by Brian Aker
Remove all of uchar.
322
      byte1= *(unsigned char*) (curr_chunk + src_offset++);
244.1.1 by Harrison Fisk
Port Ebay/Google memory storage engine variable width columns.
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
        }
481 by Brian Aker
Remove all of uchar.
335
        byte2= *(unsigned char*) (curr_chunk + src_offset++);
244.1.1 by Harrison Fisk
Port Ebay/Google memory storage engine variable width columns.
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
    {
482 by Brian Aker
Remove uint.
356
      uint32_t to_copy;
244.1.1 by Harrison Fisk
Port Ebay/Google memory storage engine variable width columns.
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
1067.4.8 by Nathan Williams
Converted all usages of cmin/cmax in plugin directory to std::min/max.
365
      to_copy= min(length, to_copy);
244.1.1 by Harrison Fisk
Port Ebay/Google memory storage engine variable width columns.
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
}