|
|
@ -1241,47 +1241,95 @@ row_merge_write_eof( |
|
|
|
return(&block[0]); |
|
|
|
} |
|
|
|
|
|
|
|
/********************************************************************//**
|
|
|
|
Reads clustered index of the table and create temporary files |
|
|
|
/** Create a temporary file if it has not been created already.
|
|
|
|
@param[in,out] tmpfd temporary file handle |
|
|
|
@param[in] path path to create temporary file |
|
|
|
@return file descriptor, or -1 on failure */ |
|
|
|
static __attribute__((warn_unused_result)) |
|
|
|
int |
|
|
|
row_merge_tmpfile_if_needed( |
|
|
|
int* tmpfd, |
|
|
|
const char* path) |
|
|
|
{ |
|
|
|
if (*tmpfd < 0) { |
|
|
|
*tmpfd = row_merge_file_create_low(path); |
|
|
|
} |
|
|
|
|
|
|
|
return(*tmpfd); |
|
|
|
} |
|
|
|
|
|
|
|
/** Create a temporary file for merge sort if it was not created already.
|
|
|
|
@param[in,out] file merge file structure |
|
|
|
@param[in,out] tmpfd temporary file structure |
|
|
|
@param[in] nrec number of records in the file |
|
|
|
@param[in] path path to create temporary files |
|
|
|
@return file descriptor, or -1 on failure */ |
|
|
|
static __attribute__((warn_unused_result)) |
|
|
|
int |
|
|
|
row_merge_file_create_if_needed( |
|
|
|
merge_file_t* file, |
|
|
|
int* tmpfd, |
|
|
|
ulint nrec, |
|
|
|
const char* path) |
|
|
|
{ |
|
|
|
ut_ad(file->fd < 0 || *tmpfd >=0); |
|
|
|
if (file->fd < 0 && row_merge_file_create(file, path) >= 0) { |
|
|
|
if (row_merge_tmpfile_if_needed(tmpfd, path) < 0) { |
|
|
|
return(-1); |
|
|
|
} |
|
|
|
|
|
|
|
file->n_rec = nrec; |
|
|
|
} |
|
|
|
|
|
|
|
ut_ad(file->fd < 0 || *tmpfd >=0); |
|
|
|
return(file->fd); |
|
|
|
} |
|
|
|
|
|
|
|
/** Reads clustered index of the table and create temporary files
|
|
|
|
containing the index entries for the indexes to be built. |
|
|
|
@return DB_SUCCESS or error */ |
|
|
|
@param[in] trx transaction |
|
|
|
@param[in,out] table MySQL table object, for reporting erroneous |
|
|
|
records |
|
|
|
@param[in] old_table table where rows are read from |
|
|
|
@param[in] new_table table where indexes are created; identical to |
|
|
|
old_table unless creating a PRIMARY KEY |
|
|
|
@param[in] online true if creating indexes online |
|
|
|
@param[in] index indexes to be created |
|
|
|
@param[in] fts_sort_idx full-text index to be created, or NULL |
|
|
|
@param[in] psort_info parallel sort info for fts_sort_idx creation, |
|
|
|
or NULL |
|
|
|
@param[in] files temporary files |
|
|
|
@param[in] key_numbers MySQL key numbers to create |
|
|
|
@param[in] n_index number of indexes to create |
|
|
|
@param[in] add_cols default values of added columns, or NULL |
|
|
|
@param[in] col_map mapping of old column numbers to new ones, or |
|
|
|
NULL if old_table == new_table |
|
|
|
@param[in] add_autoinc number of added AUTO_INCREMENT columns, or |
|
|
|
ULINT_UNDEFINED if none is added |
|
|
|
@param[in,out] sequence autoinc sequence |
|
|
|
@param[in,out] block file buffer |
|
|
|
@param[in,out] tmpfd temporary file handle |
|
|
|
return DB_SUCCESS or error */ |
|
|
|
static __attribute__((nonnull(1,2,3,4,6,9,10,16), warn_unused_result)) |
|
|
|
dberr_t |
|
|
|
row_merge_read_clustered_index( |
|
|
|
/*===========================*/ |
|
|
|
trx_t* trx, /*!< in: transaction */ |
|
|
|
struct TABLE* table, /*!< in/out: MySQL table object,
|
|
|
|
for reporting erroneous records */ |
|
|
|
const dict_table_t* old_table,/*!< in: table where rows are
|
|
|
|
read from */ |
|
|
|
const dict_table_t* new_table,/*!< in: table where indexes are
|
|
|
|
created; identical to old_table |
|
|
|
unless creating a PRIMARY KEY */ |
|
|
|
bool online, /*!< in: true if creating indexes
|
|
|
|
online */ |
|
|
|
dict_index_t** index, /*!< in: indexes to be created */ |
|
|
|
trx_t* trx, |
|
|
|
struct TABLE* table, |
|
|
|
const dict_table_t* old_table, |
|
|
|
const dict_table_t* new_table, |
|
|
|
bool online, |
|
|
|
dict_index_t** index, |
|
|
|
dict_index_t* fts_sort_idx, |
|
|
|
/*!< in: full-text index to be created,
|
|
|
|
or NULL */ |
|
|
|
fts_psort_t* psort_info, |
|
|
|
/*!< in: parallel sort info for
|
|
|
|
fts_sort_idx creation, or NULL */ |
|
|
|
merge_file_t* files, /*!< in: temporary files */ |
|
|
|
merge_file_t* files, |
|
|
|
const ulint* key_numbers, |
|
|
|
/*!< in: MySQL key numbers to create */ |
|
|
|
ulint n_index,/*!< in: number of indexes to create */ |
|
|
|
ulint n_index, |
|
|
|
const dtuple_t* add_cols, |
|
|
|
/*!< in: default values of
|
|
|
|
added columns, or NULL */ |
|
|
|
const ulint* col_map,/*!< in: mapping of old column
|
|
|
|
numbers to new ones, or NULL |
|
|
|
if old_table == new_table */ |
|
|
|
const ulint* col_map, |
|
|
|
ulint add_autoinc, |
|
|
|
/*!< in: number of added
|
|
|
|
AUTO_INCREMENT column, or |
|
|
|
ULINT_UNDEFINED if none is added */ |
|
|
|
ib_sequence_t& sequence,/*!< in/out: autoinc sequence */ |
|
|
|
row_merge_block_t* block) /*!< in/out: file buffer */ |
|
|
|
ib_sequence_t& sequence, |
|
|
|
row_merge_block_t* block, |
|
|
|
int* tmpfd) |
|
|
|
{ |
|
|
|
dict_index_t* clust_index; /* Clustered index */ |
|
|
|
mem_heap_t* row_heap; /* Heap memory to create
|
|
|
@ -1313,6 +1361,9 @@ row_merge_read_clustered_index( |
|
|
|
DEBUG_FTS_SORT_PRINT("FTS_SORT: Start Create Index\n"); |
|
|
|
#endif
|
|
|
|
|
|
|
|
ut_ad(trx->mysql_thd != NULL); |
|
|
|
const char* path = thd_innodb_tmpdir(trx->mysql_thd); |
|
|
|
|
|
|
|
/* Create and initialize memory for record buffers */ |
|
|
|
|
|
|
|
merge_buf = static_cast<row_merge_buf_t**>( |
|
|
@ -1777,13 +1828,25 @@ write_buffers: |
|
|
|
dict_index_get_lock(buf->index)); |
|
|
|
} |
|
|
|
|
|
|
|
row_merge_buf_write(buf, file, block); |
|
|
|
if (buf->n_tuples > 0) { |
|
|
|
|
|
|
|
if (!row_merge_write(file->fd, file->offset++, |
|
|
|
block)) { |
|
|
|
err = DB_TEMP_FILE_WRITE_FAILURE; |
|
|
|
trx->error_key_num = i; |
|
|
|
break; |
|
|
|
if (row_merge_file_create_if_needed( |
|
|
|
file, tmpfd, buf->n_tuples, path) < 0) { |
|
|
|
err = DB_OUT_OF_MEMORY; |
|
|
|
trx->error_key_num = i; |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
ut_ad(file->n_rec > 0); |
|
|
|
|
|
|
|
row_merge_buf_write(buf, file, block); |
|
|
|
|
|
|
|
if (!row_merge_write(file->fd, file->offset++, |
|
|
|
block)) { |
|
|
|
err = DB_TEMP_FILE_WRITE_FAILURE; |
|
|
|
trx->error_key_num = i; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
UNIV_MEM_INVALID(&block[0], srv_sort_buf_size); |
|
|
@ -1827,6 +1890,7 @@ write_buffers: |
|
|
|
|
|
|
|
func_exit: |
|
|
|
mtr_commit(&mtr); |
|
|
|
|
|
|
|
mem_heap_free(row_heap); |
|
|
|
|
|
|
|
if (nonnull) { |
|
|
@ -3039,14 +3103,15 @@ row_merge_drop_temp_indexes(void) |
|
|
|
trx_free_for_background(trx); |
|
|
|
} |
|
|
|
|
|
|
|
/*********************************************************************//**
|
|
|
|
Creates temporary merge files, and if UNIV_PFS_IO defined, register |
|
|
|
the file descriptor with Performance Schema. |
|
|
|
@return file descriptor, or -1 on failure */ |
|
|
|
|
|
|
|
/** Create temporary merge files in the given paramater path, and if
|
|
|
|
UNIV_PFS_IO defined, register the file descriptor with Performance Schema. |
|
|
|
@param[in] path location for creating temporary merge files. |
|
|
|
@return File descriptor */ |
|
|
|
UNIV_INTERN |
|
|
|
int |
|
|
|
row_merge_file_create_low(void) |
|
|
|
/*===========================*/ |
|
|
|
row_merge_file_create_low( |
|
|
|
const char* path) |
|
|
|
{ |
|
|
|
int fd; |
|
|
|
#ifdef UNIV_PFS_IO
|
|
|
@ -3060,7 +3125,7 @@ row_merge_file_create_low(void) |
|
|
|
"Innodb Merge Temp File", |
|
|
|
__FILE__, __LINE__); |
|
|
|
#endif
|
|
|
|
fd = innobase_mysql_tmpfile(); |
|
|
|
fd = innobase_mysql_tmpfile(path); |
|
|
|
#ifdef UNIV_PFS_IO
|
|
|
|
register_pfs_file_open_end(locker, fd); |
|
|
|
#endif
|
|
|
@ -3073,16 +3138,18 @@ row_merge_file_create_low(void) |
|
|
|
return(fd); |
|
|
|
} |
|
|
|
|
|
|
|
/*********************************************************************//**
|
|
|
|
Create a merge file. |
|
|
|
|
|
|
|
/** Create a merge file in the given location.
|
|
|
|
@param[out] merge_file merge file structure |
|
|
|
@param[in] path location for creating temporary file |
|
|
|
@return file descriptor, or -1 on failure */ |
|
|
|
UNIV_INTERN |
|
|
|
int |
|
|
|
row_merge_file_create( |
|
|
|
/*==================*/ |
|
|
|
merge_file_t* merge_file) /*!< out: merge file structure */ |
|
|
|
merge_file_t* merge_file, |
|
|
|
const char* path) |
|
|
|
{ |
|
|
|
merge_file->fd = row_merge_file_create_low(); |
|
|
|
merge_file->fd = row_merge_file_create_low(path); |
|
|
|
merge_file->offset = 0; |
|
|
|
merge_file->n_rec = 0; |
|
|
|
|
|
|
@ -3598,10 +3665,6 @@ row_merge_build_indexes( |
|
|
|
} |
|
|
|
|
|
|
|
for (i = 0; i < n_indexes; i++) { |
|
|
|
if (row_merge_file_create(&merge_files[i]) < 0) { |
|
|
|
error = DB_OUT_OF_MEMORY; |
|
|
|
goto func_exit; |
|
|
|
} |
|
|
|
|
|
|
|
if (indexes[i]->type & DICT_FTS) { |
|
|
|
ibool opt_doc_id_size = FALSE; |
|
|
@ -3630,13 +3693,6 @@ row_merge_build_indexes( |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
tmpfd = row_merge_file_create_low(); |
|
|
|
|
|
|
|
if (tmpfd < 0) { |
|
|
|
error = DB_OUT_OF_MEMORY; |
|
|
|
goto func_exit; |
|
|
|
} |
|
|
|
|
|
|
|
/* Reset the MySQL row buffer that is used when reporting
|
|
|
|
duplicate keys. */ |
|
|
|
innobase_rec_reset(table); |
|
|
@ -3648,7 +3704,7 @@ row_merge_build_indexes( |
|
|
|
trx, table, old_table, new_table, online, indexes, |
|
|
|
fts_sort_idx, psort_info, merge_files, key_numbers, |
|
|
|
n_indexes, add_cols, col_map, |
|
|
|
add_autoinc, sequence, block); |
|
|
|
add_autoinc, sequence, block, &tmpfd); |
|
|
|
|
|
|
|
if (error != DB_SUCCESS) { |
|
|
|
|
|
|
@ -3729,7 +3785,7 @@ wait_again: |
|
|
|
#ifdef FTS_INTERNAL_DIAG_PRINT
|
|
|
|
DEBUG_FTS_SORT_PRINT("FTS_SORT: Complete Insert\n"); |
|
|
|
#endif
|
|
|
|
} else { |
|
|
|
} else if (merge_files[i].fd != -1) { |
|
|
|
row_merge_dup_t dup = { |
|
|
|
sort_idx, table, col_map, 0}; |
|
|
|
|
|
|
|