~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

Merged from Toru - removal of my_time_t.

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_index_get_n_fields(index),
 
611
                                      dict_table_zip_size(index->table))) {
 
612
                ulint                   i;
 
613
                ulint                   longest         = 0;
 
614
                ulint                   longest_i       = ULINT_MAX;
 
615
                byte*                   data;
 
616
                big_rec_field_t*        b;
 
617
 
 
618
                for (i = dict_index_get_n_unique_in_tree(index);
 
619
                     i < dtuple_get_n_fields(entry); i++) {
 
620
                        ulint   savings;
 
621
 
 
622
                        dfield = dtuple_get_nth_field(entry, i);
 
623
                        ifield = dict_index_get_nth_field(index, i);
 
624
 
 
625
                        /* Skip fixed-length, NULL, externally stored,
 
626
                        or short columns */
 
627
 
 
628
                        if (ifield->fixed_len
 
629
                            || dfield_is_null(dfield)
 
630
                            || dfield_is_ext(dfield)
 
631
                            || dfield_get_len(dfield) <= local_len
 
632
                            || dfield_get_len(dfield)
 
633
                            <= BTR_EXTERN_FIELD_REF_SIZE * 2) {
 
634
                                goto skip_field;
 
635
                        }
 
636
 
 
637
                        savings = dfield_get_len(dfield) - local_len;
 
638
 
 
639
                        /* Check that there would be savings */
 
640
                        if (longest >= savings) {
 
641
                                goto skip_field;
 
642
                        }
 
643
 
 
644
                        longest_i = i;
 
645
                        longest = savings;
 
646
 
 
647
skip_field:
 
648
                        continue;
 
649
                }
 
650
 
 
651
                if (!longest) {
 
652
                        /* Cannot shorten more */
 
653
 
 
654
                        mem_heap_free(heap);
 
655
 
 
656
                        return(NULL);
 
657
                }
 
658
 
 
659
                /* Move data from field longest_i to big rec vector.
 
660
 
 
661
                We store the first bytes locally to the record. Then
 
662
                we can calculate all ordering fields in all indexes
 
663
                from locally stored data. */
 
664
 
 
665
                dfield = dtuple_get_nth_field(entry, longest_i);
 
666
                ifield = dict_index_get_nth_field(index, longest_i);
 
667
                local_prefix_len = local_len - BTR_EXTERN_FIELD_REF_SIZE;
 
668
 
 
669
                b = &vector->fields[n_fields];
 
670
                b->field_no = longest_i;
 
671
                b->len = dfield_get_len(dfield) - local_prefix_len;
 
672
                b->data = (char*) dfield_get_data(dfield) + local_prefix_len;
 
673
 
 
674
                /* Allocate the locally stored part of the column. */
 
675
                data = mem_heap_alloc(heap, local_len);
 
676
 
 
677
                /* Copy the local prefix. */
 
678
                memcpy(data, dfield_get_data(dfield), local_prefix_len);
 
679
                /* Clear the extern field reference (BLOB pointer). */
 
680
                memset(data + local_prefix_len, 0, BTR_EXTERN_FIELD_REF_SIZE);
 
681
#if 0
 
682
                /* The following would fail the Valgrind checks in
 
683
                page_cur_insert_rec_low() and page_cur_insert_rec_zip().
 
684
                The BLOB pointers in the record will be initialized after
 
685
                the record and the BLOBs have been written. */
 
686
                UNIV_MEM_ALLOC(data + local_prefix_len,
 
687
                               BTR_EXTERN_FIELD_REF_SIZE);
 
688
#endif
 
689
 
 
690
                dfield_set_data(dfield, data, local_len);
 
691
                dfield_set_ext(dfield);
 
692
 
 
693
                n_fields++;
 
694
                (*n_ext)++;
 
695
                ut_ad(n_fields < dtuple_get_n_fields(entry));
 
696
        }
 
697
 
 
698
        vector->n_fields = n_fields;
 
699
        return(vector);
 
700
}
 
701
 
 
702
/******************************************************************
 
703
Puts back to entry the data stored in vector. Note that to ensure the
 
704
fields in entry can accommodate the data, vector must have been created
 
705
from entry with dtuple_convert_big_rec. */
 
706
UNIV_INTERN
 
707
void
 
708
dtuple_convert_back_big_rec(
 
709
/*========================*/
 
710
        dict_index_t*   index __attribute__((unused)),  /* in: index */
 
711
        dtuple_t*       entry,  /* in: entry whose data was put to vector */
 
712
        big_rec_t*      vector) /* in, own: big rec vector; it is
 
713
                                freed in this function */
 
714
{
 
715
        big_rec_field_t*                b       = vector->fields;
 
716
        const big_rec_field_t* const    end     = b + vector->n_fields;
 
717
 
 
718
        for (; b < end; b++) {
 
719
                dfield_t*       dfield;
 
720
                ulint           local_len;
 
721
 
 
722
                dfield = dtuple_get_nth_field(entry, b->field_no);
 
723
                local_len = dfield_get_len(dfield);
 
724
 
 
725
                ut_ad(dfield_is_ext(dfield));
 
726
                ut_ad(local_len >= BTR_EXTERN_FIELD_REF_SIZE);
 
727
 
 
728
                local_len -= BTR_EXTERN_FIELD_REF_SIZE;
 
729
 
 
730
                ut_ad(local_len <= DICT_MAX_INDEX_COL_LEN);
 
731
 
 
732
                dfield_set_data(dfield,
 
733
                                (char*) b->data - local_len,
 
734
                                b->len + local_len);
 
735
        }
 
736
 
 
737
        mem_heap_free(vector->heap);
 
738
}