~ubuntu-branches/ubuntu/trusty/drizzle/trusty

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Monty Taylor
  • Date: 2010-03-18 12:12:31 UTC
  • Revision ID: james.westby@ubuntu.com-20100318121231-k6g1xe6cshbwa0f8
Tags: upstream-2010.03.1347
ImportĀ upstreamĀ versionĀ 2010.03.1347

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