339
339
if (ifield->prefix_len) {
340
340
len = dtype_get_at_most_n_mbchars(
342
col->mbminlen, col->mbmaxlen,
343
343
ifield->prefix_len,
344
344
len, dfield_get_data(field));
345
345
dfield_set_len(field, len);
1603
1603
const dict_index_t* index, /*!< in: index being created */
1604
1604
merge_file_t* file, /*!< in/out: file containing
1605
1605
index entries */
1606
ulint* half, /*!< in/out: half the file */
1607
1606
row_merge_block_t* block, /*!< in/out: 3 buffers */
1608
1607
int* tmpfd, /*!< in/out: temporary file handle */
1609
struct TABLE* table) /*!< in/out: MySQL table, for
1610
reporting erroneous key value
1608
struct TABLE* table, /*!< in/out: MySQL table, for
1609
reporting erroneous key value
1611
ulint* num_run,/*!< in/out: Number of runs remain
1613
ulint* run_offset) /*!< in/out: Array contains the
1614
first offset number for each merge
1613
1617
ulint foffs0; /*!< first input offset */
1614
1618
ulint foffs1; /*!< second input offset */
1615
1619
ulint error; /*!< error code */
1616
1620
merge_file_t of; /*!< output file */
1617
const ulint ihalf = *half;
1621
const ulint ihalf = run_offset[*num_run / 2];
1618
1622
/*!< half the input file */
1619
ulint ohalf; /*!< half the output file */
1624
/*!< num of runs generated from this merge */
1621
1627
UNIV_MEM_ASSERT_W(block[0], 3 * sizeof block[0]);
1622
1628
ut_ad(ihalf < file->offset);
1634
1640
#endif /* POSIX_FADV_SEQUENTIAL */
1636
1642
/* Merge blocks to the output file. */
1639
1644
foffs1 = ihalf;
1646
UNIV_MEM_INVALID(run_offset, *num_run * sizeof *run_offset);
1641
1648
for (; foffs0 < ihalf && foffs1 < file->offset; foffs0++, foffs1++) {
1642
ulint ahalf; /*!< arithmetic half the input file */
1644
1650
if (UNIV_UNLIKELY(trx_is_interrupted(trx))) {
1645
1651
return(DB_INTERRUPTED);
1654
/* Remember the offset number for this run */
1655
run_offset[n_run++] = of.offset;
1648
1657
error = row_merge_blocks(index, file, block,
1649
1658
&foffs0, &foffs1, &of, table);
1655
/* Record the offset of the output file when
1656
approximately half the output has been generated. In
1657
this way, the next invocation of row_merge() will
1658
spend most of the time in this loop. The initial
1659
estimate is ohalf==0. */
1660
ahalf = file->offset / 2;
1661
ut_ad(ohalf <= of.offset);
1663
/* Improve the estimate until reaching half the input
1664
file size, or we can not get any closer to it. All
1665
comparands should be non-negative when !(ohalf < ahalf)
1666
because ohalf <= of.offset. */
1667
if (ohalf < ahalf || of.offset - ahalf < ohalf - ahalf) {
1672
1666
/* Copy the last blocks, if there are any. */
1676
1670
return(DB_INTERRUPTED);
1673
/* Remember the offset number for this run */
1674
run_offset[n_run++] = of.offset;
1679
1676
if (!row_merge_blocks_copy(index, file, block, &foffs0, &of)) {
1680
1677
return(DB_CORRUPTION);
1688
1685
return(DB_INTERRUPTED);
1688
/* Remember the offset number for this run */
1689
run_offset[n_run++] = of.offset;
1691
1691
if (!row_merge_blocks_copy(index, file, block, &foffs1, &of)) {
1692
1692
return(DB_CORRUPTION);
1699
1699
return(DB_CORRUPTION);
1702
ut_ad(n_run <= *num_run);
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);
1712
/* The number of offsets in output file is always equal or
1713
smaller than input file */
1714
ut_ad(of.offset <= file->offset);
1702
1716
/* Swap file descriptors for the next pass. */
1703
1717
*tmpfd = file->fd;
1707
1720
UNIV_MEM_INVALID(block[0], 3 * sizeof block[0]);
1727
1740
if applicable */
1729
1742
ulint half = file->offset / 2;
1745
ulint error = DB_SUCCESS;
1747
/* Record the number of merge runs we need to perform */
1748
num_runs = file->offset;
1750
/* If num_runs are less than 1, nothing to merge */
1751
if (num_runs <= 1) {
1755
/* "run_offset" records each run's first offset number */
1756
run_offset = (ulint*) mem_alloc(file->offset * sizeof(ulint));
1758
/* This tells row_merge() where to start for the first round
1760
run_offset[half] = half;
1731
1762
/* The file should always contain at least one byte (the end
1732
1763
of file marker). Thus, it must be at least one block. */
1733
1764
ut_ad(file->offset > 0);
1766
/* Merge the runs until we have one big run */
1768
error = row_merge(trx, index, file, block, tmpfd,
1769
table, &num_runs, run_offset);
1738
error = row_merge(trx, index, file, &half,
1739
block, tmpfd, table);
1771
UNIV_MEM_ASSERT_RW(run_offset, num_runs * sizeof *run_offset);
1741
1773
if (error != DB_SUCCESS) {
1745
/* half > 0 should hold except when the file consists
1746
of one block. No need to merge further then. */
1747
ut_ad(half > 0 || file->offset == 1);
1748
} while (half < file->offset && half > 0);
1776
} while (num_runs > 1);
1778
mem_free(run_offset);
1753
1783
/*************************************************************//**
1784
1814
data = btr_rec_copy_externally_stored_field(
1785
1815
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
1787
1822
dfield_set_data(field, data, len);
2028
2063
ut_ad(index && table && trx);
2030
pars_info_add_dulint_literal(info, "indexid", index->id);
2065
pars_info_add_ull_literal(info, "indexid", index->id);
2032
2067
trx_start_if_not_started(trx);
2033
2068
trx->op_info = "dropping index";
2169
2204
/* This temp file open does not go through normal
2170
2205
file APIs, add instrumentation to register with
2171
2206
performance schema */
2172
struct PSI_file_locker* locker = NULL;
2173
register_pfs_file_open_begin(locker, innodb_file_temp_key,
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,
2175
2211
"Innodb Merge Temp File",
2176
2212
__FILE__, __LINE__);
2192
2228
merge_file_t* merge_file) /*!< out: merge file structure */
2194
2230
#ifdef UNIV_PFS_IO
2195
struct PSI_file_locker* locker = NULL;
2196
register_pfs_file_io_begin(locker, merge_file->fd, 0, PSI_FILE_CLOSE,
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,
2197
2234
__FILE__, __LINE__);
2199
2236
if (merge_file->fd != -1) {
2326
2363
trx->op_info = "renaming indexes";
2328
pars_info_add_dulint_literal(info, "tableid", table->id);
2365
pars_info_add_ull_literal(info, "tableid", table->id);
2330
2367
err = que_eval_sql(info, rename_indexes, FALSE, trx);
2371
2408
ut_a(trx->dict_operation_lock_mode == RW_X_LATCH);
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);
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);
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);
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);
2373
2432
trx->op_info = "renaming tables";
2375
2434
/* We use the private SQL parser of Innobase to generate the query
2502
2561
/* Note the id of the transaction that created this
2503
2562
index, we use it to restrict readers from accessing
2504
2563
this index, to ensure read consistency. */
2505
index->trx_id = (ib_uint64_t)
2506
ut_conv_dulint_to_longlong(trx->id);
2564
index->trx_id = trx->id;
2520
2578
const trx_t* trx, /*!< in: transaction */
2521
2579
const dict_index_t* index) /*!< in: index to check */
2523
return(!trx->read_view || read_view_sees_trx_id(
2525
ut_dulint_create((ulint) (index->trx_id >> 32),
2526
(ulint) index->trx_id & 0xFFFFFFFF)));
2581
return(!trx->read_view
2582
|| read_view_sees_trx_id(trx->read_view, index->trx_id));
2529
2585
/*********************************************************************//**