~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/innobase/data/data0data.c

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/************************************************************************
 
2
SQL data field and tuple
 
3
 
 
4
(c) 1994-1996 Innobase Oy
 
5
 
 
6
Created 5/30/1994 Heikki Tuuri
 
7
*************************************************************************/
 
8
 
 
9
#include "data0data.h"
 
10
 
 
11
#ifdef UNIV_NONINL
 
12
#include "data0data.ic"
 
13
#endif
 
14
 
 
15
#include "rem0rec.h"
 
16
#include "rem0cmp.h"
 
17
#include "page0page.h"
 
18
#include "dict0dict.h"
 
19
#include "btr0cur.h"
 
20
 
 
21
#include <ctype.h>
 
22
 
 
23
#ifdef UNIV_DEBUG
 
24
byte    data_error;     /* data pointers of tuple fields are initialized
 
25
                        to point here for error checking */
 
26
 
 
27
ulint   data_dummy;     /* this is used to fool the compiler in
 
28
                        dtuple_validate */
 
29
#endif /* UNIV_DEBUG */
 
30
 
 
31
/* Some non-inlined functions used in the MySQL interface: */
 
32
void
 
33
dfield_set_data_noninline(
 
34
        dfield_t*       field,  /* in: field */
 
35
        void*           data,   /* in: data */
 
36
        ulint           len)    /* in: length or UNIV_SQL_NULL */
 
37
{
 
38
        dfield_set_data(field, data, len);
 
39
}
 
40
void*
 
41
dfield_get_data_noninline(
 
42
        dfield_t* field)        /* in: field */
 
43
{
 
44
        return(dfield_get_data(field));
 
45
}
 
46
ulint
 
47
dfield_get_len_noninline(
 
48
        dfield_t* field)        /* in: field */
 
49
{
 
50
        return(dfield_get_len(field));
 
51
}
 
52
ulint
 
53
dtuple_get_n_fields_noninline(
 
54
        dtuple_t*       tuple)  /* in: tuple */
 
55
{
 
56
        return(dtuple_get_n_fields(tuple));
 
57
}
 
58
dfield_t*
 
59
dtuple_get_nth_field_noninline(
 
60
        dtuple_t*       tuple,  /* in: tuple */
 
61
        ulint           n)      /* in: index of field */
 
62
{
 
63
        return(dtuple_get_nth_field(tuple, n));
 
64
}
 
65
 
 
66
/*************************************************************************
 
67
Tests if dfield data length and content is equal to the given. */
 
68
 
 
69
ibool
 
70
dfield_data_is_binary_equal(
 
71
/*========================*/
 
72
                                /* out: TRUE if equal */
 
73
        dfield_t*       field,  /* in: field */
 
74
        ulint           len,    /* in: data length or UNIV_SQL_NULL */
 
75
        byte*           data)   /* in: data */
 
76
{
 
77
        if (len != field->len) {
 
78
 
 
79
                return(FALSE);
 
80
        }
 
81
 
 
82
        if (len == UNIV_SQL_NULL) {
 
83
 
 
84
                return(TRUE);
 
85
        }
 
86
 
 
87
        if (0 != ut_memcmp(field->data, data, len)) {
 
88
 
 
89
                return(FALSE);
 
90
        }
 
91
 
 
92
        return(TRUE);
 
93
}
 
94
 
 
95
/****************************************************************
 
96
Returns TRUE if lengths of two dtuples are equal and respective data fields
 
97
in them are equal when compared with collation in char fields (not as binary
 
98
strings). */
 
99
 
 
100
ibool
 
101
dtuple_datas_are_ordering_equal(
 
102
/*============================*/
 
103
                                /* out: TRUE if length and fieds are equal
 
104
                                when compared with cmp_data_data:
 
105
                                NOTE: in character type fields some letters
 
106
                                are identified with others! (collation) */
 
107
        dtuple_t*       tuple1, /* in: tuple 1 */
 
108
        dtuple_t*       tuple2) /* in: tuple 2 */
 
109
{
 
110
        dfield_t*       field1;
 
111
        dfield_t*       field2;
 
112
        ulint           n_fields;
 
113
        ulint           i;
 
114
 
 
115
        ut_ad(tuple1 && tuple2);
 
116
        ut_ad(tuple1->magic_n == DATA_TUPLE_MAGIC_N);
 
117
        ut_ad(tuple2->magic_n == DATA_TUPLE_MAGIC_N);
 
118
        ut_ad(dtuple_check_typed(tuple1));
 
119
        ut_ad(dtuple_check_typed(tuple2));
 
120
 
 
121
        n_fields = dtuple_get_n_fields(tuple1);
 
122
 
 
123
        if (n_fields != dtuple_get_n_fields(tuple2)) {
 
124
 
 
125
                return(FALSE);
 
126
        }
 
127
 
 
128
        for (i = 0; i < n_fields; i++) {
 
129
 
 
130
                field1 = dtuple_get_nth_field(tuple1, i);
 
131
                field2 = dtuple_get_nth_field(tuple2, i);
 
132
 
 
133
                if (0 != cmp_dfield_dfield(field1, field2)) {
 
134
 
 
135
                        return(FALSE);
 
136
                }
 
137
        }
 
138
 
 
139
        return(TRUE);
 
140
}
 
141
 
 
142
/*************************************************************************
 
143
Creates a dtuple for use in MySQL. */
 
144
 
 
145
dtuple_t*
 
146
dtuple_create_for_mysql(
 
147
/*====================*/
 
148
                                /* out, own created dtuple */
 
149
        void**  heap,           /* out: created memory heap */
 
150
        ulint   n_fields)       /* in: number of fields */
 
151
{
 
152
        *heap = (void*)mem_heap_create(500);
 
153
 
 
154
        return(dtuple_create(*((mem_heap_t**)heap), n_fields));
 
155
}
 
156
 
 
157
/*************************************************************************
 
158
Frees a dtuple used in MySQL. */
 
159
 
 
160
void
 
161
dtuple_free_for_mysql(
 
162
/*==================*/
 
163
        void*   heap) /* in: memory heap where tuple was created */
 
164
{
 
165
        mem_heap_free((mem_heap_t*)heap);
 
166
}
 
167
 
 
168
/*************************************************************************
 
169
Sets number of fields used in a tuple. Normally this is set in
 
170
dtuple_create, but if you want later to set it smaller, you can use this. */
 
171
 
 
172
void
 
173
dtuple_set_n_fields(
 
174
/*================*/
 
175
        dtuple_t*       tuple,          /* in: tuple */
 
176
        ulint           n_fields)       /* in: number of fields */
 
177
{
 
178
        ut_ad(tuple);
 
179
 
 
180
        tuple->n_fields = n_fields;
 
181
        tuple->n_fields_cmp = n_fields;
 
182
}
 
183
 
 
184
/**************************************************************
 
185
Checks that a data field is typed. */
 
186
static
 
187
ibool
 
188
dfield_check_typed_no_assert(
 
189
/*=========================*/
 
190
                                /* out: TRUE if ok */
 
191
        dfield_t*       field)  /* in: data field */
 
192
{
 
193
        if (dfield_get_type(field)->mtype > DATA_MYSQL
 
194
            || dfield_get_type(field)->mtype < DATA_VARCHAR) {
 
195
 
 
196
                fprintf(stderr,
 
197
                        "InnoDB: Error: data field type %lu, len %lu\n",
 
198
                        (ulong) dfield_get_type(field)->mtype,
 
199
                        (ulong) dfield_get_len(field));
 
200
                return(FALSE);
 
201
        }
 
202
 
 
203
        return(TRUE);
 
204
}
 
205
 
 
206
/**************************************************************
 
207
Checks that a data tuple is typed. */
 
208
 
 
209
ibool
 
210
dtuple_check_typed_no_assert(
 
211
/*=========================*/
 
212
                                /* out: TRUE if ok */
 
213
        dtuple_t*       tuple)  /* in: tuple */
 
214
{
 
215
        dfield_t*       field;
 
216
        ulint           i;
 
217
 
 
218
        if (dtuple_get_n_fields(tuple) > REC_MAX_N_FIELDS) {
 
219
                fprintf(stderr,
 
220
                        "InnoDB: Error: index entry has %lu fields\n",
 
221
                        (ulong) dtuple_get_n_fields(tuple));
 
222
dump:
 
223
                fputs("InnoDB: Tuple contents: ", stderr);
 
224
                dtuple_print(stderr, tuple);
 
225
                putc('\n', stderr);
 
226
 
 
227
                return(FALSE);
 
228
        }
 
229
 
 
230
        for (i = 0; i < dtuple_get_n_fields(tuple); i++) {
 
231
 
 
232
                field = dtuple_get_nth_field(tuple, i);
 
233
 
 
234
                if (!dfield_check_typed_no_assert(field)) {
 
235
                        goto dump;
 
236
                }
 
237
        }
 
238
 
 
239
        return(TRUE);
 
240
}
 
241
 
 
242
/**************************************************************
 
243
Checks that a data field is typed. Asserts an error if not. */
 
244
 
 
245
ibool
 
246
dfield_check_typed(
 
247
/*===============*/
 
248
                                /* out: TRUE if ok */
 
249
        dfield_t*       field)  /* in: data field */
 
250
{
 
251
        if (dfield_get_type(field)->mtype > DATA_MYSQL
 
252
            || dfield_get_type(field)->mtype < DATA_VARCHAR) {
 
253
 
 
254
                fprintf(stderr,
 
255
                        "InnoDB: Error: data field type %lu, len %lu\n",
 
256
                        (ulong) dfield_get_type(field)->mtype,
 
257
                        (ulong) dfield_get_len(field));
 
258
 
 
259
                ut_error;
 
260
        }
 
261
 
 
262
        return(TRUE);
 
263
}
 
264
 
 
265
/**************************************************************
 
266
Checks that a data tuple is typed. Asserts an error if not. */
 
267
 
 
268
ibool
 
269
dtuple_check_typed(
 
270
/*===============*/
 
271
                                /* out: TRUE if ok */
 
272
        dtuple_t*       tuple)  /* in: tuple */
 
273
{
 
274
        dfield_t*       field;
 
275
        ulint           i;
 
276
 
 
277
        for (i = 0; i < dtuple_get_n_fields(tuple); i++) {
 
278
 
 
279
                field = dtuple_get_nth_field(tuple, i);
 
280
 
 
281
                ut_a(dfield_check_typed(field));
 
282
        }
 
283
 
 
284
        return(TRUE);
 
285
}
 
286
 
 
287
#ifdef UNIV_DEBUG
 
288
/**************************************************************
 
289
Validates the consistency of a tuple which must be complete, i.e,
 
290
all fields must have been set. */
 
291
 
 
292
ibool
 
293
dtuple_validate(
 
294
/*============*/
 
295
                                /* out: TRUE if ok */
 
296
        dtuple_t*       tuple)  /* in: tuple */
 
297
{
 
298
        dfield_t*       field;
 
299
        byte*           data;
 
300
        ulint           n_fields;
 
301
        ulint           len;
 
302
        ulint           i;
 
303
        ulint           j;
 
304
 
 
305
        ut_ad(tuple->magic_n == DATA_TUPLE_MAGIC_N);
 
306
 
 
307
        n_fields = dtuple_get_n_fields(tuple);
 
308
 
 
309
        /* We dereference all the data of each field to test
 
310
        for memory traps */
 
311
 
 
312
        for (i = 0; i < n_fields; i++) {
 
313
 
 
314
                field = dtuple_get_nth_field(tuple, i);
 
315
                len = dfield_get_len(field);
 
316
 
 
317
                if (len != UNIV_SQL_NULL) {
 
318
 
 
319
                        data = field->data;
 
320
 
 
321
                        for (j = 0; j < len; j++) {
 
322
 
 
323
                                data_dummy  += *data; /* fool the compiler not
 
324
                                                      to optimize out this
 
325
                                                      code */
 
326
                                data++;
 
327
                        }
 
328
                }
 
329
        }
 
330
 
 
331
        ut_a(dtuple_check_typed(tuple));
 
332
 
 
333
        return(TRUE);
 
334
}
 
335
#endif /* UNIV_DEBUG */
 
336
 
 
337
/*****************************************************************
 
338
Pretty prints a dfield value according to its data type. */
 
339
 
 
340
void
 
341
dfield_print(
 
342
/*=========*/
 
343
        dfield_t*       dfield)  /* in: dfield */
 
344
{
 
345
        byte*   data;
 
346
        ulint   len;
 
347
        ulint   mtype;
 
348
        ulint   i;
 
349
 
 
350
        len = dfield_get_len(dfield);
 
351
        data = dfield_get_data(dfield);
 
352
 
 
353
        if (len == UNIV_SQL_NULL) {
 
354
                fputs("NULL", stderr);
 
355
 
 
356
                return;
 
357
        }
 
358
 
 
359
        mtype = dtype_get_mtype(dfield_get_type(dfield));
 
360
 
 
361
        if ((mtype == DATA_CHAR) || (mtype == DATA_VARCHAR)) {
 
362
 
 
363
                for (i = 0; i < len; i++) {
 
364
                        int     c = *data++;
 
365
                        putc(isprint(c) ? c : ' ', stderr);
 
366
                }
 
367
        } else if (mtype == DATA_INT) {
 
368
                ut_a(len == 4); /* only works for 32-bit integers */
 
369
                fprintf(stderr, "%d", (int)mach_read_from_4(data));
 
370
        } else {
 
371
                ut_error;
 
372
        }
 
373
}
 
374
 
 
375
/*****************************************************************
 
376
Pretty prints a dfield value according to its data type. Also the hex string
 
377
is printed if a string contains non-printable characters. */
 
378
 
 
379
void
 
380
dfield_print_also_hex(
 
381
/*==================*/
 
382
        dfield_t*       dfield)  /* in: dfield */
 
383
{
 
384
        byte*   data;
 
385
        ulint   len;
 
386
        ulint   mtype;
 
387
        ulint   i;
 
388
        ibool   print_also_hex;
 
389
 
 
390
        len = dfield_get_len(dfield);
 
391
        data = dfield_get_data(dfield);
 
392
 
 
393
        if (len == UNIV_SQL_NULL) {
 
394
                fputs("NULL", stderr);
 
395
 
 
396
                return;
 
397
        }
 
398
 
 
399
        mtype = dtype_get_mtype(dfield_get_type(dfield));
 
400
 
 
401
        if ((mtype == DATA_CHAR) || (mtype == DATA_VARCHAR)) {
 
402
 
 
403
                print_also_hex = FALSE;
 
404
 
 
405
                for (i = 0; i < len; i++) {
 
406
                        int c = *data++;
 
407
                        if (!isprint(c)) {
 
408
                                print_also_hex = TRUE;
 
409
                                c = ' ';
 
410
                        }
 
411
                        putc(c, stderr);
 
412
                }
 
413
 
 
414
                if (!print_also_hex) {
 
415
 
 
416
                        return;
 
417
                }
 
418
 
 
419
                fputs(" Hex: ", stderr);
 
420
 
 
421
                data = dfield_get_data(dfield);
 
422
 
 
423
                for (i = 0; i < len; i++) {
 
424
                        fprintf(stderr, "%02lx", (ulint)*data);
 
425
 
 
426
                        data++;
 
427
                }
 
428
        } else if (mtype == DATA_INT) {
 
429
                ut_a(len == 4); /* only works for 32-bit integers */
 
430
                fprintf(stderr, "%d", (int)mach_read_from_4(data));
 
431
        } else {
 
432
                ut_error;
 
433
        }
 
434
}
 
435
 
 
436
/*****************************************************************
 
437
Print a dfield value using ut_print_buf. */
 
438
static
 
439
void
 
440
dfield_print_raw(
 
441
/*=============*/
 
442
        FILE*           f,              /* in: output stream */
 
443
        dfield_t*       dfield)         /* in: dfield */
 
444
{
 
445
        ulint   len     = dfield->len;
 
446
        if (len != UNIV_SQL_NULL) {
 
447
                ulint   print_len = ut_min(len, 1000);
 
448
                ut_print_buf(f, dfield->data, print_len);
 
449
                if (len != print_len) {
 
450
                        fprintf(f, "(total %lu bytes)", (ulong) len);
 
451
                }
 
452
        } else {
 
453
                fputs(" SQL NULL", f);
 
454
        }
 
455
}
 
456
 
 
457
/**************************************************************
 
458
The following function prints the contents of a tuple. */
 
459
 
 
460
void
 
461
dtuple_print(
 
462
/*=========*/
 
463
        FILE*           f,      /* in: output stream */
 
464
        dtuple_t*       tuple)  /* in: tuple */
 
465
{
 
466
        ulint           n_fields;
 
467
        ulint           i;
 
468
 
 
469
        n_fields = dtuple_get_n_fields(tuple);
 
470
 
 
471
        fprintf(f, "DATA TUPLE: %lu fields;\n", (ulong) n_fields);
 
472
 
 
473
        for (i = 0; i < n_fields; i++) {
 
474
                fprintf(f, " %lu:", (ulong) i);
 
475
 
 
476
                dfield_print_raw(f, dtuple_get_nth_field(tuple, i));
 
477
 
 
478
                putc(';', f);
 
479
        }
 
480
 
 
481
        putc('\n', f);
 
482
        ut_ad(dtuple_validate(tuple));
 
483
}
 
484
 
 
485
/******************************************************************
 
486
Moves parts of long fields in entry to the big record vector so that
 
487
the size of tuple drops below the maximum record size allowed in the
 
488
database. Moves data only from those fields which are not necessary
 
489
to determine uniquely the insertion place of the tuple in the index. */
 
490
 
 
491
big_rec_t*
 
492
dtuple_convert_big_rec(
 
493
/*===================*/
 
494
                                /* out, own: created big record vector,
 
495
                                NULL if we are not able to shorten
 
496
                                the entry enough, i.e., if there are
 
497
                                too many short fields in entry */
 
498
        dict_index_t*   index,  /* in: index */
 
499
        dtuple_t*       entry,  /* in: index entry */
 
500
        ulint*          ext_vec,/* in: array of externally stored fields,
 
501
                                or NULL: if a field already is externally
 
502
                                stored, then we cannot move it to the vector
 
503
                                this function returns */
 
504
        ulint           n_ext_vec)/* in: number of elements is ext_vec */
 
505
{
 
506
        mem_heap_t*     heap;
 
507
        big_rec_t*      vector;
 
508
        dfield_t*       dfield;
 
509
        ulint           size;
 
510
        ulint           n_fields;
 
511
        ulint           longest;
 
512
        ulint           longest_i               = ULINT_MAX;
 
513
        ibool           is_externally_stored;
 
514
        ulint           i;
 
515
        ulint           j;
 
516
 
 
517
        ut_a(dtuple_check_typed_no_assert(entry));
 
518
 
 
519
        size = rec_get_converted_size(index, entry);
 
520
 
 
521
        if (UNIV_UNLIKELY(size > 1000000000)) {
 
522
                fprintf(stderr,
 
523
                        "InnoDB: Warning: tuple size very big: %lu\n",
 
524
                        (ulong) size);
 
525
                fputs("InnoDB: Tuple contents: ", stderr);
 
526
                dtuple_print(stderr, entry);
 
527
                putc('\n', stderr);
 
528
        }
 
529
 
 
530
        heap = mem_heap_create(size + dtuple_get_n_fields(entry)
 
531
                               * sizeof(big_rec_field_t) + 1000);
 
532
 
 
533
        vector = mem_heap_alloc(heap, sizeof(big_rec_t));
 
534
 
 
535
        vector->heap = heap;
 
536
        vector->fields = mem_heap_alloc(heap, dtuple_get_n_fields(entry)
 
537
                                        * sizeof(big_rec_field_t));
 
538
 
 
539
        /* Decide which fields to shorten: the algorithm is to look for
 
540
        the longest field whose type is DATA_BLOB */
 
541
 
 
542
        n_fields = 0;
 
543
 
 
544
        while (rec_get_converted_size(index, entry)
 
545
               >= ut_min(page_get_free_space_of_empty(
 
546
                                 dict_table_is_comp(index->table)) / 2,
 
547
                         REC_MAX_DATA_SIZE)) {
 
548
 
 
549
                longest = 0;
 
550
                for (i = dict_index_get_n_unique_in_tree(index);
 
551
                     i < dtuple_get_n_fields(entry); i++) {
 
552
 
 
553
                        /* Skip over fields which already are externally
 
554
                        stored */
 
555
 
 
556
                        is_externally_stored = FALSE;
 
557
 
 
558
                        if (ext_vec) {
 
559
                                for (j = 0; j < n_ext_vec; j++) {
 
560
                                        if (ext_vec[j] == i) {
 
561
                                                is_externally_stored = TRUE;
 
562
                                        }
 
563
                                }
 
564
                        }
 
565
 
 
566
                        if (!is_externally_stored) {
 
567
 
 
568
                                dfield = dtuple_get_nth_field(entry, i);
 
569
 
 
570
                                if (dfield->len != UNIV_SQL_NULL
 
571
                                    && dfield->len > longest) {
 
572
 
 
573
                                        longest = dfield->len;
 
574
 
 
575
                                        longest_i = i;
 
576
                                }
 
577
                        }
 
578
                }
 
579
 
 
580
                /* We do not store externally fields which are smaller than
 
581
                DICT_MAX_INDEX_COL_LEN */
 
582
 
 
583
#if DICT_MAX_INDEX_COL_LEN <= REC_1BYTE_OFFS_LIMIT
 
584
# error "DICT_MAX_INDEX_COL_LEN <= REC_1BYTE_OFFS_LIMIT"
 
585
#endif
 
586
 
 
587
                if (longest < BTR_EXTERN_FIELD_REF_SIZE + 10
 
588
                    + DICT_MAX_INDEX_COL_LEN) {
 
589
                        /* Cannot shorten more */
 
590
 
 
591
                        mem_heap_free(heap);
 
592
 
 
593
                        return(NULL);
 
594
                }
 
595
 
 
596
                /* Move data from field longest_i to big rec vector;
 
597
                we do not let data size of the remaining entry
 
598
                drop below 128 which is the limit for the 2-byte
 
599
                offset storage format in a physical record. This
 
600
                we accomplish by storing 128 bytes of data in entry
 
601
                itself, and only the remaining part to big rec vec.
 
602
 
 
603
                We store the first bytes locally to the record. Then
 
604
                we can calculate all ordering fields in all indexes
 
605
                from locally stored data. */
 
606
 
 
607
                dfield = dtuple_get_nth_field(entry, longest_i);
 
608
                vector->fields[n_fields].field_no = longest_i;
 
609
 
 
610
                ut_a(dfield->len > DICT_MAX_INDEX_COL_LEN);
 
611
 
 
612
                vector->fields[n_fields].len = dfield->len
 
613
                        - DICT_MAX_INDEX_COL_LEN;
 
614
 
 
615
                vector->fields[n_fields].data = mem_heap_alloc(
 
616
                        heap, vector->fields[n_fields].len);
 
617
 
 
618
                /* Copy data (from the end of field) to big rec vector */
 
619
 
 
620
                ut_memcpy(vector->fields[n_fields].data,
 
621
                          ((byte*)dfield->data) + dfield->len
 
622
                          - vector->fields[n_fields].len,
 
623
                          vector->fields[n_fields].len);
 
624
                dfield->len = dfield->len - vector->fields[n_fields].len
 
625
                        + BTR_EXTERN_FIELD_REF_SIZE;
 
626
 
 
627
                /* Set the extern field reference in dfield to zero */
 
628
                memset(((byte*)dfield->data)
 
629
                       + dfield->len - BTR_EXTERN_FIELD_REF_SIZE,
 
630
                       0, BTR_EXTERN_FIELD_REF_SIZE);
 
631
                n_fields++;
 
632
        }
 
633
 
 
634
        vector->n_fields = n_fields;
 
635
        return(vector);
 
636
}
 
637
 
 
638
/******************************************************************
 
639
Puts back to entry the data stored in vector. Note that to ensure the
 
640
fields in entry can accommodate the data, vector must have been created
 
641
from entry with dtuple_convert_big_rec. */
 
642
 
 
643
void
 
644
dtuple_convert_back_big_rec(
 
645
/*========================*/
 
646
        dict_index_t*   index __attribute__((unused)),  /* in: index */
 
647
        dtuple_t*       entry,  /* in: entry whose data was put to vector */
 
648
        big_rec_t*      vector) /* in, own: big rec vector; it is
 
649
                                freed in this function */
 
650
{
 
651
        dfield_t*       dfield;
 
652
        ulint           i;
 
653
 
 
654
        for (i = 0; i < vector->n_fields; i++) {
 
655
 
 
656
                dfield = dtuple_get_nth_field(entry,
 
657
                                              vector->fields[i].field_no);
 
658
                /* Copy data from big rec vector */
 
659
 
 
660
                ut_memcpy(((byte*)dfield->data)
 
661
                          + dfield->len - BTR_EXTERN_FIELD_REF_SIZE,
 
662
                          vector->fields[i].data,
 
663
                          vector->fields[i].len);
 
664
                dfield->len = dfield->len + vector->fields[i].len
 
665
                        - BTR_EXTERN_FIELD_REF_SIZE;
 
666
        }
 
667
 
 
668
        mem_heap_free(vector->heap);
 
669
}
 
670
 
 
671
/******************************************************************
 
672
Frees the memory in a big rec vector. */
 
673
 
 
674
void
 
675
dtuple_big_rec_free(
 
676
/*================*/
 
677
        big_rec_t*      vector) /* in, own: big rec vector; it is
 
678
                                freed in this function */
 
679
{
 
680
        mem_heap_free(vector->heap);
 
681
}