~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Brian Aker
  • Date: 2010-12-08 22:35:56 UTC
  • mfrom: (1819.9.158 update-innobase)
  • Revision ID: brian@tangent.org-20101208223556-37mi4omqg7lkjzf3
Merge in Stewart's changes, 1.3 changes.

Show diffs side-by-side

added added

removed removed

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