~percona-dev/percona-innodb-plugin/percona-innodb-1.0

« back to all changes in this revision

Viewing changes to data/data0data.c

  • Committer: Vadim Tkachenko
  • Date: 2008-12-01 02:05:57 UTC
  • Revision ID: vadim@percona.com-20081201020557-p7k2m94mjtdg1a83
New rw-locks

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 "page0zip.h"
 
19
#include "dict0dict.h"
 
20
#include "btr0cur.h"
 
21
 
 
22
#include <ctype.h>
 
23
 
 
24
#ifdef UNIV_DEBUG
 
25
/* data pointers of tuple fields are initialized to point here
 
26
for error checking */
 
27
UNIV_INTERN byte        data_error;
 
28
 
 
29
/* this is used to fool the compiler in dtuple_validate */
 
30
UNIV_INTERN ulint       data_dummy;
 
31
#endif /* UNIV_DEBUG */
 
32
 
 
33
/*************************************************************************
 
34
Tests if dfield data length and content is equal to the given. */
 
35
UNIV_INTERN
 
36
ibool
 
37
dfield_data_is_binary_equal(
 
38
/*========================*/
 
39
                                /* out: TRUE if equal */
 
40
        const dfield_t* field,  /* in: field */
 
41
        ulint           len,    /* in: data length or UNIV_SQL_NULL */
 
42
        const byte*     data)   /* in: data */
 
43
{
 
44
        if (len != dfield_get_len(field)) {
 
45
 
 
46
                return(FALSE);
 
47
        }
 
48
 
 
49
        if (len == UNIV_SQL_NULL) {
 
50
 
 
51
                return(TRUE);
 
52
        }
 
53
 
 
54
        if (0 != memcmp(dfield_get_data(field), data, len)) {
 
55
 
 
56
                return(FALSE);
 
57
        }
 
58
 
 
59
        return(TRUE);
 
60
}
 
61
 
 
62
/****************************************************************
 
63
Compare two data tuples, respecting the collation of character fields. */
 
64
UNIV_INTERN
 
65
int
 
66
dtuple_coll_cmp(
 
67
/*============*/
 
68
                                /* out: 1, 0 , -1 if tuple1 is greater, equal,
 
69
                                less, respectively, than tuple2 */
 
70
        const dtuple_t* tuple1, /* in: tuple 1 */
 
71
        const dtuple_t* tuple2) /* in: tuple 2 */
 
72
{
 
73
        ulint   n_fields;
 
74
        ulint   i;
 
75
 
 
76
        ut_ad(tuple1 && tuple2);
 
77
        ut_ad(tuple1->magic_n == DATA_TUPLE_MAGIC_N);
 
78
        ut_ad(tuple2->magic_n == DATA_TUPLE_MAGIC_N);
 
79
        ut_ad(dtuple_check_typed(tuple1));
 
80
        ut_ad(dtuple_check_typed(tuple2));
 
81
 
 
82
        n_fields = dtuple_get_n_fields(tuple1);
 
83
 
 
84
        if (n_fields != dtuple_get_n_fields(tuple2)) {
 
85
 
 
86
                return(n_fields < dtuple_get_n_fields(tuple2) ? -1 : 1);
 
87
        }
 
88
 
 
89
        for (i = 0; i < n_fields; i++) {
 
90
                int             cmp;
 
91
                const dfield_t* field1  = dtuple_get_nth_field(tuple1, i);
 
92
                const dfield_t* field2  = dtuple_get_nth_field(tuple2, i);
 
93
 
 
94
                cmp = cmp_dfield_dfield(field1, field2);
 
95
 
 
96
                if (cmp) {
 
97
                        return(cmp);
 
98
                }
 
99
        }
 
100
 
 
101
        return(0);
 
102
}
 
103
 
 
104
/*************************************************************************
 
105
Sets number of fields used in a tuple. Normally this is set in
 
106
dtuple_create, but if you want later to set it smaller, you can use this. */
 
107
UNIV_INTERN
 
108
void
 
109
dtuple_set_n_fields(
 
110
/*================*/
 
111
        dtuple_t*       tuple,          /* in: tuple */
 
112
        ulint           n_fields)       /* in: number of fields */
 
113
{
 
114
        ut_ad(tuple);
 
115
 
 
116
        tuple->n_fields = n_fields;
 
117
        tuple->n_fields_cmp = n_fields;
 
118
}
 
119
 
 
120
/**************************************************************
 
121
Checks that a data field is typed. */
 
122
static
 
123
ibool
 
124
dfield_check_typed_no_assert(
 
125
/*=========================*/
 
126
                                /* out: TRUE if ok */
 
127
        const dfield_t* field)  /* in: data field */
 
128
{
 
129
        if (dfield_get_type(field)->mtype > DATA_MYSQL
 
130
            || dfield_get_type(field)->mtype < DATA_VARCHAR) {
 
131
 
 
132
                fprintf(stderr,
 
133
                        "InnoDB: Error: data field type %lu, len %lu\n",
 
134
                        (ulong) dfield_get_type(field)->mtype,
 
135
                        (ulong) dfield_get_len(field));
 
136
                return(FALSE);
 
137
        }
 
138
 
 
139
        return(TRUE);
 
140
}
 
141
 
 
142
/**************************************************************
 
143
Checks that a data tuple is typed. */
 
144
UNIV_INTERN
 
145
ibool
 
146
dtuple_check_typed_no_assert(
 
147
/*=========================*/
 
148
                                /* out: TRUE if ok */
 
149
        const dtuple_t* tuple)  /* in: tuple */
 
150
{
 
151
        const dfield_t* field;
 
152
        ulint           i;
 
153
 
 
154
        if (dtuple_get_n_fields(tuple) > REC_MAX_N_FIELDS) {
 
155
                fprintf(stderr,
 
156
                        "InnoDB: Error: index entry has %lu fields\n",
 
157
                        (ulong) dtuple_get_n_fields(tuple));
 
158
dump:
 
159
                fputs("InnoDB: Tuple contents: ", stderr);
 
160
                dtuple_print(stderr, tuple);
 
161
                putc('\n', stderr);
 
162
 
 
163
                return(FALSE);
 
164
        }
 
165
 
 
166
        for (i = 0; i < dtuple_get_n_fields(tuple); i++) {
 
167
 
 
168
                field = dtuple_get_nth_field(tuple, i);
 
169
 
 
170
                if (!dfield_check_typed_no_assert(field)) {
 
171
                        goto dump;
 
172
                }
 
173
        }
 
174
 
 
175
        return(TRUE);
 
176
}
 
177
 
 
178
/**************************************************************
 
179
Checks that a data field is typed. Asserts an error if not. */
 
180
UNIV_INTERN
 
181
ibool
 
182
dfield_check_typed(
 
183
/*===============*/
 
184
                                /* out: TRUE if ok */
 
185
        const dfield_t* field)  /* in: data field */
 
186
{
 
187
        if (dfield_get_type(field)->mtype > DATA_MYSQL
 
188
            || dfield_get_type(field)->mtype < DATA_VARCHAR) {
 
189
 
 
190
                fprintf(stderr,
 
191
                        "InnoDB: Error: data field type %lu, len %lu\n",
 
192
                        (ulong) dfield_get_type(field)->mtype,
 
193
                        (ulong) dfield_get_len(field));
 
194
 
 
195
                ut_error;
 
196
        }
 
197
 
 
198
        return(TRUE);
 
199
}
 
200
 
 
201
/**************************************************************
 
202
Checks that a data tuple is typed. Asserts an error if not. */
 
203
UNIV_INTERN
 
204
ibool
 
205
dtuple_check_typed(
 
206
/*===============*/
 
207
                                /* out: TRUE if ok */
 
208
        const dtuple_t* tuple)  /* in: tuple */
 
209
{
 
210
        const dfield_t* field;
 
211
        ulint           i;
 
212
 
 
213
        for (i = 0; i < dtuple_get_n_fields(tuple); i++) {
 
214
 
 
215
                field = dtuple_get_nth_field(tuple, i);
 
216
 
 
217
                ut_a(dfield_check_typed(field));
 
218
        }
 
219
 
 
220
        return(TRUE);
 
221
}
 
222
 
 
223
#ifdef UNIV_DEBUG
 
224
/**************************************************************
 
225
Validates the consistency of a tuple which must be complete, i.e,
 
226
all fields must have been set. */
 
227
UNIV_INTERN
 
228
ibool
 
229
dtuple_validate(
 
230
/*============*/
 
231
                                /* out: TRUE if ok */
 
232
        const dtuple_t* tuple)  /* in: tuple */
 
233
{
 
234
        const dfield_t* field;
 
235
        const byte*     data;
 
236
        ulint           n_fields;
 
237
        ulint           len;
 
238
        ulint           i;
 
239
        ulint           j;
 
240
 
 
241
        ut_ad(tuple->magic_n == DATA_TUPLE_MAGIC_N);
 
242
 
 
243
        n_fields = dtuple_get_n_fields(tuple);
 
244
 
 
245
        /* We dereference all the data of each field to test
 
246
        for memory traps */
 
247
 
 
248
        for (i = 0; i < n_fields; i++) {
 
249
 
 
250
                field = dtuple_get_nth_field(tuple, i);
 
251
                len = dfield_get_len(field);
 
252
 
 
253
                if (!dfield_is_null(field)) {
 
254
 
 
255
                        data = dfield_get_data(field);
 
256
                        UNIV_MEM_ASSERT_RW(data, len);
 
257
 
 
258
                        for (j = 0; j < len; j++) {
 
259
 
 
260
                                data_dummy  += *data; /* fool the compiler not
 
261
                                                      to optimize out this
 
262
                                                      code */
 
263
                                data++;
 
264
                        }
 
265
                }
 
266
        }
 
267
 
 
268
        ut_a(dtuple_check_typed(tuple));
 
269
 
 
270
        return(TRUE);
 
271
}
 
272
#endif /* UNIV_DEBUG */
 
273
 
 
274
/*****************************************************************
 
275
Pretty prints a dfield value according to its data type. */
 
276
UNIV_INTERN
 
277
void
 
278
dfield_print(
 
279
/*=========*/
 
280
        const dfield_t* dfield) /* in: dfield */
 
281
{
 
282
        const byte*     data;
 
283
        ulint           len;
 
284
        ulint           i;
 
285
 
 
286
        len = dfield_get_len(dfield);
 
287
        data = dfield_get_data(dfield);
 
288
 
 
289
        if (dfield_is_null(dfield)) {
 
290
                fputs("NULL", stderr);
 
291
 
 
292
                return;
 
293
        }
 
294
 
 
295
        switch (dtype_get_mtype(dfield_get_type(dfield))) {
 
296
        case DATA_CHAR:
 
297
        case DATA_VARCHAR:
 
298
                for (i = 0; i < len; i++) {
 
299
                        int     c = *data++;
 
300
                        putc(isprint(c) ? c : ' ', stderr);
 
301
                }
 
302
 
 
303
                if (dfield_is_ext(dfield)) {
 
304
                        fputs("(external)", stderr);
 
305
                }
 
306
                break;
 
307
        case DATA_INT:
 
308
                ut_a(len == 4); /* only works for 32-bit integers */
 
309
                fprintf(stderr, "%d", (int)mach_read_from_4(data));
 
310
                break;
 
311
        default:
 
312
                ut_error;
 
313
        }
 
314
}
 
315
 
 
316
/*****************************************************************
 
317
Pretty prints a dfield value according to its data type. Also the hex string
 
318
is printed if a string contains non-printable characters. */
 
319
UNIV_INTERN
 
320
void
 
321
dfield_print_also_hex(
 
322
/*==================*/
 
323
        const dfield_t* dfield) /* in: dfield */
 
324
{
 
325
        const byte*     data;
 
326
        ulint           len;
 
327
        ulint           prtype;
 
328
        ulint           i;
 
329
        ibool           print_also_hex;
 
330
 
 
331
        len = dfield_get_len(dfield);
 
332
        data = dfield_get_data(dfield);
 
333
 
 
334
        if (dfield_is_null(dfield)) {
 
335
                fputs("NULL", stderr);
 
336
 
 
337
                return;
 
338
        }
 
339
 
 
340
        prtype = dtype_get_prtype(dfield_get_type(dfield));
 
341
 
 
342
        switch (dtype_get_mtype(dfield_get_type(dfield))) {
 
343
                dulint  id;
 
344
        case DATA_INT:
 
345
                switch (len) {
 
346
                        ulint   val;
 
347
                case 1:
 
348
                        val = mach_read_from_1(data);
 
349
 
 
350
                        if (!(prtype & DATA_UNSIGNED)) {
 
351
                                val &= ~0x80;
 
352
                                fprintf(stderr, "%ld", (long) val);
 
353
                        } else {
 
354
                                fprintf(stderr, "%lu", (ulong) val);
 
355
                        }
 
356
                        break;
 
357
 
 
358
                case 2:
 
359
                        val = mach_read_from_2(data);
 
360
 
 
361
                        if (!(prtype & DATA_UNSIGNED)) {
 
362
                                val &= ~0x8000;
 
363
                                fprintf(stderr, "%ld", (long) val);
 
364
                        } else {
 
365
                                fprintf(stderr, "%lu", (ulong) val);
 
366
                        }
 
367
                        break;
 
368
 
 
369
                case 3:
 
370
                        val = mach_read_from_3(data);
 
371
 
 
372
                        if (!(prtype & DATA_UNSIGNED)) {
 
373
                                val &= ~0x800000;
 
374
                                fprintf(stderr, "%ld", (long) val);
 
375
                        } else {
 
376
                                fprintf(stderr, "%lu", (ulong) val);
 
377
                        }
 
378
                        break;
 
379
 
 
380
                case 4:
 
381
                        val = mach_read_from_4(data);
 
382
 
 
383
                        if (!(prtype & DATA_UNSIGNED)) {
 
384
                                val &= ~0x80000000;
 
385
                                fprintf(stderr, "%ld", (long) val);
 
386
                        } else {
 
387
                                fprintf(stderr, "%lu", (ulong) val);
 
388
                        }
 
389
                        break;
 
390
 
 
391
                case 6:
 
392
                        id = mach_read_from_6(data);
 
393
                        fprintf(stderr, "{%lu %lu}",
 
394
                                ut_dulint_get_high(id),
 
395
                                ut_dulint_get_low(id));
 
396
                        break;
 
397
 
 
398
                case 7:
 
399
                        id = mach_read_from_7(data);
 
400
                        fprintf(stderr, "{%lu %lu}",
 
401
                                ut_dulint_get_high(id),
 
402
                                ut_dulint_get_low(id));
 
403
                        break;
 
404
                case 8:
 
405
                        id = mach_read_from_8(data);
 
406
                        fprintf(stderr, "{%lu %lu}",
 
407
                                ut_dulint_get_high(id),
 
408
                                ut_dulint_get_low(id));
 
409
                        break;
 
410
                default:
 
411
                        goto print_hex;
 
412
                }
 
413
                break;
 
414
 
 
415
        case DATA_SYS:
 
416
                switch (prtype & DATA_SYS_PRTYPE_MASK) {
 
417
                case DATA_TRX_ID:
 
418
                        id = mach_read_from_6(data);
 
419
 
 
420
                        fprintf(stderr, "trx_id " TRX_ID_FMT,
 
421
                                TRX_ID_PREP_PRINTF(id));
 
422
                        break;
 
423
 
 
424
                case DATA_ROLL_PTR:
 
425
                        id = mach_read_from_7(data);
 
426
 
 
427
                        fprintf(stderr, "roll_ptr {%lu %lu}",
 
428
                                ut_dulint_get_high(id), ut_dulint_get_low(id));
 
429
                        break;
 
430
 
 
431
                case DATA_ROW_ID:
 
432
                        id = mach_read_from_6(data);
 
433
 
 
434
                        fprintf(stderr, "row_id {%lu %lu}",
 
435
                                ut_dulint_get_high(id), ut_dulint_get_low(id));
 
436
                        break;
 
437
 
 
438
                default:
 
439
                        id = mach_dulint_read_compressed(data);
 
440
 
 
441
                        fprintf(stderr, "mix_id {%lu %lu}",
 
442
                                ut_dulint_get_high(id), ut_dulint_get_low(id));
 
443
                }
 
444
                break;
 
445
 
 
446
        case DATA_CHAR:
 
447
        case DATA_VARCHAR:
 
448
                print_also_hex = FALSE;
 
449
 
 
450
                for (i = 0; i < len; i++) {
 
451
                        int c = *data++;
 
452
 
 
453
                        if (!isprint(c)) {
 
454
                                print_also_hex = TRUE;
 
455
 
 
456
                                fprintf(stderr, "\\x%02x", (unsigned char) c);
 
457
                        } else {
 
458
                                putc(c, stderr);
 
459
                        }
 
460
                }
 
461
 
 
462
                if (dfield_is_ext(dfield)) {
 
463
                        fputs("(external)", stderr);
 
464
                }
 
465
 
 
466
                if (!print_also_hex) {
 
467
                        break;
 
468
                }
 
469
 
 
470
                data = dfield_get_data(dfield);
 
471
                /* fall through */
 
472
 
 
473
        case DATA_BINARY:
 
474
        default:
 
475
print_hex:
 
476
                fputs(" Hex: ",stderr);
 
477
 
 
478
                for (i = 0; i < len; i++) {
 
479
                        fprintf(stderr, "%02lx", (ulint) *data++);
 
480
                }
 
481
 
 
482
                if (dfield_is_ext(dfield)) {
 
483
                        fputs("(external)", stderr);
 
484
                }
 
485
        }
 
486
}
 
487
 
 
488
/*****************************************************************
 
489
Print a dfield value using ut_print_buf. */
 
490
static
 
491
void
 
492
dfield_print_raw(
 
493
/*=============*/
 
494
        FILE*           f,              /* in: output stream */
 
495
        const dfield_t* dfield)         /* in: dfield */
 
496
{
 
497
        ulint   len     = dfield_get_len(dfield);
 
498
        if (!dfield_is_null(dfield)) {
 
499
                ulint   print_len = ut_min(len, 1000);
 
500
                ut_print_buf(f, dfield_get_data(dfield), print_len);
 
501
                if (len != print_len) {
 
502
                        fprintf(f, "(total %lu bytes%s)",
 
503
                                (ulong) len,
 
504
                                dfield_is_ext(dfield) ? ", external" : "");
 
505
                }
 
506
        } else {
 
507
                fputs(" SQL NULL", f);
 
508
        }
 
509
}
 
510
 
 
511
/**************************************************************
 
512
The following function prints the contents of a tuple. */
 
513
UNIV_INTERN
 
514
void
 
515
dtuple_print(
 
516
/*=========*/
 
517
        FILE*           f,      /* in: output stream */
 
518
        const dtuple_t* tuple)  /* in: tuple */
 
519
{
 
520
        ulint           n_fields;
 
521
        ulint           i;
 
522
 
 
523
        n_fields = dtuple_get_n_fields(tuple);
 
524
 
 
525
        fprintf(f, "DATA TUPLE: %lu fields;\n", (ulong) n_fields);
 
526
 
 
527
        for (i = 0; i < n_fields; i++) {
 
528
                fprintf(f, " %lu:", (ulong) i);
 
529
 
 
530
                dfield_print_raw(f, dtuple_get_nth_field(tuple, i));
 
531
 
 
532
                putc(';', f);
 
533
        }
 
534
 
 
535
        putc('\n', f);
 
536
        ut_ad(dtuple_validate(tuple));
 
537
}
 
538
 
 
539
/******************************************************************
 
540
Moves parts of long fields in entry to the big record vector so that
 
541
the size of tuple drops below the maximum record size allowed in the
 
542
database. Moves data only from those fields which are not necessary
 
543
to determine uniquely the insertion place of the tuple in the index. */
 
544
UNIV_INTERN
 
545
big_rec_t*
 
546
dtuple_convert_big_rec(
 
547
/*===================*/
 
548
                                /* out, own: created big record vector,
 
549
                                NULL if we are not able to shorten
 
550
                                the entry enough, i.e., if there are
 
551
                                too many fixed-length or short fields
 
552
                                in entry or the index is clustered */
 
553
        dict_index_t*   index,  /* in: index */
 
554
        dtuple_t*       entry,  /* in/out: index entry */
 
555
        ulint*          n_ext)  /* in/out: number of
 
556
                                externally stored columns */
 
557
{
 
558
        mem_heap_t*     heap;
 
559
        big_rec_t*      vector;
 
560
        dfield_t*       dfield;
 
561
        dict_field_t*   ifield;
 
562
        ulint           size;
 
563
        ulint           n_fields;
 
564
        ulint           local_len;
 
565
        ulint           local_prefix_len;
 
566
 
 
567
        if (UNIV_UNLIKELY(!dict_index_is_clust(index))) {
 
568
                return(NULL);
 
569
        }
 
570
 
 
571
        if (dict_table_get_format(index->table) < DICT_TF_FORMAT_ZIP) {
 
572
                /* up to MySQL 5.1: store a 768-byte prefix locally */
 
573
                local_len = BTR_EXTERN_FIELD_REF_SIZE + DICT_MAX_INDEX_COL_LEN;
 
574
        } else {
 
575
                /* new-format table: do not store any BLOB prefix locally */
 
576
                local_len = BTR_EXTERN_FIELD_REF_SIZE;
 
577
        }
 
578
 
 
579
        ut_a(dtuple_check_typed_no_assert(entry));
 
580
 
 
581
        size = rec_get_converted_size(index, entry, *n_ext);
 
582
 
 
583
        if (UNIV_UNLIKELY(size > 1000000000)) {
 
584
                fprintf(stderr,
 
585
                        "InnoDB: Warning: tuple size very big: %lu\n",
 
586
                        (ulong) size);
 
587
                fputs("InnoDB: Tuple contents: ", stderr);
 
588
                dtuple_print(stderr, entry);
 
589
                putc('\n', stderr);
 
590
        }
 
591
 
 
592
        heap = mem_heap_create(size + dtuple_get_n_fields(entry)
 
593
                               * sizeof(big_rec_field_t) + 1000);
 
594
 
 
595
        vector = mem_heap_alloc(heap, sizeof(big_rec_t));
 
596
 
 
597
        vector->heap = heap;
 
598
        vector->fields = mem_heap_alloc(heap, dtuple_get_n_fields(entry)
 
599
                                        * sizeof(big_rec_field_t));
 
600
 
 
601
        /* Decide which fields to shorten: the algorithm is to look for
 
602
        a variable-length field that yields the biggest savings when
 
603
        stored externally */
 
604
 
 
605
        n_fields = 0;
 
606
 
 
607
        while (page_zip_rec_needs_ext(rec_get_converted_size(index, entry,
 
608
                                                             *n_ext),
 
609
                                      dict_table_is_comp(index->table),
 
610
                                      dict_table_zip_size(index->table))) {
 
611
                ulint                   i;
 
612
                ulint                   longest         = 0;
 
613
                ulint                   longest_i       = ULINT_MAX;
 
614
                byte*                   data;
 
615
                big_rec_field_t*        b;
 
616
 
 
617
                for (i = dict_index_get_n_unique_in_tree(index);
 
618
                     i < dtuple_get_n_fields(entry); i++) {
 
619
                        ulint   savings;
 
620
 
 
621
                        dfield = dtuple_get_nth_field(entry, i);
 
622
                        ifield = dict_index_get_nth_field(index, i);
 
623
 
 
624
                        /* Skip fixed-length, NULL, externally stored,
 
625
                        or short columns */
 
626
 
 
627
                        if (ifield->fixed_len
 
628
                            || dfield_is_null(dfield)
 
629
                            || dfield_is_ext(dfield)
 
630
                            || dfield_get_len(dfield) <= local_len
 
631
                            || dfield_get_len(dfield)
 
632
                            <= BTR_EXTERN_FIELD_REF_SIZE * 2) {
 
633
                                goto skip_field;
 
634
                        }
 
635
 
 
636
                        savings = dfield_get_len(dfield) - local_len;
 
637
 
 
638
                        /* Check that there would be savings */
 
639
                        if (longest >= savings) {
 
640
                                goto skip_field;
 
641
                        }
 
642
 
 
643
                        longest_i = i;
 
644
                        longest = savings;
 
645
 
 
646
skip_field:
 
647
                        continue;
 
648
                }
 
649
 
 
650
                if (!longest) {
 
651
                        /* Cannot shorten more */
 
652
 
 
653
                        mem_heap_free(heap);
 
654
 
 
655
                        return(NULL);
 
656
                }
 
657
 
 
658
                /* Move data from field longest_i to big rec vector.
 
659
 
 
660
                We store the first bytes locally to the record. Then
 
661
                we can calculate all ordering fields in all indexes
 
662
                from locally stored data. */
 
663
 
 
664
                dfield = dtuple_get_nth_field(entry, longest_i);
 
665
                ifield = dict_index_get_nth_field(index, longest_i);
 
666
                local_prefix_len = local_len - BTR_EXTERN_FIELD_REF_SIZE;
 
667
 
 
668
                b = &vector->fields[n_fields];
 
669
                b->field_no = longest_i;
 
670
                b->len = dfield_get_len(dfield) - local_prefix_len;
 
671
                b->data = (char*) dfield_get_data(dfield) + local_prefix_len;
 
672
 
 
673
                /* Allocate the locally stored part of the column. */
 
674
                data = mem_heap_alloc(heap, local_len);
 
675
 
 
676
                /* Copy the local prefix. */
 
677
                memcpy(data, dfield_get_data(dfield), local_prefix_len);
 
678
                /* Clear the extern field reference (BLOB pointer). */
 
679
                memset(data + local_prefix_len, 0, BTR_EXTERN_FIELD_REF_SIZE);
 
680
#if 0
 
681
                /* The following would fail the Valgrind checks in
 
682
                page_cur_insert_rec_low() and page_cur_insert_rec_zip().
 
683
                The BLOB pointers in the record will be initialized after
 
684
                the record and the BLOBs have been written. */
 
685
                UNIV_MEM_ALLOC(data + local_prefix_len,
 
686
                               BTR_EXTERN_FIELD_REF_SIZE);
 
687
#endif
 
688
 
 
689
                dfield_set_data(dfield, data, local_len);
 
690
                dfield_set_ext(dfield);
 
691
 
 
692
                n_fields++;
 
693
                (*n_ext)++;
 
694
                ut_ad(n_fields < dtuple_get_n_fields(entry));
 
695
        }
 
696
 
 
697
        vector->n_fields = n_fields;
 
698
        return(vector);
 
699
}
 
700
 
 
701
/******************************************************************
 
702
Puts back to entry the data stored in vector. Note that to ensure the
 
703
fields in entry can accommodate the data, vector must have been created
 
704
from entry with dtuple_convert_big_rec. */
 
705
UNIV_INTERN
 
706
void
 
707
dtuple_convert_back_big_rec(
 
708
/*========================*/
 
709
        dict_index_t*   index __attribute__((unused)),  /* in: index */
 
710
        dtuple_t*       entry,  /* in: entry whose data was put to vector */
 
711
        big_rec_t*      vector) /* in, own: big rec vector; it is
 
712
                                freed in this function */
 
713
{
 
714
        big_rec_field_t*                b       = vector->fields;
 
715
        const big_rec_field_t* const    end     = b + vector->n_fields;
 
716
 
 
717
        for (; b < end; b++) {
 
718
                dfield_t*       dfield;
 
719
                ulint           local_len;
 
720
 
 
721
                dfield = dtuple_get_nth_field(entry, b->field_no);
 
722
                local_len = dfield_get_len(dfield);
 
723
 
 
724
                ut_ad(dfield_is_ext(dfield));
 
725
                ut_ad(local_len >= BTR_EXTERN_FIELD_REF_SIZE);
 
726
 
 
727
                local_len -= BTR_EXTERN_FIELD_REF_SIZE;
 
728
 
 
729
                ut_ad(local_len <= DICT_MAX_INDEX_COL_LEN);
 
730
 
 
731
                dfield_set_data(dfield,
 
732
                                (char*) b->data - local_len,
 
733
                                b->len + local_len);
 
734
        }
 
735
 
 
736
        mem_heap_free(vector->heap);
 
737
}