~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Monty
  • Date: 2008-11-07 05:51:15 UTC
  • mto: This revision was merged to the branch mainline in revision 579.
  • Revision ID: mordred@palanthas.inaugust.com-20081107055115-0275gvq62buzls77
Fixed a decimal sign thing.

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