~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/innobase/row/row0merge.c

Merge Stewart's dead code removal

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*****************************************************************************
2
2
 
3
 
Copyright (C) 2005, 2010, Innobase Oy. All Rights Reserved.
 
3
Copyright (c) 2005, 2009, Innobase Oy. All Rights Reserved.
4
4
 
5
5
This program is free software; you can redistribute it and/or modify it under
6
6
the terms of the GNU General Public License as published by the Free Software
11
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
12
 
13
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
 
14
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 
15
Place, Suite 330, Boston, MA 02111-1307 USA
16
16
 
17
17
*****************************************************************************/
18
18
 
56
56
#include "log0log.h"
57
57
#include "ut0sort.h"
58
58
#include "handler0alter.h"
59
 
#include <unistd.h>
60
 
 
61
 
/* Ignore posix_fadvise() on those platforms where it does not exist */
62
 
#if defined __WIN__
63
 
# define posix_fadvise(fd, offset, len, advice) /* nothing */
64
 
#endif /* __WIN__ */
65
59
 
66
60
#ifdef UNIV_DEBUG
67
61
/** Set these in order ot enable debug printout. */
68
62
/* @{ */
69
 
/** Log the outcome of each row_merge_cmp() call, comparing records. */
70
63
static ibool    row_merge_print_cmp;
71
 
/** Log each record read from temporary file. */
72
64
static ibool    row_merge_print_read;
73
 
/** Log each record write to temporary file. */
74
65
static ibool    row_merge_print_write;
75
 
/** Log each row_merge_blocks() call, merging two blocks of records to
76
 
a bigger one. */
77
 
static ibool    row_merge_print_block;
78
 
/** Log each block read from temporary file. */
79
 
static ibool    row_merge_print_block_read;
80
 
/** Log each block read from temporary file. */
81
 
static ibool    row_merge_print_block_write;
82
66
/* @} */
83
67
#endif /* UNIV_DEBUG */
84
68
 
125
109
 
126
110
/** Information about temporary files used in merge sort */
127
111
struct merge_file_struct {
128
 
        int             fd;             /*!< file descriptor */
129
 
        ulint           offset;         /*!< file offset (end of file) */
130
 
        ib_uint64_t     n_rec;          /*!< number of records in the file */
 
112
        int     fd;             /*!< file descriptor */
 
113
        ulint   offset;         /*!< file offset */
131
114
};
132
115
 
133
116
/** Information about temporary files used in merge sort */
187
170
        ut_ad(max_tuples <= sizeof(row_merge_block_t));
188
171
        ut_ad(max_tuples < buf_size);
189
172
 
190
 
        buf = static_cast<row_merge_buf_t *>(mem_heap_zalloc(heap, buf_size));
 
173
        buf = mem_heap_zalloc(heap, buf_size);
191
174
        buf->heap = heap;
192
175
        buf->index = index;
193
176
        buf->max_tuples = max_tuples;
194
 
        buf->tuples = static_cast<const dfield_t **>(mem_heap_alloc(heap,
195
 
                                     2 * max_tuples * sizeof *buf->tuples));
 
177
        buf->tuples = mem_heap_alloc(heap,
 
178
                                     2 * max_tuples * sizeof *buf->tuples);
196
179
        buf->tmp_tuples = buf->tuples + max_tuples;
197
180
 
198
181
        return(buf);
275
258
        const dict_index_t*     index;
276
259
        dfield_t*               entry;
277
260
        dfield_t*               field;
278
 
        const dict_field_t*     ifield;
279
261
 
280
262
        if (buf->n_tuples >= buf->max_tuples) {
281
263
                return(FALSE);
287
269
 
288
270
        n_fields = dict_index_get_n_fields(index);
289
271
 
290
 
        entry = static_cast<dfield_t *>(mem_heap_alloc(buf->heap, n_fields * sizeof *entry));
 
272
        entry = mem_heap_alloc(buf->heap, n_fields * sizeof *entry);
291
273
        buf->tuples[buf->n_tuples] = entry;
292
274
        field = entry;
293
275
 
294
276
        data_size = 0;
295
277
        extra_size = UT_BITS_IN_BYTES(index->n_nullable);
296
278
 
297
 
        ifield = dict_index_get_nth_field(index, 0);
298
 
 
299
 
        for (i = 0; i < n_fields; i++, field++, ifield++) {
 
279
        for (i = 0; i < n_fields; i++, field++) {
 
280
                const dict_field_t*     ifield;
300
281
                const dict_col_t*       col;
301
282
                ulint                   col_no;
302
283
                const dfield_t*         row_field;
303
284
                ulint                   len;
304
285
 
 
286
                ifield = dict_index_get_nth_field(index, i);
305
287
                col = ifield->col;
306
288
                col_no = dict_col_get_no(col);
307
289
                row_field = dtuple_get_nth_field(row, col_no);
314
296
                } else if (UNIV_LIKELY(!ext)) {
315
297
                } else if (dict_index_is_clust(index)) {
316
298
                        /* Flag externally stored fields. */
317
 
                        const byte*     row_buf = row_ext_lookup(ext, col_no,
 
299
                        const byte*     buf = row_ext_lookup(ext, col_no,
318
300
                                                             &len);
319
 
                        if (UNIV_LIKELY_NULL(row_buf)) {
320
 
                                ut_a(row_buf != field_ref_zero);
 
301
                        if (UNIV_LIKELY_NULL(buf)) {
 
302
                                ut_a(buf != field_ref_zero);
321
303
                                if (i < dict_index_get_n_unique(index)) {
322
 
                                        dfield_set_data(field, row_buf, len);
 
304
                                        dfield_set_data(field, buf, len);
323
305
                                } else {
324
306
                                        dfield_set_ext(field);
325
307
                                        len = dfield_get_len(field);
326
308
                                }
327
309
                        }
328
310
                } else {
329
 
                        const byte*     row_buf = row_ext_lookup(ext, col_no,
 
311
                        const byte*     buf = row_ext_lookup(ext, col_no,
330
312
                                                             &len);
331
 
                        if (UNIV_LIKELY_NULL(row_buf)) {
332
 
                                ut_a(row_buf != field_ref_zero);
333
 
                                dfield_set_data(field, row_buf, len);
 
313
                        if (UNIV_LIKELY_NULL(buf)) {
 
314
                                ut_a(buf != field_ref_zero);
 
315
                                dfield_set_data(field, buf, len);
334
316
                        }
335
317
                }
336
318
 
339
321
                if (ifield->prefix_len) {
340
322
                        len = dtype_get_at_most_n_mbchars(
341
323
                                col->prtype,
342
 
                                col->mbminmaxlen,
 
324
                                col->mbminlen, col->mbmaxlen,
343
325
                                ifield->prefix_len,
344
 
                                len, static_cast<const char *>(dfield_get_data(field)));
 
326
                                len, dfield_get_data(field));
345
327
                        dfield_set_len(field, len);
346
328
                }
347
329
 
415
397
/** Structure for reporting duplicate records. */
416
398
struct row_merge_dup_struct {
417
399
        const dict_index_t*     index;          /*!< index being sorted */
418
 
        TABLE*          table;          /*!< MySQL table object */
 
400
        TABLE*                  table;          /*!< MySQL table object */
419
401
        ulint                   n_dup;          /*!< number of duplicates */
420
402
};
421
403
 
431
413
        row_merge_dup_t*        dup,    /*!< in/out: for reporting duplicates */
432
414
        const dfield_t*         entry)  /*!< in: duplicate index entry */
433
415
{
434
 
        mrec_buf_t*             buf;
 
416
        mrec_buf_t              buf;
435
417
        const dtuple_t*         tuple;
436
418
        dtuple_t                tuple_store;
437
419
        const rec_t*            rec;
438
420
        const dict_index_t*     index   = dup->index;
439
421
        ulint                   n_fields= dict_index_get_n_fields(index);
440
 
        mem_heap_t*             heap;
 
422
        mem_heap_t*             heap    = NULL;
 
423
        ulint                   offsets_[REC_OFFS_NORMAL_SIZE];
441
424
        ulint*                  offsets;
442
425
        ulint                   n_ext;
443
426
 
447
430
                return;
448
431
        }
449
432
 
 
433
        rec_offs_init(offsets_);
 
434
 
450
435
        /* Convert the tuple to a record and then to MySQL format. */
451
 
        heap = mem_heap_create((1 + REC_OFFS_HEADER_SIZE + n_fields)
452
 
                               * sizeof *offsets
453
 
                               + sizeof *buf);
454
 
 
455
 
        buf = static_cast<mrec_buf_t *>(mem_heap_alloc(heap, sizeof *buf));
456
436
 
457
437
        tuple = dtuple_from_fields(&tuple_store, entry, n_fields);
458
438
        n_ext = dict_index_is_clust(index) ? dtuple_get_n_ext(tuple) : 0;
459
439
 
460
 
        rec = rec_convert_dtuple_to_rec(*buf, index, tuple, n_ext);
461
 
        offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED, &heap);
 
440
        rec = rec_convert_dtuple_to_rec(buf, index, tuple, n_ext);
 
441
        offsets = rec_get_offsets(rec, index, offsets_, ULINT_UNDEFINED,
 
442
                                  &heap);
462
443
 
463
444
        innobase_rec_to_mysql(dup->table, rec, index, offsets);
464
445
 
465
 
        mem_heap_free(heap);
 
446
        if (UNIV_LIKELY_NULL(heap)) {
 
447
                mem_heap_free(heap);
 
448
        }
466
449
}
467
450
 
468
451
/*************************************************************//**
633
616
}
634
617
 
635
618
/******************************************************//**
636
 
Create a memory heap and allocate space for row_merge_rec_offsets()
637
 
and mrec_buf_t[3].
 
619
Create a memory heap and allocate space for row_merge_rec_offsets().
638
620
@return memory heap */
639
621
static
640
622
mem_heap_t*
641
623
row_merge_heap_create(
642
624
/*==================*/
643
625
        const dict_index_t*     index,          /*!< in: record descriptor */
644
 
        mrec_buf_t**            buf,            /*!< out: 3 buffers */
645
626
        ulint**                 offsets1,       /*!< out: offsets */
646
627
        ulint**                 offsets2)       /*!< out: offsets */
647
628
{
648
629
        ulint           i       = 1 + REC_OFFS_HEADER_SIZE
649
630
                + dict_index_get_n_fields(index);
650
 
        mem_heap_t*     heap    = mem_heap_create(2 * i * sizeof **offsets1
651
 
                                                  + 3 * sizeof **buf);
 
631
        mem_heap_t*     heap    = mem_heap_create(2 * i * sizeof *offsets1);
652
632
 
653
 
        *buf = static_cast<mrec_buf_t*>(mem_heap_alloc(heap, 3 * sizeof **buf));
654
 
        *offsets1 = static_cast<ulint*>(mem_heap_alloc(heap, i * sizeof **offsets1));
655
 
        *offsets2 = static_cast<ulint*>(mem_heap_alloc(heap, i * sizeof **offsets2));
 
633
        *offsets1 = mem_heap_alloc(heap, i * sizeof *offsets1);
 
634
        *offsets2 = mem_heap_alloc(heap, i * sizeof *offsets2);
656
635
 
657
636
        (*offsets1)[0] = (*offsets2)[0] = i;
658
637
        (*offsets1)[1] = (*offsets2)[1] = dict_index_get_n_fields(index);
675
654
        dict_index_t*   index;
676
655
        const char**    column_names;
677
656
 
678
 
        column_names = static_cast<const char **>(mem_alloc(index_def->n_fields * sizeof *column_names));
 
657
        column_names = mem_alloc(index_def->n_fields * sizeof *column_names);
679
658
 
680
659
        for (i = 0; i < index_def->n_fields; ++i) {
681
660
                column_names[i] = index_def->fields[i].field_name;
697
676
row_merge_read(
698
677
/*===========*/
699
678
        int                     fd,     /*!< in: file descriptor */
700
 
        ulint                   offset, /*!< in: offset where to read
701
 
                                        in number of row_merge_block_t
702
 
                                        elements */
 
679
        ulint                   offset, /*!< in: offset where to read */
703
680
        row_merge_block_t*      buf)    /*!< out: data */
704
681
{
705
682
        ib_uint64_t     ofs = ((ib_uint64_t) offset) * sizeof *buf;
706
683
        ibool           success;
707
684
 
708
 
#ifdef UNIV_DEBUG
709
 
        if (row_merge_print_block_read) {
710
 
                fprintf(stderr, "row_merge_read fd=%d ofs=%lu\n",
711
 
                        fd, (ulong) offset);
712
 
        }
713
 
#endif /* UNIV_DEBUG */
714
 
 
715
685
        success = os_file_read_no_error_handling(OS_FILE_FROM_FD(fd), buf,
716
686
                                                 (ulint) (ofs & 0xFFFFFFFF),
717
687
                                                 (ulint) (ofs >> 32),
718
688
                                                 sizeof *buf);
719
 
#ifdef POSIX_FADV_DONTNEED
720
 
        /* Each block is read exactly once.  Free up the file cache. */
721
 
        posix_fadvise(fd, ofs, sizeof *buf, POSIX_FADV_DONTNEED);
722
 
#endif /* POSIX_FADV_DONTNEED */
723
 
 
724
689
        if (UNIV_UNLIKELY(!success)) {
725
690
                ut_print_timestamp(stderr);
726
691
                fprintf(stderr,
731
696
}
732
697
 
733
698
/********************************************************************//**
734
 
Write a merge block to the file system.
 
699
Read a merge block from the file system.
735
700
@return TRUE if request was successful, FALSE if fail */
736
701
static
737
702
ibool
738
703
row_merge_write(
739
704
/*============*/
740
705
        int             fd,     /*!< in: file descriptor */
741
 
        ulint           offset, /*!< in: offset where to write,
742
 
                                in number of row_merge_block_t elements */
 
706
        ulint           offset, /*!< in: offset where to write */
743
707
        const void*     buf)    /*!< in: data */
744
708
{
745
 
        size_t          buf_len = sizeof(row_merge_block_t);
746
 
        ib_uint64_t     ofs = buf_len * (ib_uint64_t) offset;
747
 
        ibool           ret;
748
 
 
749
 
        ret = os_file_write("(merge)", OS_FILE_FROM_FD(fd), buf,
750
 
                            (ulint) (ofs & 0xFFFFFFFF),
751
 
                            (ulint) (ofs >> 32),
752
 
                            buf_len);
753
 
 
754
 
#ifdef UNIV_DEBUG
755
 
        if (row_merge_print_block_write) {
756
 
                fprintf(stderr, "row_merge_write fd=%d ofs=%lu\n",
757
 
                        fd, (ulong) offset);
758
 
        }
759
 
#endif /* UNIV_DEBUG */
760
 
 
761
 
#ifdef POSIX_FADV_DONTNEED
762
 
        /* The block will be needed on the next merge pass,
763
 
        but it can be evicted from the file cache meanwhile. */
764
 
        posix_fadvise(fd, ofs, buf_len, POSIX_FADV_DONTNEED);
765
 
#endif /* POSIX_FADV_DONTNEED */
766
 
 
767
 
        return(UNIV_LIKELY(ret));
 
709
        ib_uint64_t     ofs = ((ib_uint64_t) offset)
 
710
                * sizeof(row_merge_block_t);
 
711
 
 
712
        return(UNIV_LIKELY(os_file_write("(merge)", OS_FILE_FROM_FD(fd), buf,
 
713
                                         (ulint) (ofs & 0xFFFFFFFF),
 
714
                                         (ulint) (ofs >> 32),
 
715
                                         sizeof(row_merge_block_t))));
768
716
}
769
717
 
770
718
/********************************************************************//**
771
719
Read a merge record.
772
720
@return pointer to next record, or NULL on I/O error or end of list */
773
 
static __attribute__((nonnull))
 
721
static
774
722
const byte*
775
723
row_merge_read_rec(
776
724
/*===============*/
1099
1047
                                                record to be compared */
1100
1048
        const ulint*            offsets1,       /*!< in: first record offsets */
1101
1049
        const ulint*            offsets2,       /*!< in: second record offsets */
1102
 
        const dict_index_t*     index,          /*!< in: index */
1103
 
        ibool*                  null_eq)        /*!< out: set to TRUE if
1104
 
                                                found matching null values */
 
1050
        const dict_index_t*     index)          /*!< in: index */
1105
1051
{
1106
1052
        int     cmp;
1107
1053
 
1108
 
        cmp = cmp_rec_rec_simple(mrec1, mrec2, offsets1, offsets2, index,
1109
 
                                 null_eq);
 
1054
        cmp = cmp_rec_rec_simple(mrec1, mrec2, offsets1, offsets2, index);
1110
1055
 
1111
1056
#ifdef UNIV_DEBUG
1112
1057
        if (row_merge_print_cmp) {
1125
1070
Reads clustered index of the table and create temporary files
1126
1071
containing the index entries for the indexes to be built.
1127
1072
@return DB_SUCCESS or error */
1128
 
static __attribute__((nonnull))
 
1073
static
1129
1074
ulint
1130
1075
row_merge_read_clustered_index(
1131
1076
/*===========================*/
1132
1077
        trx_t*                  trx,    /*!< in: transaction */
1133
 
        TABLE*          table,  /*!< in/out: MySQL table object,
 
1078
        TABLE*                  table,  /*!< in/out: MySQL table object,
1134
1079
                                        for reporting erroneous records */
1135
1080
        const dict_table_t*     old_table,/*!< in: table where rows are
1136
1081
                                        read from */
1165
1110
 
1166
1111
        /* Create and initialize memory for record buffers */
1167
1112
 
1168
 
        merge_buf = static_cast<row_merge_buf_t **>(mem_alloc(n_index * sizeof *merge_buf));
 
1113
        merge_buf = mem_alloc(n_index * sizeof *merge_buf);
1169
1114
 
1170
1115
        for (i = 0; i < n_index; i++) {
1171
1116
                merge_buf[i] = row_merge_buf_create(index[i]);
1192
1137
 
1193
1138
                ut_a(n_cols == dict_table_get_n_cols(new_table));
1194
1139
 
1195
 
                nonnull = static_cast<ulint*>(mem_alloc(n_cols * sizeof *nonnull));
 
1140
                nonnull = mem_alloc(n_cols * sizeof *nonnull);
1196
1141
 
1197
1142
                for (i = 0; i < n_cols; i++) {
1198
1143
                        if (dict_table_get_nth_col(old_table, i)->prtype
1230
1175
                in order to release the latch on the old page. */
1231
1176
 
1232
1177
                if (btr_pcur_is_after_last_on_page(&pcur)) {
1233
 
                        if (UNIV_UNLIKELY(trx_is_interrupted(trx))) {
1234
 
                                err = DB_INTERRUPTED;
1235
 
                                trx->error_key_num = 0;
1236
 
                                goto func_exit;
1237
 
                        }
1238
 
 
1239
1178
                        btr_pcur_store_position(&pcur, &mtr);
1240
1179
                        mtr_commit(&mtr);
1241
1180
                        mtr_start(&mtr);
1275
1214
 
1276
1215
                                        if (dfield_is_null(field)) {
1277
1216
                                                err = DB_PRIMARY_KEY_IS_NULL;
1278
 
                                                trx->error_key_num = 0;
1279
 
                                                goto func_exit;
 
1217
                                                i = 0;
 
1218
                                                goto err_exit;
1280
1219
                                        }
1281
1220
 
1282
1221
                                        field_type->prtype |= DATA_NOT_NULL;
1290
1229
                for (i = 0; i < n_index; i++) {
1291
1230
                        row_merge_buf_t*        buf     = merge_buf[i];
1292
1231
                        merge_file_t*           file    = &files[i];
1293
 
                        const dict_index_t*     buf_index       = buf->index;
 
1232
                        const dict_index_t*     index   = buf->index;
1294
1233
 
1295
1234
                        if (UNIV_LIKELY
1296
1235
                            (row && row_merge_buf_add(buf, row, ext))) {
1297
 
                                file->n_rec++;
1298
1236
                                continue;
1299
1237
                        }
1300
1238
 
1306
1244
                        Sort them and write to disk. */
1307
1245
 
1308
1246
                        if (buf->n_tuples) {
1309
 
                                if (dict_index_is_unique(buf_index)) {
 
1247
                                if (dict_index_is_unique(index)) {
1310
1248
                                        row_merge_dup_t dup;
1311
1249
                                        dup.index = buf->index;
1312
1250
                                        dup.table = table;
1316
1254
 
1317
1255
                                        if (dup.n_dup) {
1318
1256
                                                err = DB_DUPLICATE_KEY;
 
1257
err_exit:
1319
1258
                                                trx->error_key_num = i;
1320
1259
                                                goto func_exit;
1321
1260
                                        }
1329
1268
                        if (!row_merge_write(file->fd, file->offset++,
1330
1269
                                             block)) {
1331
1270
                                err = DB_OUT_OF_FILE_SPACE;
1332
 
                                trx->error_key_num = i;
1333
 
                                goto func_exit;
 
1271
                                goto err_exit;
1334
1272
                        }
1335
1273
 
1336
1274
                        UNIV_MEM_INVALID(block[0], sizeof block[0]);
1337
1275
                        merge_buf[i] = row_merge_buf_empty(buf);
1338
1276
 
1339
 
                        if (UNIV_LIKELY(row != NULL)) {
1340
 
                                /* Try writing the record again, now
1341
 
                                that the buffer has been written out
1342
 
                                and emptied. */
1343
 
 
1344
 
                                if (UNIV_UNLIKELY
1345
 
                                    (!row_merge_buf_add(buf, row, ext))) {
1346
 
                                        /* An empty buffer should have enough
1347
 
                                        room for at least one record. */
1348
 
                                        ut_error;
1349
 
                                }
1350
 
 
1351
 
                                file->n_rec++;
 
1277
                        /* Try writing the record again, now that
 
1278
                        the buffer has been written out and emptied. */
 
1279
 
 
1280
                        if (UNIV_UNLIKELY
 
1281
                            (row && !row_merge_buf_add(buf, row, ext))) {
 
1282
                                /* An empty buffer should have enough
 
1283
                                room for at least one record. */
 
1284
                                ut_error;
1352
1285
                        }
1353
1286
                }
1354
1287
 
1387
1320
                b2 = row_merge_write_rec(&block[2], &buf[2], b2,        \
1388
1321
                                         of->fd, &of->offset,           \
1389
1322
                                         mrec##N, offsets##N);          \
1390
 
                if (UNIV_UNLIKELY(!b2 || ++of->n_rec > file->n_rec)) {  \
 
1323
                if (UNIV_UNLIKELY(!b2)) {                               \
1391
1324
                        goto corrupt;                                   \
1392
1325
                }                                                       \
1393
1326
                b##N = row_merge_read_rec(&block[N], &buf[N],           \
1403
1336
        } while (0)
1404
1337
 
1405
1338
/*************************************************************//**
1406
 
Merge two blocks of records on disk and write a bigger block.
 
1339
Merge two blocks of linked lists on disk and write a bigger block.
1407
1340
@return DB_SUCCESS or error code */
1408
1341
static
1409
1342
ulint
1410
1343
row_merge_blocks(
1411
1344
/*=============*/
1412
1345
        const dict_index_t*     index,  /*!< in: index being created */
1413
 
        const merge_file_t*     file,   /*!< in: file containing
 
1346
        merge_file_t*           file,   /*!< in/out: file containing
1414
1347
                                        index entries */
1415
1348
        row_merge_block_t*      block,  /*!< in/out: 3 buffers */
1416
1349
        ulint*                  foffs0, /*!< in/out: offset of first
1418
1351
        ulint*                  foffs1, /*!< in/out: offset of second
1419
1352
                                        source list in the file */
1420
1353
        merge_file_t*           of,     /*!< in/out: output file */
1421
 
        TABLE*          table)  /*!< in/out: MySQL table, for
 
1354
        TABLE*                  table)  /*!< in/out: MySQL table, for
1422
1355
                                        reporting erroneous key value
1423
1356
                                        if applicable */
1424
1357
{
1425
1358
        mem_heap_t*     heap;   /*!< memory heap for offsets0, offsets1 */
1426
1359
 
1427
 
        mrec_buf_t*     buf;    /*!< buffer for handling
1428
 
                                split mrec in block[] */
 
1360
        mrec_buf_t      buf[3]; /*!< buffer for handling split mrec in block[] */
1429
1361
        const byte*     b0;     /*!< pointer to block[0] */
1430
1362
        const byte*     b1;     /*!< pointer to block[1] */
1431
1363
        byte*           b2;     /*!< pointer to block[2] */
1434
1366
        ulint*          offsets0;/* offsets of mrec0 */
1435
1367
        ulint*          offsets1;/* offsets of mrec1 */
1436
1368
 
1437
 
#ifdef UNIV_DEBUG
1438
 
        if (row_merge_print_block) {
1439
 
                fprintf(stderr,
1440
 
                        "row_merge_blocks fd=%d ofs=%lu + fd=%d ofs=%lu"
1441
 
                        " = fd=%d ofs=%lu\n",
1442
 
                        file->fd, (ulong) *foffs0,
1443
 
                        file->fd, (ulong) *foffs1,
1444
 
                        of->fd, (ulong) of->offset);
1445
 
        }
1446
 
#endif /* UNIV_DEBUG */
1447
 
 
1448
 
        heap = row_merge_heap_create(index, &buf, &offsets0, &offsets1);
1449
 
 
1450
 
        buf = static_cast<mrec_buf_t *>(mem_heap_alloc(heap, sizeof(mrec_buf_t) * 3));
 
1369
        heap = row_merge_heap_create(index, &offsets0, &offsets1);
1451
1370
 
1452
1371
        /* Write a record and read the next record.  Split the output
1453
1372
        file in two halves, which can be merged on the following pass. */
1474
1393
        }
1475
1394
 
1476
1395
        while (mrec0 && mrec1) {
1477
 
                ibool   null_eq = FALSE;
1478
1396
                switch (row_merge_cmp(mrec0, mrec1,
1479
 
                                      offsets0, offsets1, index,
1480
 
                                      &null_eq)) {
 
1397
                                      offsets0, offsets1, index)) {
1481
1398
                case 0:
1482
1399
                        if (UNIV_UNLIKELY
1483
 
                            (dict_index_is_unique(index) && !null_eq)) {
 
1400
                            (dict_index_is_unique(index))) {
1484
1401
                                innobase_rec_to_mysql(table, mrec0,
1485
1402
                                                      index, offsets0);
1486
1403
                                mem_heap_free(heap);
1521
1438
}
1522
1439
 
1523
1440
/*************************************************************//**
1524
 
Copy a block of index entries.
1525
 
@return TRUE on success, FALSE on failure */
1526
 
static __attribute__((nonnull))
1527
 
ibool
1528
 
row_merge_blocks_copy(
1529
 
/*==================*/
1530
 
        const dict_index_t*     index,  /*!< in: index being created */
1531
 
        const merge_file_t*     file,   /*!< in: input file */
1532
 
        row_merge_block_t*      block,  /*!< in/out: 3 buffers */
1533
 
        ulint*                  foffs0, /*!< in/out: input file offset */
1534
 
        merge_file_t*           of)     /*!< in/out: output file */
1535
 
{
1536
 
        mem_heap_t*     heap;   /*!< memory heap for offsets0, offsets1 */
1537
 
 
1538
 
        mrec_buf_t*     buf;    /*!< buffer for handling
1539
 
                                split mrec in block[] */
1540
 
        const byte*     b0;     /*!< pointer to block[0] */
1541
 
        byte*           b2;     /*!< pointer to block[2] */
1542
 
        const mrec_t*   mrec0;  /*!< merge rec, points to block[0] */
1543
 
        ulint*          offsets0;/* offsets of mrec0 */
1544
 
        ulint*          offsets1;/* dummy offsets */
1545
 
 
1546
 
#ifdef UNIV_DEBUG
1547
 
        if (row_merge_print_block) {
1548
 
                fprintf(stderr,
1549
 
                        "row_merge_blocks_copy fd=%d ofs=%lu"
1550
 
                        " = fd=%d ofs=%lu\n",
1551
 
                        file->fd, (ulong) foffs0,
1552
 
                        of->fd, (ulong) of->offset);
1553
 
        }
1554
 
#endif /* UNIV_DEBUG */
1555
 
 
1556
 
        heap = row_merge_heap_create(index, &buf, &offsets0, &offsets1);
1557
 
        buf = static_cast<mrec_buf_t *>(mem_heap_alloc(heap, sizeof(mrec_buf_t) * 3));
1558
 
 
1559
 
        /* Write a record and read the next record.  Split the output
1560
 
        file in two halves, which can be merged on the following pass. */
1561
 
 
1562
 
        if (!row_merge_read(file->fd, *foffs0, &block[0])) {
1563
 
corrupt:
1564
 
                mem_heap_free(heap);
1565
 
                return(FALSE);
1566
 
        }
1567
 
 
1568
 
        b0 = block[0];
1569
 
        b2 = block[2];
1570
 
 
1571
 
        b0 = row_merge_read_rec(&block[0], &buf[0], b0, index, file->fd,
1572
 
                                foffs0, &mrec0, offsets0);
1573
 
        if (UNIV_UNLIKELY(!b0 && mrec0)) {
1574
 
 
1575
 
                goto corrupt;
1576
 
        }
1577
 
 
1578
 
        if (mrec0) {
1579
 
                /* append all mrec0 to output */
1580
 
                for (;;) {
1581
 
                        ROW_MERGE_WRITE_GET_NEXT(0, goto done0);
1582
 
                }
1583
 
        }
1584
 
done0:
1585
 
 
1586
 
        /* The file offset points to the beginning of the last page
1587
 
        that has been read.  Update it to point to the next block. */
1588
 
        (*foffs0)++;
1589
 
 
1590
 
        mem_heap_free(heap);
1591
 
        return(row_merge_write_eof(&block[2], b2, of->fd, &of->offset)
1592
 
               != NULL);
1593
 
}
1594
 
 
1595
 
/*************************************************************//**
1596
1441
Merge disk files.
1597
1442
@return DB_SUCCESS or error code */
1598
 
static __attribute__((nonnull))
 
1443
static
1599
1444
ulint
1600
1445
row_merge(
1601
1446
/*======*/
1602
 
        trx_t*                  trx,    /*!< in: transaction */
1603
1447
        const dict_index_t*     index,  /*!< in: index being created */
1604
1448
        merge_file_t*           file,   /*!< in/out: file containing
1605
1449
                                        index entries */
 
1450
        ulint                   half,   /*!< in: half the file */
1606
1451
        row_merge_block_t*      block,  /*!< in/out: 3 buffers */
1607
1452
        int*                    tmpfd,  /*!< in/out: temporary file handle */
1608
 
        TABLE*          table,  /*!< in/out: MySQL table, for
1609
 
                                        reporting erroneous key value
1610
 
                                        if applicable */
1611
 
        ulint*                  num_run,/*!< in/out: Number of runs remain
1612
 
                                        to be merged */
1613
 
        ulint*                  run_offset) /*!< in/out: Array contains the
1614
 
                                        first offset number for each merge
1615
 
                                        run */
 
1453
        TABLE*                  table)  /*!< in/out: MySQL table, for
 
1454
                                        reporting erroneous key value
 
1455
                                        if applicable */
1616
1456
{
1617
1457
        ulint           foffs0; /*!< first input offset */
1618
1458
        ulint           foffs1; /*!< second input offset */
1619
1459
        ulint           error;  /*!< error code */
1620
1460
        merge_file_t    of;     /*!< output file */
1621
 
        const ulint     ihalf   = run_offset[*num_run / 2];
1622
 
                                /*!< half the input file */
1623
 
        ulint           n_run   = 0;
1624
 
                                /*!< num of runs generated from this merge */
1625
 
 
1626
1461
 
1627
1462
        UNIV_MEM_ASSERT_W(block[0], 3 * sizeof block[0]);
1628
 
        ut_ad(ihalf < file->offset);
 
1463
        ut_ad(half > 0);
1629
1464
 
1630
1465
        of.fd = *tmpfd;
1631
1466
        of.offset = 0;
1632
 
        of.n_rec = 0;
1633
 
 
1634
 
#ifdef POSIX_FADV_SEQUENTIAL
1635
 
        /* The input file will be read sequentially, starting from the
1636
 
        beginning and the middle.  In Linux, the POSIX_FADV_SEQUENTIAL
1637
 
        affects the entire file.  Each block will be read exactly once. */
1638
 
        posix_fadvise(file->fd, 0, 0,
1639
 
                      POSIX_FADV_SEQUENTIAL | POSIX_FADV_NOREUSE);
1640
 
#endif /* POSIX_FADV_SEQUENTIAL */
1641
1467
 
1642
1468
        /* Merge blocks to the output file. */
1643
1469
        foffs0 = 0;
1644
 
        foffs1 = ihalf;
1645
 
 
1646
 
        UNIV_MEM_INVALID(run_offset, *num_run * sizeof *run_offset);
1647
 
 
1648
 
        for (; foffs0 < ihalf && foffs1 < file->offset; foffs0++, foffs1++) {
1649
 
 
1650
 
                if (UNIV_UNLIKELY(trx_is_interrupted(trx))) {
1651
 
                        return(DB_INTERRUPTED);
1652
 
                }
1653
 
 
1654
 
                /* Remember the offset number for this run */
1655
 
                run_offset[n_run++] = of.offset;
1656
 
 
 
1470
        foffs1 = half;
 
1471
 
 
1472
        for (; foffs0 < half && foffs1 < file->offset; foffs0++, foffs1++) {
1657
1473
                error = row_merge_blocks(index, file, block,
1658
1474
                                         &foffs0, &foffs1, &of, table);
1659
1475
 
1660
1476
                if (error != DB_SUCCESS) {
1661
1477
                        return(error);
1662
1478
                }
1663
 
 
1664
1479
        }
1665
1480
 
1666
 
        /* Copy the last blocks, if there are any. */
1667
 
 
1668
 
        while (foffs0 < ihalf) {
1669
 
                if (UNIV_UNLIKELY(trx_is_interrupted(trx))) {
1670
 
                        return(DB_INTERRUPTED);
1671
 
                }
1672
 
 
1673
 
                /* Remember the offset number for this run */
1674
 
                run_offset[n_run++] = of.offset;
1675
 
 
1676
 
                if (!row_merge_blocks_copy(index, file, block, &foffs0, &of)) {
 
1481
        /* Copy the last block, if there is one. */
 
1482
        while (foffs0 < half) {
 
1483
                if (!row_merge_read(file->fd, foffs0++, block)
 
1484
                    || !row_merge_write(of.fd, of.offset++, block)) {
1677
1485
                        return(DB_CORRUPTION);
1678
1486
                }
1679
1487
        }
1680
 
 
1681
 
        ut_ad(foffs0 == ihalf);
1682
 
 
1683
1488
        while (foffs1 < file->offset) {
1684
 
                if (UNIV_UNLIKELY(trx_is_interrupted(trx))) {
1685
 
                        return(DB_INTERRUPTED);
1686
 
                }
1687
 
 
1688
 
                /* Remember the offset number for this run */
1689
 
                run_offset[n_run++] = of.offset;
1690
 
 
1691
 
                if (!row_merge_blocks_copy(index, file, block, &foffs1, &of)) {
 
1489
                if (!row_merge_read(file->fd, foffs1++, block)
 
1490
                    || !row_merge_write(of.fd, of.offset++, block)) {
1692
1491
                        return(DB_CORRUPTION);
1693
1492
                }
1694
1493
        }
1695
1494
 
1696
 
        ut_ad(foffs1 == file->offset);
1697
 
 
1698
 
        if (UNIV_UNLIKELY(of.n_rec != file->n_rec)) {
1699
 
                return(DB_CORRUPTION);
1700
 
        }
1701
 
 
1702
 
        ut_ad(n_run <= *num_run);
1703
 
 
1704
 
        *num_run = n_run;
1705
 
 
1706
 
        /* Each run can contain one or more offsets. As merge goes on,
1707
 
        the number of runs (to merge) will reduce until we have one
1708
 
        single run. So the number of runs will always be smaller than
1709
 
        the number of offsets in file */
1710
 
        ut_ad((*num_run) <= file->offset);
1711
 
 
1712
 
        /* The number of offsets in output file is always equal or
1713
 
        smaller than input file */
1714
 
        ut_ad(of.offset <= file->offset);
1715
 
 
1716
1495
        /* Swap file descriptors for the next pass. */
1717
1496
        *tmpfd = file->fd;
1718
1497
        *file = of;
1729
1508
ulint
1730
1509
row_merge_sort(
1731
1510
/*===========*/
1732
 
        trx_t*                  trx,    /*!< in: transaction */
1733
1511
        const dict_index_t*     index,  /*!< in: index being created */
1734
1512
        merge_file_t*           file,   /*!< in/out: file containing
1735
1513
                                        index entries */
1736
1514
        row_merge_block_t*      block,  /*!< in/out: 3 buffers */
1737
1515
        int*                    tmpfd,  /*!< in/out: temporary file handle */
1738
 
        TABLE*          table)  /*!< in/out: MySQL table, for
 
1516
        TABLE*                  table)  /*!< in/out: MySQL table, for
1739
1517
                                        reporting erroneous key value
1740
1518
                                        if applicable */
1741
1519
{
1742
 
        ulint   half = file->offset / 2;
1743
 
        ulint   num_runs;
1744
 
        ulint*  run_offset;
1745
 
        ulint   error = DB_SUCCESS;
1746
 
 
1747
 
        /* Record the number of merge runs we need to perform */
1748
 
        num_runs = file->offset;
1749
 
 
1750
 
        /* If num_runs are less than 1, nothing to merge */
1751
 
        if (num_runs <= 1) {
1752
 
                return(error);
1753
 
        }
1754
 
 
1755
 
        /* "run_offset" records each run's first offset number */
1756
 
        run_offset = (ulint*) mem_alloc(file->offset * sizeof(ulint));
1757
 
 
1758
 
        /* This tells row_merge() where to start for the first round
1759
 
        of merge. */
1760
 
        run_offset[half] = half;
1761
 
 
1762
 
        /* The file should always contain at least one byte (the end
1763
 
        of file marker).  Thus, it must be at least one block. */
1764
 
        ut_ad(file->offset > 0);
1765
 
 
1766
 
        /* Merge the runs until we have one big run */
1767
 
        do {
1768
 
                error = row_merge(trx, index, file, block, tmpfd,
1769
 
                                  table, &num_runs, run_offset);
1770
 
 
1771
 
                UNIV_MEM_ASSERT_RW(run_offset, num_runs * sizeof *run_offset);
 
1520
        ulint   blksz;  /*!< block size */
 
1521
 
 
1522
        for (blksz = 1; blksz < file->offset; blksz *= 2) {
 
1523
                ulint   half;
 
1524
                ulint   error;
 
1525
 
 
1526
                ut_ad(ut_is_2pow(blksz));
 
1527
                half = ut_2pow_round((file->offset + (blksz - 1)) / 2, blksz);
 
1528
                error = row_merge(index, file, half, block, tmpfd, table);
1772
1529
 
1773
1530
                if (error != DB_SUCCESS) {
1774
 
                        break;
 
1531
                        return(error);
1775
1532
                }
1776
 
        } while (num_runs > 1);
1777
 
 
1778
 
        mem_free(run_offset);
1779
 
 
1780
 
        return(error);
 
1533
        }
 
1534
 
 
1535
        return(DB_SUCCESS);
1781
1536
}
1782
1537
 
1783
1538
/*************************************************************//**
1813
1568
                (below). */
1814
1569
                data = btr_rec_copy_externally_stored_field(
1815
1570
                        mrec, offsets, zip_size, i, &len, heap);
1816
 
                /* Because we have locked the table, any records
1817
 
                written by incomplete transactions must have been
1818
 
                rolled back already. There must not be any incomplete
1819
 
                BLOB columns. */
1820
 
                ut_a(data);
1821
1571
 
1822
1572
                dfield_set_data(field, data, len);
1823
1573
        }
1839
1589
        int                     fd,     /*!< in: file descriptor */
1840
1590
        row_merge_block_t*      block)  /*!< in/out: file buffer */
1841
1591
{
 
1592
        mrec_buf_t              buf;
1842
1593
        const byte*             b;
1843
1594
        que_thr_t*              thr;
1844
1595
        ins_node_t*             node;
1857
1608
 
1858
1609
        trx->op_info = "inserting index entries";
1859
1610
 
1860
 
        graph_heap = mem_heap_create(500 + sizeof(mrec_buf_t));
 
1611
        graph_heap = mem_heap_create(500);
1861
1612
        node = ins_node_create(INS_DIRECT, table, graph_heap);
1862
1613
 
1863
1614
        thr = pars_complete_graph_for_exec(node, trx, graph_heap);
1869
1620
        {
1870
1621
                ulint i = 1 + REC_OFFS_HEADER_SIZE
1871
1622
                        + dict_index_get_n_fields(index);
1872
 
                offsets = static_cast<ulint *>(mem_heap_alloc(graph_heap, i * sizeof *offsets));
 
1623
                offsets = mem_heap_alloc(graph_heap, i * sizeof *offsets);
1873
1624
                offsets[0] = i;
1874
1625
                offsets[1] = dict_index_get_n_fields(index);
1875
1626
        }
1879
1630
        if (!row_merge_read(fd, foffs, block)) {
1880
1631
                error = DB_CORRUPTION;
1881
1632
        } else {
1882
 
                mrec_buf_t*     buf = static_cast<mrec_buf_t *>(mem_heap_alloc(graph_heap, sizeof *buf));
1883
 
 
1884
1633
                for (;;) {
1885
1634
                        const mrec_t*   mrec;
1886
1635
                        dtuple_t*       dtuple;
1887
1636
                        ulint           n_ext;
1888
1637
 
1889
 
                        b = row_merge_read_rec(block, buf, b, index,
 
1638
                        b = row_merge_read_rec(block, &buf, b, index,
1890
1639
                                               fd, &foffs, &mrec, offsets);
1891
1640
                        if (UNIV_UNLIKELY(!b)) {
1892
1641
                                /* End of list, or I/O error */
1977
1726
        /* We use the select query graph as the dummy graph needed
1978
1727
        in the lock module call */
1979
1728
 
1980
 
        thr = que_fork_get_first_thr(static_cast<que_fork_t *>(que_node_get_parent(thr)));
 
1729
        thr = que_fork_get_first_thr(que_node_get_parent(thr));
1981
1730
        que_thr_move_to_run_state_for_mysql(thr, trx);
1982
1731
 
1983
1732
run_again:
2007
1756
                        que_node_t*     parent;
2008
1757
 
2009
1758
                        parent = que_node_get_parent(thr);
2010
 
                        run_thr = que_fork_start_command(static_cast<que_fork_t *>(parent));
 
1759
                        run_thr = que_fork_start_command(parent);
2011
1760
 
2012
1761
                        ut_a(run_thr == thr);
2013
1762
 
2048
1797
        static const char str1[] =
2049
1798
                "PROCEDURE DROP_INDEX_PROC () IS\n"
2050
1799
                "BEGIN\n"
2051
 
                /* Rename the index, so that it will be dropped by
2052
 
                row_merge_drop_temp_indexes() at crash recovery
2053
 
                if the server crashes before this trx is committed. */
2054
 
                "UPDATE SYS_INDEXES SET NAME=CONCAT('"
2055
 
                TEMP_INDEX_PREFIX_STR "', NAME) WHERE ID = :indexid;\n"
2056
 
                "COMMIT WORK;\n"
2057
 
                /* Drop the field definitions of the index. */
2058
1800
                "DELETE FROM SYS_FIELDS WHERE INDEX_ID = :indexid;\n"
2059
 
                /* Drop the index definition and the B-tree. */
2060
 
                "DELETE FROM SYS_INDEXES WHERE ID = :indexid;\n"
 
1801
                "DELETE FROM SYS_INDEXES WHERE ID = :indexid\n"
 
1802
                "               AND TABLE_ID = :tableid;\n"
2061
1803
                "END;\n";
2062
1804
 
2063
1805
        ut_ad(index && table && trx);
2064
1806
 
2065
 
        pars_info_add_ull_literal(info, "indexid", index->id);
 
1807
        pars_info_add_dulint_literal(info, "indexid", index->id);
 
1808
        pars_info_add_dulint_literal(info, "tableid", table->id);
2066
1809
 
2067
1810
        trx_start_if_not_started(trx);
2068
1811
        trx->op_info = "dropping index";
2076
1819
        /* Replace this index with another equivalent index for all
2077
1820
        foreign key constraints on this table where this index is used */
2078
1821
 
2079
 
        dict_table_replace_index_in_foreign_list(table, index, trx);
 
1822
        dict_table_replace_index_in_foreign_list(table, index);
2080
1823
        dict_index_remove_from_cache(table, index);
2081
1824
 
2082
1825
        trx->op_info = "";
2111
1854
/*=============================*/
2112
1855
{
2113
1856
        trx_t*          trx;
2114
 
        btr_pcur_t      pcur;
2115
 
        mtr_t           mtr;
 
1857
        ulint           err;
2116
1858
 
2117
 
        /* Load the table definitions that contain partially defined
2118
 
        indexes, so that the data dictionary information can be checked
2119
 
        when accessing the tablename.ibd files. */
 
1859
        /* We use the private SQL parser of Innobase to generate the
 
1860
        query graphs needed in deleting the dictionary data from system
 
1861
        tables in Innobase. Deleting a row from SYS_INDEXES table also
 
1862
        frees the file segments of the B-tree associated with the index. */
 
1863
        static const char drop_temp_indexes[] =
 
1864
                "PROCEDURE DROP_TEMP_INDEXES_PROC () IS\n"
 
1865
                "indexid CHAR;\n"
 
1866
                "DECLARE CURSOR c IS SELECT ID FROM SYS_INDEXES\n"
 
1867
                "WHERE SUBSTR(NAME,0,1)='" TEMP_INDEX_PREFIX_STR "';\n"
 
1868
                "BEGIN\n"
 
1869
                "\tOPEN c;\n"
 
1870
                "\tWHILE 1=1 LOOP\n"
 
1871
                "\t\tFETCH c INTO indexid;\n"
 
1872
                "\t\tIF (SQL % NOTFOUND) THEN\n"
 
1873
                "\t\t\tEXIT;\n"
 
1874
                "\t\tEND IF;\n"
 
1875
                "\t\tDELETE FROM SYS_FIELDS WHERE INDEX_ID = indexid;\n"
 
1876
                "\t\tDELETE FROM SYS_INDEXES WHERE ID = indexid;\n"
 
1877
                "\tEND LOOP;\n"
 
1878
                "\tCLOSE c;\n"
 
1879
                "\tCOMMIT WORK;\n"
 
1880
                "END;\n";
2120
1881
 
2121
1882
        trx = trx_allocate_for_background();
2122
1883
        trx->op_info = "dropping partially created indexes";
2123
1884
        row_mysql_lock_data_dictionary(trx);
2124
1885
 
2125
 
        mtr_start(&mtr);
2126
 
 
2127
 
        btr_pcur_open_at_index_side(
2128
 
                TRUE,
2129
 
                dict_table_get_first_index(dict_sys->sys_indexes),
2130
 
                BTR_SEARCH_LEAF, &pcur, TRUE, &mtr);
2131
 
 
2132
 
        for (;;) {
2133
 
                const rec_t*    rec;
2134
 
                const byte*     field;
2135
 
                ulint           len;
2136
 
                table_id_t      table_id;
2137
 
                dict_table_t*   table;
2138
 
 
2139
 
                btr_pcur_move_to_next_user_rec(&pcur, &mtr);
2140
 
 
2141
 
                if (!btr_pcur_is_on_user_rec(&pcur)) {
2142
 
                        break;
2143
 
                }
2144
 
 
2145
 
                rec = btr_pcur_get_rec(&pcur);
2146
 
                field = rec_get_nth_field_old(rec, DICT_SYS_INDEXES_NAME_FIELD,
2147
 
                                              &len);
2148
 
                if (len == UNIV_SQL_NULL || len == 0
2149
 
                    || (char) *field != TEMP_INDEX_PREFIX) {
2150
 
                        continue;
2151
 
                }
2152
 
 
2153
 
                /* This is a temporary index. */
2154
 
 
2155
 
                field = rec_get_nth_field_old(rec, 0/*TABLE_ID*/, &len);
2156
 
                if (len != 8) {
2157
 
                        /* Corrupted TABLE_ID */
2158
 
                        continue;
2159
 
                }
2160
 
 
2161
 
                table_id = mach_read_from_8(field);
2162
 
 
2163
 
                btr_pcur_store_position(&pcur, &mtr);
2164
 
                btr_pcur_commit_specify_mtr(&pcur, &mtr);
2165
 
 
2166
 
                table = dict_table_get_on_id_low(table_id);
2167
 
 
2168
 
                if (table) {
2169
 
                        dict_index_t*   index;
2170
 
                        dict_index_t*   next_index;
2171
 
 
2172
 
                        for (index = dict_table_get_first_index(table);
2173
 
                             index; index = next_index) {
2174
 
 
2175
 
                                next_index = dict_table_get_next_index(index);
2176
 
 
2177
 
                                if (*index->name == TEMP_INDEX_PREFIX) {
2178
 
                                        row_merge_drop_index(index, table, trx);
2179
 
                                        trx_commit_for_mysql(trx);
2180
 
                                }
2181
 
                        }
2182
 
                }
2183
 
 
2184
 
                mtr_start(&mtr);
2185
 
                btr_pcur_restore_position(BTR_SEARCH_LEAF,
2186
 
                                          &pcur, &mtr);
2187
 
        }
2188
 
 
2189
 
        btr_pcur_close(&pcur);
2190
 
        mtr_commit(&mtr);
 
1886
        /* Incomplete transactions may be holding some locks on the
 
1887
        data dictionary tables.  However, they should never have been
 
1888
        able to lock the records corresponding to the partially
 
1889
        created indexes that we are attempting to delete, because the
 
1890
        table was locked when the indexes were being created.  We will
 
1891
        drop the partially created indexes before the rollback of
 
1892
        incomplete transactions is initiated.  Thus, this should not
 
1893
        interfere with the incomplete transactions. */
 
1894
        trx->isolation_level = TRX_ISO_READ_UNCOMMITTED;
 
1895
        err = que_eval_sql(NULL, drop_temp_indexes, FALSE, trx);
 
1896
        ut_a(err == DB_SUCCESS);
 
1897
 
2191
1898
        row_mysql_unlock_data_dictionary(trx);
2192
1899
        trx_free_for_background(trx);
2193
1900
}
2200
1907
/*==================*/
2201
1908
        merge_file_t*   merge_file)     /*!< out: merge file structure */
2202
1909
{
2203
 
#ifdef UNIV_PFS_IO
2204
 
        /* This temp file open does not go through normal
2205
 
        file APIs, add instrumentation to register with
2206
 
        performance schema */
2207
 
        struct PSI_file_locker* locker = NULL;
2208
 
        PSI_file_locker_state   state;
2209
 
        register_pfs_file_open_begin(&state, locker, innodb_file_temp_key,
2210
 
                                     PSI_FILE_OPEN,
2211
 
                                     "Innodb Merge Temp File",
2212
 
                                     __FILE__, __LINE__);
2213
 
#endif
2214
1910
        merge_file->fd = innobase_mysql_tmpfile();
2215
1911
        merge_file->offset = 0;
2216
 
        merge_file->n_rec = 0;
2217
 
#ifdef UNIV_PFS_IO
2218
 
        register_pfs_file_open_end(locker, merge_file->fd);
2219
 
#endif
2220
1912
}
2221
1913
 
2222
1914
/*********************************************************************//**
2227
1919
/*===================*/
2228
1920
        merge_file_t*   merge_file)     /*!< out: merge file structure */
2229
1921
{
2230
 
#ifdef UNIV_PFS_IO
2231
 
        struct PSI_file_locker* locker = NULL;
2232
 
        PSI_file_locker_state   state;
2233
 
        register_pfs_file_io_begin(&state, locker, merge_file->fd, 0, PSI_FILE_CLOSE,
2234
 
                                   __FILE__, __LINE__);
2235
 
#endif
2236
1922
        if (merge_file->fd != -1) {
2237
1923
                close(merge_file->fd);
2238
1924
                merge_file->fd = -1;
2239
1925
        }
2240
 
 
2241
 
#ifdef UNIV_PFS_IO
2242
 
        register_pfs_file_io_end(locker, 0);
2243
 
#endif
2244
1926
}
2245
1927
 
2246
1928
/*********************************************************************//**
2362
2044
 
2363
2045
        trx->op_info = "renaming indexes";
2364
2046
 
2365
 
        pars_info_add_ull_literal(info, "tableid", table->id);
 
2047
        pars_info_add_dulint_literal(info, "tableid", table->id);
2366
2048
 
2367
2049
        err = que_eval_sql(info, rename_indexes, FALSE, trx);
2368
2050
 
2399
2081
{
2400
2082
        ulint           err     = DB_ERROR;
2401
2083
        pars_info_t*    info;
2402
 
        char            old_name[MAX_TABLE_NAME_LEN + 1];
 
2084
        const char*     old_name= old_table->name;
2403
2085
 
2404
2086
        ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
2405
2087
        ut_ad(old_table != new_table);
2407
2089
 
2408
2090
        ut_a(trx->dict_operation_lock_mode == RW_X_LATCH);
2409
2091
 
2410
 
        /* store the old/current name to an automatic variable */
2411
 
        if (strlen(old_table->name) + 1 <= sizeof(old_name)) {
2412
 
                memcpy(old_name, old_table->name, strlen(old_table->name) + 1);
2413
 
        } else {
2414
 
                ut_print_timestamp(stderr);
2415
 
                fprintf(stderr, "InnoDB: too long table name: '%s', "
2416
 
                        "max length is %d\n", old_table->name,
2417
 
                        MAX_TABLE_NAME_LEN);
2418
 
                ut_error;
2419
 
        }
2420
 
 
2421
 
        /* store the old/current name to an automatic variable */
2422
 
        if (strlen(old_table->name) + 1 <= sizeof(old_name)) {
2423
 
                memcpy(old_name, old_table->name, strlen(old_table->name) + 1);
2424
 
        } else {
2425
 
                ut_print_timestamp(stderr);
2426
 
                fprintf(stderr, "InnoDB: too long table name: '%s', "
2427
 
                        "max length is %d\n", old_table->name,
2428
 
                        MAX_TABLE_NAME_LEN);
2429
 
                ut_error;
2430
 
        }
2431
 
 
2432
2092
        trx->op_info = "renaming tables";
2433
2093
 
2434
2094
        /* We use the private SQL parser of Innobase to generate the query
2464
2124
                goto err_exit;
2465
2125
        }
2466
2126
 
2467
 
        err = dict_load_foreigns(old_name, FALSE, TRUE);
 
2127
        err = dict_load_foreigns(old_name, TRUE);
2468
2128
 
2469
2129
        if (err != DB_SUCCESS) {
2470
2130
err_exit:
2471
2131
                trx->error_state = DB_SUCCESS;
2472
 
                trx_general_rollback_for_mysql(trx, NULL);
 
2132
                trx_general_rollback_for_mysql(trx, FALSE, NULL);
2473
2133
                trx->error_state = DB_SUCCESS;
2474
2134
        }
2475
2135
 
2504
2164
        node = ind_create_graph_create(index, heap);
2505
2165
        thr = pars_complete_graph_for_exec(node, trx, heap);
2506
2166
 
2507
 
        ut_a(thr == que_fork_start_command(static_cast<que_fork_t *>(que_node_get_parent(thr))));
 
2167
        ut_a(thr == que_fork_start_command(que_node_get_parent(thr)));
2508
2168
 
2509
2169
        que_run_threads(thr);
2510
2170
 
2561
2221
                /* Note the id of the transaction that created this
2562
2222
                index, we use it to restrict readers from accessing
2563
2223
                this index, to ensure read consistency. */
2564
 
                index->trx_id = trx->id;
 
2224
                index->trx_id = (ib_uint64_t)
 
2225
                        ut_conv_dulint_to_longlong(trx->id);
2565
2226
        } else {
2566
2227
                index = NULL;
2567
2228
        }
2578
2239
        const trx_t*            trx,    /*!< in: transaction */
2579
2240
        const dict_index_t*     index)  /*!< in: index to check */
2580
2241
{
2581
 
        return(!trx->read_view
2582
 
               || read_view_sees_trx_id(trx->read_view, index->trx_id));
 
2242
        return(!trx->read_view || read_view_sees_trx_id(
 
2243
                       trx->read_view,
 
2244
                       ut_dulint_create((ulint) (index->trx_id >> 32),
 
2245
                                        (ulint) index->trx_id & 0xFFFFFFFF)));
2583
2246
}
2584
2247
 
2585
2248
/*********************************************************************//**
2615
2278
                                        unless creating a PRIMARY KEY */
2616
2279
        dict_index_t**  indexes,        /*!< in: indexes to be created */
2617
2280
        ulint           n_indexes,      /*!< in: size of indexes[] */
2618
 
        TABLE*  table)          /*!< in/out: MySQL table, for
 
2281
        TABLE*          table)          /*!< in/out: MySQL table, for
2619
2282
                                        reporting erroneous key value
2620
2283
                                        if applicable */
2621
2284
{
2637
2300
        /* Allocate memory for merge file data structure and initialize
2638
2301
        fields */
2639
2302
 
2640
 
        merge_files = static_cast<merge_file_t *>(mem_alloc(n_indexes * sizeof *merge_files));
 
2303
        merge_files = mem_alloc(n_indexes * sizeof *merge_files);
2641
2304
        block_size = 3 * sizeof *block;
2642
 
        block = static_cast<row_merge_block_t *>(os_mem_alloc_large(&block_size));
 
2305
        block = os_mem_alloc_large(&block_size);
2643
2306
 
2644
2307
        for (i = 0; i < n_indexes; i++) {
2645
2308
 
2668
2331
        sorting and inserting. */
2669
2332
 
2670
2333
        for (i = 0; i < n_indexes; i++) {
2671
 
                error = row_merge_sort(trx, indexes[i], &merge_files[i],
 
2334
                error = row_merge_sort(indexes[i], &merge_files[i],
2672
2335
                                       block, &tmpfd, table);
2673
2336
 
2674
2337
                if (error == DB_SUCCESS) {