~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Monty Taylor
  • Date: 2010-02-05 08:11:15 UTC
  • mfrom: (1283 build)
  • mto: (1273.13.43 fix_is)
  • mto: This revision was merged to the branch mainline in revision 1300.
  • Revision ID: mordred@inaugust.com-20100205081115-dr82nvrwv4lvw7sd
Merged trunk.

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
 
                dulint  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, "{%lu %lu}",
423
 
                                ut_dulint_get_high(id),
424
 
                                ut_dulint_get_low(id));
425
 
                        break;
426
 
 
427
 
                case 7:
428
 
                        id = mach_read_from_7(data);
429
 
                        fprintf(stderr, "{%lu %lu}",
430
 
                                ut_dulint_get_high(id),
431
 
                                ut_dulint_get_low(id));
432
 
                        break;
433
 
                case 8:
434
 
                        id = mach_read_from_8(data);
435
 
                        fprintf(stderr, "{%lu %lu}",
436
 
                                ut_dulint_get_high(id),
437
 
                                ut_dulint_get_low(id));
438
 
                        break;
439
 
                default:
440
 
                        goto print_hex;
441
 
                }
442
 
                break;
443
 
 
444
 
        case DATA_SYS:
445
 
                switch (prtype & DATA_SYS_PRTYPE_MASK) {
446
 
                case DATA_TRX_ID:
447
 
                        id = mach_read_from_6(data);
448
 
 
449
 
                        fprintf(stderr, "trx_id " TRX_ID_FMT,
450
 
                                TRX_ID_PREP_PRINTF(id));
451
 
                        break;
452
 
 
453
 
                case DATA_ROLL_PTR:
454
 
                        id = mach_read_from_7(data);
455
 
 
456
 
                        fprintf(stderr, "roll_ptr {%lu %lu}",
457
 
                                ut_dulint_get_high(id), ut_dulint_get_low(id));
458
 
                        break;
459
 
 
460
 
                case DATA_ROW_ID:
461
 
                        id = mach_read_from_6(data);
462
 
 
463
 
                        fprintf(stderr, "row_id {%lu %lu}",
464
 
                                ut_dulint_get_high(id), ut_dulint_get_low(id));
465
 
                        break;
466
 
 
467
 
                default:
468
 
                        id = mach_dulint_read_compressed(data);
469
 
 
470
 
                        fprintf(stderr, "mix_id {%lu %lu}",
471
 
                                ut_dulint_get_high(id), ut_dulint_get_low(id));
472
 
                }
473
 
                break;
474
 
 
475
 
        case DATA_CHAR:
476
 
        case DATA_VARCHAR:
477
 
                print_also_hex = FALSE;
478
 
 
479
 
                for (i = 0; i < len; i++) {
480
 
                        int c = *data++;
481
 
 
482
 
                        if (!isprint(c)) {
483
 
                                print_also_hex = TRUE;
484
 
 
485
 
                                fprintf(stderr, "\\x%02x", (unsigned char) c);
486
 
                        } else {
487
 
                                putc(c, stderr);
488
 
                        }
489
 
                }
490
 
 
491
 
                if (dfield_is_ext(dfield)) {
492
 
                        fputs("(external)", stderr);
493
 
                }
494
 
 
495
 
                if (!print_also_hex) {
496
 
                        break;
497
 
                }
498
 
 
499
 
                data = dfield_get_data(dfield);
500
 
                /* fall through */
501
 
 
502
 
        case DATA_BINARY:
503
 
        default:
504
 
print_hex:
505
 
                fputs(" Hex: ",stderr);
506
 
 
507
 
                for (i = 0; i < len; i++) {
508
 
                        fprintf(stderr, "%02lx", (ulint) *data++);
509
 
                }
510
 
 
511
 
                if (dfield_is_ext(dfield)) {
512
 
                        fputs("(external)", stderr);
513
 
                }
514
 
        }
515
 
}
516
 
 
517
 
/*************************************************************//**
518
 
Print a dfield value using ut_print_buf. */
519
 
static
520
 
void
521
 
dfield_print_raw(
522
 
/*=============*/
523
 
        FILE*           f,              /*!< in: output stream */
524
 
        const dfield_t* dfield)         /*!< in: dfield */
525
 
{
526
 
        ulint   len     = dfield_get_len(dfield);
527
 
        if (!dfield_is_null(dfield)) {
528
 
                ulint   print_len = ut_min(len, 1000);
529
 
                ut_print_buf(f, dfield_get_data(dfield), print_len);
530
 
                if (len != print_len) {
531
 
                        fprintf(f, "(total %lu bytes%s)",
532
 
                                (ulong) len,
533
 
                                dfield_is_ext(dfield) ? ", external" : "");
534
 
                }
535
 
        } else {
536
 
                fputs(" SQL NULL", f);
537
 
        }
538
 
}
539
 
 
540
 
/**********************************************************//**
541
 
The following function prints the contents of a tuple. */
542
 
UNIV_INTERN
543
 
void
544
 
dtuple_print(
545
 
/*=========*/
546
 
        FILE*           f,      /*!< in: output stream */
547
 
        const dtuple_t* tuple)  /*!< in: tuple */
548
 
{
549
 
        ulint           n_fields;
550
 
        ulint           i;
551
 
 
552
 
        n_fields = dtuple_get_n_fields(tuple);
553
 
 
554
 
        fprintf(f, "DATA TUPLE: %lu fields;\n", (ulong) n_fields);
555
 
 
556
 
        for (i = 0; i < n_fields; i++) {
557
 
                fprintf(f, " %lu:", (ulong) i);
558
 
 
559
 
                dfield_print_raw(f, dtuple_get_nth_field(tuple, i));
560
 
 
561
 
                putc(';', f);
562
 
                putc('\n', f);
563
 
        }
564
 
 
565
 
        ut_ad(dtuple_validate(tuple));
566
 
}
567
 
 
568
 
/**************************************************************//**
569
 
Moves parts of long fields in entry to the big record vector so that
570
 
the size of tuple drops below the maximum record size allowed in the
571
 
database. Moves data only from those fields which are not necessary
572
 
to determine uniquely the insertion place of the tuple in the index.
573
 
@return own: created big record vector, NULL if we are not able to
574
 
shorten the entry enough, i.e., if there are too many fixed-length or
575
 
short fields in entry or the index is clustered */
576
 
UNIV_INTERN
577
 
big_rec_t*
578
 
dtuple_convert_big_rec(
579
 
/*===================*/
580
 
        dict_index_t*   index,  /*!< in: index */
581
 
        dtuple_t*       entry,  /*!< in/out: index entry */
582
 
        ulint*          n_ext)  /*!< in/out: number of
583
 
                                externally stored columns */
584
 
{
585
 
        mem_heap_t*     heap;
586
 
        big_rec_t*      vector;
587
 
        dfield_t*       dfield;
588
 
        dict_field_t*   ifield;
589
 
        ulint           size;
590
 
        ulint           n_fields;
591
 
        ulint           local_len;
592
 
        ulint           local_prefix_len;
593
 
 
594
 
        if (UNIV_UNLIKELY(!dict_index_is_clust(index))) {
595
 
                return(NULL);
596
 
        }
597
 
 
598
 
        if (dict_table_get_format(index->table) < DICT_TF_FORMAT_ZIP) {
599
 
                /* up to MySQL 5.1: store a 768-byte prefix locally */
600
 
                local_len = BTR_EXTERN_FIELD_REF_SIZE + DICT_MAX_INDEX_COL_LEN;
601
 
        } else {
602
 
                /* new-format table: do not store any BLOB prefix locally */
603
 
                local_len = BTR_EXTERN_FIELD_REF_SIZE;
604
 
        }
605
 
 
606
 
        ut_a(dtuple_check_typed_no_assert(entry));
607
 
 
608
 
        size = rec_get_converted_size(index, entry, *n_ext);
609
 
 
610
 
        if (UNIV_UNLIKELY(size > 1000000000)) {
611
 
                fprintf(stderr,
612
 
                        "InnoDB: Warning: tuple size very big: %lu\n",
613
 
                        (ulong) size);
614
 
                fputs("InnoDB: Tuple contents: ", stderr);
615
 
                dtuple_print(stderr, entry);
616
 
                putc('\n', stderr);
617
 
        }
618
 
 
619
 
        heap = mem_heap_create(size + dtuple_get_n_fields(entry)
620
 
                               * sizeof(big_rec_field_t) + 1000);
621
 
 
622
 
        vector = mem_heap_alloc(heap, sizeof(big_rec_t));
623
 
 
624
 
        vector->heap = heap;
625
 
        vector->fields = mem_heap_alloc(heap, dtuple_get_n_fields(entry)
626
 
                                        * sizeof(big_rec_field_t));
627
 
 
628
 
        /* Decide which fields to shorten: the algorithm is to look for
629
 
        a variable-length field that yields the biggest savings when
630
 
        stored externally */
631
 
 
632
 
        n_fields = 0;
633
 
 
634
 
        while (page_zip_rec_needs_ext(rec_get_converted_size(index, entry,
635
 
                                                             *n_ext),
636
 
                                      dict_table_is_comp(index->table),
637
 
                                      dict_index_get_n_fields(index),
638
 
                                      dict_table_zip_size(index->table))) {
639
 
                ulint                   i;
640
 
                ulint                   longest         = 0;
641
 
                ulint                   longest_i       = ULINT_MAX;
642
 
                byte*                   data;
643
 
                big_rec_field_t*        b;
644
 
 
645
 
                for (i = dict_index_get_n_unique_in_tree(index);
646
 
                     i < dtuple_get_n_fields(entry); i++) {
647
 
                        ulint   savings;
648
 
 
649
 
                        dfield = dtuple_get_nth_field(entry, i);
650
 
                        ifield = dict_index_get_nth_field(index, i);
651
 
 
652
 
                        /* Skip fixed-length, NULL, externally stored,
653
 
                        or short columns */
654
 
 
655
 
                        if (ifield->fixed_len
656
 
                            || dfield_is_null(dfield)
657
 
                            || dfield_is_ext(dfield)
658
 
                            || dfield_get_len(dfield) <= local_len
659
 
                            || dfield_get_len(dfield)
660
 
                            <= BTR_EXTERN_FIELD_REF_SIZE * 2) {
661
 
                                goto skip_field;
662
 
                        }
663
 
 
664
 
                        savings = dfield_get_len(dfield) - local_len;
665
 
 
666
 
                        /* Check that there would be savings */
667
 
                        if (longest >= savings) {
668
 
                                goto skip_field;
669
 
                        }
670
 
 
671
 
                        /* In DYNAMIC and COMPRESSED format, store
672
 
                        locally any non-BLOB columns whose maximum
673
 
                        length does not exceed 256 bytes.  This is
674
 
                        because there is no room for the "external
675
 
                        storage" flag when the maximum length is 255
676
 
                        bytes or less. This restriction trivially
677
 
                        holds in REDUNDANT and COMPACT format, because
678
 
                        there we always store locally columns whose
679
 
                        length is up to local_len == 788 bytes.
680
 
                        @see rec_init_offsets_comp_ordinary */
681
 
                        if (ifield->col->mtype != DATA_BLOB
682
 
                            && ifield->col->len < 256) {
683
 
                                goto skip_field;
684
 
                        }
685
 
 
686
 
                        /* In DYNAMIC and COMPRESSED format, store
687
 
                        locally any non-BLOB columns whose maximum
688
 
                        length does not exceed 256 bytes.  This is
689
 
                        because there is no room for the "external
690
 
                        storage" flag when the maximum length is 255
691
 
                        bytes or less. This restriction trivially
692
 
                        holds in REDUNDANT and COMPACT format, because
693
 
                        there we always store locally columns whose
694
 
                        length is up to local_len == 788 bytes.
695
 
                        @see rec_init_offsets_comp_ordinary */
696
 
                        if (ifield->col->mtype != DATA_BLOB
697
 
                            && ifield->col->len < 256) {
698
 
                                goto skip_field;
699
 
                        }
700
 
 
701
 
                        longest_i = i;
702
 
                        longest = savings;
703
 
 
704
 
skip_field:
705
 
                        continue;
706
 
                }
707
 
 
708
 
                if (!longest) {
709
 
                        /* Cannot shorten more */
710
 
 
711
 
                        mem_heap_free(heap);
712
 
 
713
 
                        return(NULL);
714
 
                }
715
 
 
716
 
                /* Move data from field longest_i to big rec vector.
717
 
 
718
 
                We store the first bytes locally to the record. Then
719
 
                we can calculate all ordering fields in all indexes
720
 
                from locally stored data. */
721
 
 
722
 
                dfield = dtuple_get_nth_field(entry, longest_i);
723
 
                ifield = dict_index_get_nth_field(index, longest_i);
724
 
                local_prefix_len = local_len - BTR_EXTERN_FIELD_REF_SIZE;
725
 
 
726
 
                b = &vector->fields[n_fields];
727
 
                b->field_no = longest_i;
728
 
                b->len = dfield_get_len(dfield) - local_prefix_len;
729
 
                b->data = (char*) dfield_get_data(dfield) + local_prefix_len;
730
 
 
731
 
                /* Allocate the locally stored part of the column. */
732
 
                data = mem_heap_alloc(heap, local_len);
733
 
 
734
 
                /* Copy the local prefix. */
735
 
                memcpy(data, dfield_get_data(dfield), local_prefix_len);
736
 
                /* Clear the extern field reference (BLOB pointer). */
737
 
                memset(data + local_prefix_len, 0, BTR_EXTERN_FIELD_REF_SIZE);
738
 
#if 0
739
 
                /* The following would fail the Valgrind checks in
740
 
                page_cur_insert_rec_low() and page_cur_insert_rec_zip().
741
 
                The BLOB pointers in the record will be initialized after
742
 
                the record and the BLOBs have been written. */
743
 
                UNIV_MEM_ALLOC(data + local_prefix_len,
744
 
                               BTR_EXTERN_FIELD_REF_SIZE);
745
 
#endif
746
 
 
747
 
                dfield_set_data(dfield, data, local_len);
748
 
                dfield_set_ext(dfield);
749
 
 
750
 
                n_fields++;
751
 
                (*n_ext)++;
752
 
                ut_ad(n_fields < dtuple_get_n_fields(entry));
753
 
        }
754
 
 
755
 
        vector->n_fields = n_fields;
756
 
        return(vector);
757
 
}
758
 
 
759
 
/**************************************************************//**
760
 
Puts back to entry the data stored in vector. Note that to ensure the
761
 
fields in entry can accommodate the data, vector must have been created
762
 
from entry with dtuple_convert_big_rec. */
763
 
UNIV_INTERN
764
 
void
765
 
dtuple_convert_back_big_rec(
766
 
/*========================*/
767
 
        dict_index_t*   index __attribute__((unused)),  /*!< in: index */
768
 
        dtuple_t*       entry,  /*!< in: entry whose data was put to vector */
769
 
        big_rec_t*      vector) /*!< in, own: big rec vector; it is
770
 
                                freed in this function */
771
 
{
772
 
        big_rec_field_t*                b       = vector->fields;
773
 
        const big_rec_field_t* const    end     = b + vector->n_fields;
774
 
 
775
 
        for (; b < end; b++) {
776
 
                dfield_t*       dfield;
777
 
                ulint           local_len;
778
 
 
779
 
                dfield = dtuple_get_nth_field(entry, b->field_no);
780
 
                local_len = dfield_get_len(dfield);
781
 
 
782
 
                ut_ad(dfield_is_ext(dfield));
783
 
                ut_ad(local_len >= BTR_EXTERN_FIELD_REF_SIZE);
784
 
 
785
 
                local_len -= BTR_EXTERN_FIELD_REF_SIZE;
786
 
 
787
 
                ut_ad(local_len <= DICT_MAX_INDEX_COL_LEN);
788
 
 
789
 
                dfield_set_data(dfield,
790
 
                                (char*) b->data - local_len,
791
 
                                b->len + local_len);
792
 
        }
793
 
 
794
 
        mem_heap_free(vector->heap);
795
 
}
796
 
#endif /* !UNIV_HOTBACKUP */