~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Brian Aker
  • Date: 2010-07-28 22:40:44 UTC
  • mto: This revision was merged to the branch mainline in revision 1671.
  • Revision ID: brian@gaz-20100728224044-j7lfssku6pbqg8wr
Remove the need for tolower in retrieval of table functions.

Show diffs side-by-side

added added

removed removed

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