26 #ifndef UNIV_HOTBACKUP 
  117 #define TABLE_STATS_NAME        "mysql/innodb_table_stats" 
  118 #define TABLE_STATS_NAME_PRINT  "mysql.innodb_table_stats" 
  119 #define INDEX_STATS_NAME        "mysql/innodb_index_stats" 
  120 #define INDEX_STATS_NAME_PRINT  "mysql.innodb_index_stats" 
  122 #ifdef UNIV_STATS_DEBUG 
  123 #define DEBUG_PRINTF(fmt, ...)  printf(fmt, ## __VA_ARGS__) 
  125 #define DEBUG_PRINTF(fmt, ...)   
  129 #define N_SAMPLE_PAGES(index)                           \ 
  130         ((index)->table->stats_sample_pages != 0 ?      \ 
  131          (index)->table->stats_sample_pages :           \ 
  132          srv_stats_persistent_sample_pages) 
  137 #define N_DIFF_REQUIRED(index)  (N_SAMPLE_PAGES(index) * 10) 
  144 typedef std::vector<ib_uint64_t>        boundaries_t;
 
  158         return((index->
type & DICT_FTS)
 
  170 dict_stats_persistent_storage_check(
 
  172         bool    caller_has_dict_sys_mutex)      
 
  177                 {
"database_name", DATA_VARMYSQL,
 
  180                 {
"table_name", DATA_VARMYSQL,
 
  183                 {
"last_update", DATA_FIXBINARY,
 
  187                         DATA_NOT_NULL | DATA_UNSIGNED, 8},
 
  189                 {
"clustered_index_size", DATA_INT,
 
  190                         DATA_NOT_NULL | DATA_UNSIGNED, 8},
 
  192                 {
"sum_of_other_index_sizes", DATA_INT,
 
  193                         DATA_NOT_NULL | DATA_UNSIGNED, 8}
 
  197                 UT_ARR_SIZE(table_stats_columns),
 
  205                 {
"database_name", DATA_VARMYSQL,
 
  208                 {
"table_name", DATA_VARMYSQL,
 
  211                 {
"index_name", DATA_VARMYSQL,
 
  214                 {
"last_update", DATA_FIXBINARY,
 
  217                 {
"stat_name", DATA_VARMYSQL,
 
  218                         DATA_NOT_NULL, 64*3},
 
  220                 {
"stat_value", DATA_INT,
 
  221                         DATA_NOT_NULL | DATA_UNSIGNED, 8},
 
  223                 {
"sample_size", DATA_INT,
 
  226                 {
"stat_description", DATA_VARMYSQL,
 
  227                         DATA_NOT_NULL, 1024*3}
 
  231                 UT_ARR_SIZE(index_stats_columns),
 
  240         if (!caller_has_dict_sys_mutex) {
 
  249         if (ret == DB_SUCCESS) {
 
  255         if (!caller_has_dict_sys_mutex) {
 
  259         if (ret != DB_SUCCESS) {
 
  261                 fprintf(stderr, 
" InnoDB: Error: %s\n", errstr);
 
  285 #ifdef UNIV_SYNC_DEBUG 
  290         if (!dict_stats_persistent_storage_check(
true)) {
 
  296         trx_start_if_not_started(trx);
 
  300         if (err == DB_SUCCESS) {
 
  303                 trx->
op_info = 
"rollback of internal trx on stats tables";
 
  347 dict_stats_table_clone_create(
 
  358         heap_size += strlen(table->
name) + 1;
 
  360         for (index = dict_table_get_first_index(table);
 
  362              index = dict_table_get_next_index(index)) {
 
  368                 ut_ad(!dict_index_is_univ(index));
 
  373                 heap_size += strlen(index->
name) + 1;
 
  374                 heap_size += n_uniq * 
sizeof(index->
fields[0]);
 
  375                 for (ulint 
i = 0; 
i < n_uniq; 
i++) {
 
  380                 heap_size += n_uniq * 
sizeof(index->stat_n_non_null_key_vals[0]);
 
  393         UNIV_MEM_ASSERT_RW_ABORT(&table->
id, 
sizeof(table->
id));
 
  398         UNIV_MEM_ASSERT_RW_ABORT(table->
name, strlen(table->
name) + 1);
 
  405         for (index = dict_table_get_first_index(table);
 
  407              index = dict_table_get_next_index(index)) {
 
  413                 ut_ad(!dict_index_is_univ(index));
 
  419                 UNIV_MEM_ASSERT_RW_ABORT(&index->
id, 
sizeof(index->
id));
 
  422                 UNIV_MEM_ASSERT_RW_ABORT(index->
name, strlen(index->
name) + 1);
 
  440                 for (ulint 
i = 0; 
i < idx->
n_uniq; 
i++) {
 
  459                         idx->
n_uniq * 
sizeof(idx->stat_n_non_null_key_vals[0]));
 
  460                 ut_d(idx->magic_n = DICT_INDEX_MAGIC_N);
 
  463         ut_d(t->magic_n = DICT_TABLE_MAGIC_N);
 
  473 dict_stats_table_clone_free(
 
  487 dict_stats_empty_index(
 
  492         ut_ad(!dict_index_is_univ(index));
 
  494         ulint   n_uniq = index->
n_uniq;
 
  496         for (ulint 
i = 0; 
i < n_uniq; 
i++) {
 
  499                 index->stat_n_non_null_key_vals[
i] = 0;
 
  511 dict_stats_empty_table(
 
  528         for (index = dict_table_get_first_index(table);
 
  530              index = dict_table_get_next_index(index)) {
 
  532                 if (index->
type & DICT_FTS) {
 
  536                 ut_ad(!dict_index_is_univ(index));
 
  538                 dict_stats_empty_index(index);
 
  550 dict_stats_assert_initialized_index(
 
  554         UNIV_MEM_ASSERT_RW_ABORT(
 
  558         UNIV_MEM_ASSERT_RW_ABORT(
 
  562         UNIV_MEM_ASSERT_RW_ABORT(
 
  563                 index->stat_n_non_null_key_vals,
 
  564                 index->
n_uniq * 
sizeof(index->stat_n_non_null_key_vals[0]));
 
  566         UNIV_MEM_ASSERT_RW_ABORT(
 
  570         UNIV_MEM_ASSERT_RW_ABORT(
 
  579 dict_stats_assert_initialized(
 
  612         for (
dict_index_t* index = dict_table_get_first_index(table);
 
  614              index = dict_table_get_next_index(index)) {
 
  617                         dict_stats_assert_initialized_index(index);
 
  622 #define INDEX_EQ(i1, i2) \ 
  625          && (i1)->id == (i2)->id \ 
  626          && strcmp((i1)->name, (i2)->name) == 0) 
  648         for (dst_idx = dict_table_get_first_index(dst),
 
  649              src_idx = dict_table_get_first_index(src);
 
  651              dst_idx = dict_table_get_next_index(dst_idx),
 
  653               && (src_idx = dict_table_get_next_index(src_idx)))) {
 
  659                 ut_ad(!dict_index_is_univ(dst_idx));
 
  661                 if (!INDEX_EQ(src_idx, dst_idx)) {
 
  662                         for (src_idx = dict_table_get_first_index(src);
 
  664                              src_idx = dict_table_get_next_index(src_idx)) {
 
  666                                 if (INDEX_EQ(src_idx, dst_idx)) {
 
  672                 if (!INDEX_EQ(src_idx, dst_idx)) {
 
  673                         dict_stats_empty_index(dst_idx);
 
  679                 if (dst_idx->
n_uniq > src_idx->n_uniq) {
 
  680                         n_copy_el = src_idx->n_uniq;
 
  684                         dict_stats_empty_index(dst_idx);
 
  686                         n_copy_el = dst_idx->
n_uniq;
 
  690                         src_idx->stat_n_diff_key_vals,
 
  694                         src_idx->stat_n_sample_sizes,
 
  697                 memmove(dst_idx->stat_n_non_null_key_vals,
 
  698                         src_idx->stat_n_non_null_key_vals,
 
  699                         n_copy_el * 
sizeof(dst_idx->stat_n_non_null_key_vals[0]));
 
  732 dict_stats_snapshot_create(
 
  740         dict_stats_assert_initialized(table);
 
  744         t = dict_stats_table_clone_create(table);
 
  746         dict_stats_copy(t, table);
 
  765 dict_stats_snapshot_free(
 
  769         dict_stats_table_clone_free(t);
 
  779 dict_stats_update_transient_for_index(
 
  794                 if (size != ULINT_UNDEFINED) {
 
  798                                 index, BTR_N_LEAF_PAGES, &mtr);
 
  804                 case ULINT_UNDEFINED:
 
  805                         dict_stats_empty_index(index);
 
  822                 dict_stats_empty_index(index);
 
  839         ulint           sum_of_index_sizes      = 0;
 
  844         index = dict_table_get_first_index(table);
 
  848                 dict_stats_empty_table(table);
 
  850         } 
else if (index == NULL) {
 
  853                 char    buf[MAX_FULL_NAME_LEN];
 
  855                 fprintf(stderr, 
" InnoDB: table %s has no indexes. " 
  856                         "Cannot calculate statistics.\n",
 
  858                 dict_stats_empty_table(table);
 
  862         for (; index != NULL; index = dict_table_get_next_index(index)) {
 
  864                 ut_ad(!dict_index_is_univ(index));
 
  866                 if (index->
type & DICT_FTS) {
 
  870                 dict_stats_empty_index(index);
 
  876                 dict_stats_update_transient_for_index(index);
 
  881         index = dict_table_get_first_index(table);
 
  926 dict_stats_analyze_index_level(
 
  932         ib_uint64_t*    total_recs,     
 
  933         ib_uint64_t*    total_pages,    
 
  934         boundaries_t*   n_diff_boundaries,
 
  943         const rec_t*    prev_rec;
 
  944         bool            prev_rec_is_copied;
 
  945         byte*           prev_rec_buf = NULL;
 
  946         ulint           prev_rec_buf_size = 0;
 
  948         ulint*          prev_rec_offsets;
 
  951         DEBUG_PRINTF(
"    %s(table=%s, index=%s, level=%lu)\n", __func__,
 
  960         memset(n_diff, 0x0, n_uniq * 
sizeof(n_diff[0]));
 
  966         i = (REC_OFFS_HEADER_SIZE + 1 + 1) + index->
n_fields;
 
  969         rec_offsets = 
static_cast<ulint*
>(
 
  971         prev_rec_offsets = 
static_cast<ulint*
>(
 
  977         if (n_diff_boundaries != NULL) {
 
  978                 for (i = 0; i < n_uniq; i++) {
 
  979                         n_diff_boundaries[
i].erase(
 
  980                                 n_diff_boundaries[i].begin(),
 
  981                                 n_diff_boundaries[i].end());
 
  990                 &pcur, 
true, level, mtr);
 
  993         page = btr_pcur_get_page(&pcur);
 
  998         ut_ad(btr_pcur_get_rec(&pcur)
 
 1002         ut_a(btr_page_get_level(page, mtr) == level);
 
 1014         prev_rec_is_copied = 
false;
 
 1028                 ulint   matched_fields = 0;
 
 1029                 ulint   matched_bytes = 0;
 
 1030                 bool    rec_is_last_on_page;
 
 1032                 rec = btr_pcur_get_rec(&pcur);
 
 1037                 if (prev_rec != NULL
 
 1040                         ut_a(prev_rec_is_copied);
 
 1043                 rec_is_last_on_page =
 
 1047                 if (rec_is_last_on_page) {
 
 1063                         if (rec_is_last_on_page
 
 1064                             && !prev_rec_is_copied
 
 1065                             && prev_rec != NULL) {
 
 1068                                 prev_rec_offsets = rec_get_offsets(
 
 1069                                         prev_rec, index, prev_rec_offsets,
 
 1075                                         &prev_rec_buf, &prev_rec_buf_size);
 
 1077                                 prev_rec_is_copied = 
true;
 
 1083                 rec_offsets = rec_get_offsets(
 
 1084                         rec, index, rec_offsets, n_uniq, &heap);
 
 1088                 if (prev_rec != NULL) {
 
 1089                         prev_rec_offsets = rec_get_offsets(
 
 1090                                 prev_rec, index, prev_rec_offsets,
 
 1102                         for (i = matched_fields; i < n_uniq; i++) {
 
 1104                                 if (n_diff_boundaries != NULL) {
 
 1119                                         idx = *total_recs - 2;
 
 1121                                         n_diff_boundaries[
i].push_back(idx);
 
 1131                         for (i = 0; i < n_uniq; i++) {
 
 1136                 if (rec_is_last_on_page) {
 
 1148                                 &prev_rec_buf, &prev_rec_buf_size);
 
 1149                         prev_rec_is_copied = 
true;
 
 1158                         prev_rec_is_copied = 
false;
 
 1166         if (*total_pages == 0) {
 
 1169                 ut_ad(*total_recs == 0);
 
 1176         if (*total_recs > 0 && n_diff_boundaries != NULL) {
 
 1181                 for (i = 0; i < n_uniq; i++) {
 
 1184                         idx = *total_recs - 1;
 
 1186                         n_diff_boundaries[
i].push_back(idx);
 
 1193 #ifdef UNIV_STATS_DEBUG 
 1194         for (i = 0; i < n_uniq; i++) {
 
 1196                 DEBUG_PRINTF(
"    %s(): total recs: " UINT64PF
 
 1197                              ", total pages: " UINT64PF
 
 1198                              ", n_diff[%lu]: " UINT64PF 
"\n",
 
 1199                              __func__, *total_recs,
 
 1204                 if (n_diff_boundaries != NULL) {
 
 1207                         DEBUG_PRINTF(
"    %s(): boundaries[%lu]: ",
 
 1210                         for (j = 0; j < n_diff[
i]; j++) {
 
 1213                                 idx = n_diff_boundaries[
i][j];
 
 1215                                 DEBUG_PRINTF(UINT64PF 
"=" UINT64PF 
", ",
 
 1230         if (prev_rec_buf != NULL) {
 
 1239 enum page_scan_method_t {
 
 1240         COUNT_ALL_NON_BORING_AND_SKIP_DEL_MARKED,
 
 1244         QUIT_ON_FIRST_NON_BORING
 
 1259 UNIV_INLINE __attribute__((nonnull))
 
 1261 dict_stats_scan_page(
 
 1263         const rec_t**           out_rec,        
 
 1276         ib_uint64_t*            n_diff)         
 
 1280         ulint*          offsets_next_rec        = 
offsets2;
 
 1282         const rec_t*    next_rec;
 
 1287         const rec_t*    (*get_next)(
const rec_t*);
 
 1289         if (scan_method == COUNT_ALL_NON_BORING_AND_SKIP_DEL_MARKED) {
 
 1295         rec = get_next(page_get_infimum_rec(page));
 
 1304         offsets_rec = rec_get_offsets(rec, index, offsets_rec,
 
 1305                                       ULINT_UNDEFINED, &heap);
 
 1307         next_rec = get_next(rec);
 
 1313                 ulint   matched_fields = 0;
 
 1314                 ulint   matched_bytes = 0;
 
 1316                 offsets_next_rec = rec_get_offsets(next_rec, index,
 
 1324                                        offsets_rec, offsets_next_rec,
 
 1325                                        index, FALSE, &matched_fields,
 
 1328                 if (matched_fields < n_prefix) {
 
 1333                         if (scan_method == QUIT_ON_FIRST_NON_BORING) {
 
 1352                         offsets_tmp = offsets_rec;
 
 1353                         offsets_rec = offsets_next_rec;
 
 1354                         offsets_next_rec = offsets_tmp;
 
 1357                 next_rec = get_next(next_rec);
 
 1364         return(offsets_rec);
 
 1374 dict_stats_analyze_index_below_cur(
 
 1410                         heap, size * 
sizeof *offsets1));
 
 1413                         heap, size * 
sizeof *offsets2));
 
 1421         rec = btr_cur_get_rec(cur);
 
 1423         offsets_rec = rec_get_offsets(rec, index, offsets1,
 
 1424                                       ULINT_UNDEFINED, &heap);
 
 1433                                          BUF_GET, __FILE__, __LINE__, mtr);
 
 1435                 page = buf_block_get_frame(block);
 
 1437                 if (btr_page_get_level(page, mtr) == 0) {
 
 1444                 offsets_rec = dict_stats_scan_page(
 
 1445                         &rec, offsets1, offsets2, index, page, n_prefix,
 
 1446                         QUIT_ON_FIRST_NON_BORING, &n_diff);
 
 1449                 ut_a(offsets_rec != NULL);
 
 1475         ut_ad(btr_page_get_level(page, mtr) == 0);
 
 1480         offsets_rec = dict_stats_scan_page(
 
 1481                 &rec, offsets1, offsets2, index, page, n_prefix,
 
 1482                 COUNT_ALL_NON_BORING_AND_SKIP_DEL_MARKED, &n_diff);
 
 1485         DEBUG_PRINTF(
"      %s(): n_diff below page_no=%lu: " UINT64PF 
"\n",
 
 1486                      __func__, page_no, n_diff);
 
 1502 dict_stats_analyze_index_for_n_prefix(
 
 1506         ib_uint64_t     total_recs_on_level,
 
 1512         ib_uint64_t     n_diff_for_this_prefix,
 
 1517         boundaries_t*   boundaries,     
 
 1530         ib_uint64_t     rec_idx;
 
 1531         ib_uint64_t     last_idx_on_level;
 
 1532         ib_uint64_t     n_recs_to_dive_below;
 
 1533         ib_uint64_t     n_diff_sum_of_all_analyzed_pages;
 
 1537         DEBUG_PRINTF(
"    %s(table=%s, index=%s, level=%lu, n_prefix=%lu, " 
 1538                      "n_diff_for_this_prefix=" UINT64PF 
")\n",
 
 1540                      n_prefix, n_diff_for_this_prefix);
 
 1549         ut_ad(total_recs_on_level > 0);
 
 1550         ut_ad(n_diff_for_this_prefix > 0);
 
 1553         ut_ad(N_SAMPLE_PAGES(index) > 0);
 
 1560                 &pcur, 
true, level, mtr);
 
 1563         page = btr_pcur_get_page(&pcur);
 
 1568         ut_ad(btr_pcur_get_rec(&pcur)
 
 1572         ut_a(btr_page_get_level(page, mtr) == level);
 
 1583         last_idx_on_level = boundaries->at(n_diff_for_this_prefix - 1);
 
 1587         n_diff_sum_of_all_analyzed_pages = 0;
 
 1589         n_recs_to_dive_below = 
ut_min(N_SAMPLE_PAGES(index),
 
 1590                                       n_diff_for_this_prefix);
 
 1592         for (i = 0; i < n_recs_to_dive_below; i++) {
 
 1596                 ib_uint64_t     dive_below_idx;
 
 1626                 left = n_diff_for_this_prefix * i / n_recs_to_dive_below;
 
 1627                 right = n_diff_for_this_prefix * (i + 1)
 
 1628                         / n_recs_to_dive_below - 1;
 
 1630                 ut_a(left <= right);
 
 1631                 ut_a(right <= last_idx_on_level);
 
 1638                 dive_below_idx = boundaries->at(left + rnd);
 
 1641                 DEBUG_PRINTF(
"    %s(): dive below record with index=" 
 1642                              UINT64PF 
"\n", __func__, dive_below_idx);
 
 1646                 while (rec_idx < dive_below_idx
 
 1657                 if (rec_idx < dive_below_idx) {
 
 1671                 ut_a(rec_idx == dive_below_idx);
 
 1673                 ib_uint64_t     n_diff_on_leaf_page;
 
 1675                 n_diff_on_leaf_page = dict_stats_analyze_index_below_cur(
 
 1676                         btr_pcur_get_btr_cur(&pcur), n_prefix, mtr);
 
 1692                 if (n_diff_on_leaf_page > 0) {
 
 1693                         n_diff_on_leaf_page--;
 
 1696                 n_diff_sum_of_all_analyzed_pages += n_diff_on_leaf_page;
 
 1708                 * n_diff_for_this_prefix
 
 1709                 / total_recs_on_level
 
 1711                 * n_diff_sum_of_all_analyzed_pages
 
 1712                 / n_recs_to_dive_below;
 
 1716         DEBUG_PRINTF(
"    %s(): n_diff=" UINT64PF 
" for n_prefix=%lu " 
 1718                      " * " UINT64PF 
" / " UINT64PF
 
 1719                      " * " UINT64PF 
" / " UINT64PF 
")\n",
 
 1723                      n_diff_for_this_prefix, total_recs_on_level,
 
 1724                      n_diff_sum_of_all_analyzed_pages, n_recs_to_dive_below);
 
 1735 dict_stats_analyze_index(
 
 1741         bool            level_is_analyzed;
 
 1744         ib_uint64_t*    n_diff_on_level;
 
 1745         ib_uint64_t     total_recs;
 
 1746         ib_uint64_t     total_pages;
 
 1747         boundaries_t*   n_diff_boundaries;
 
 1750         DBUG_ENTER(
"dict_stats_analyze_index");
 
 1752         DBUG_PRINT(
"info", (
"index: %s, online status: %d", index->
name,
 
 1755         DEBUG_PRINTF(
"  %s(index=%s)\n", __func__, index->
name);
 
 1757         dict_stats_empty_index(index);
 
 1765         if (size != ULINT_UNDEFINED) {
 
 1774         case ULINT_UNDEFINED:
 
 1775                 dict_stats_assert_initialized_index(index);
 
 1804                 if (root_level == 0) {
 
 1805                         DEBUG_PRINTF(
"  %s(): just one page, " 
 1806                                      "doing full scan\n", __func__);
 
 1808                         DEBUG_PRINTF(
"  %s(): too many pages requested for " 
 1809                                      "sampling, doing full scan\n", __func__);
 
 1815                 dict_stats_analyze_index_level(index,
 
 1823                 for (ulint i = 0; i < n_uniq; i++) {
 
 1829                 dict_stats_assert_initialized_index(index);
 
 1834         n_diff_on_level = 
reinterpret_cast<ib_uint64_t*
> 
 1837         n_diff_boundaries = 
new boundaries_t[n_uniq];
 
 1854         level_is_analyzed = 
false;
 
 1856         for (n_prefix = n_uniq; n_prefix >= 1; n_prefix--) {
 
 1858                 DEBUG_PRINTF(
"  %s(): searching level with >=%llu " 
 1859                              "distinct records, n_prefix=%lu\n",
 
 1860                              __func__, N_DIFF_REQUIRED(index), n_prefix);
 
 1883                 if (level_is_analyzed
 
 1884                     && (n_diff_on_level[n_prefix - 1] >= N_DIFF_REQUIRED(index)
 
 1892                 if (level_is_analyzed && level > 1) {
 
 1896                         ut_ad(n_diff_on_level[n_prefix - 1]
 
 1897                               < N_DIFF_REQUIRED(index));
 
 1900                         level_is_analyzed = 
false;
 
 1912                         ut_ad(!level_is_analyzed);
 
 1922                         if (total_recs > N_SAMPLE_PAGES(index)) {
 
 1929                                 ut_a(level != root_level);
 
 1934                                 level_is_analyzed = 
true;
 
 1939                         dict_stats_analyze_index_level(index,
 
 1947                         level_is_analyzed = 
true;
 
 1949                         if (n_diff_on_level[n_prefix - 1]
 
 1950                             >= N_DIFF_REQUIRED(index)
 
 1959                         level_is_analyzed = 
false;
 
 1963                 DEBUG_PRINTF(
"  %s(): found level %lu that has " UINT64PF
 
 1964                              " distinct records for n_prefix=%lu\n",
 
 1965                              __func__, level, n_diff_on_level[n_prefix - 1],
 
 1974                 ut_ad(level_is_analyzed);
 
 1979                 dict_stats_analyze_index_for_n_prefix(
 
 1980                         index, level, total_recs, n_prefix,
 
 1981                         n_diff_on_level[n_prefix - 1],
 
 1982                         &n_diff_boundaries[n_prefix - 1], &mtr);
 
 1987         delete[] n_diff_boundaries;
 
 1991         dict_stats_assert_initialized_index(index);
 
 2002 dict_stats_update_persistent(
 
 2008         DEBUG_PRINTF(
"%s(table=%s)\n", __func__, table->
name);
 
 2014         index = dict_table_get_first_index(table);
 
 2022                 dict_stats_empty_table(table);
 
 2027         ut_ad(!dict_index_is_univ(index));
 
 2029         dict_stats_analyze_index(index);
 
 2041         for (index = dict_table_get_next_index(index);
 
 2043              index = dict_table_get_next_index(index)) {
 
 2045                 ut_ad(!dict_index_is_univ(index));
 
 2047                 if (index->
type & DICT_FTS) {
 
 2051                 dict_stats_empty_index(index);
 
 2058                         dict_stats_analyze_index(index);
 
 2071         dict_stats_assert_initialized(table);
 
 2078 #include "mysql_com.h" 
 2085 dict_stats_save_index_stat(
 
 2089         const char*     stat_name,      
 
 2090         ib_uint64_t     stat_value,     
 
 2091         ib_uint64_t*    sample_size,    
 
 2092         const char*     stat_description)
 
 2096         char            db_utf8[MAX_DB_UTF8_LEN];
 
 2097         char            table_utf8[MAX_TABLE_UTF8_LEN];
 
 2099 #ifdef UNIV_SYNC_DEBUG 
 2105                      table_utf8, 
sizeof(table_utf8));
 
 2110         UNIV_MEM_ASSERT_RW_ABORT(index->
name, strlen(index->
name));
 
 2112         UNIV_MEM_ASSERT_RW_ABORT(&last_update, 4);
 
 2114         UNIV_MEM_ASSERT_RW_ABORT(stat_name, strlen(stat_name));
 
 2116         UNIV_MEM_ASSERT_RW_ABORT(&stat_value, 8);
 
 2118         if (sample_size != NULL) {
 
 2119                 UNIV_MEM_ASSERT_RW_ABORT(sample_size, 8);
 
 2123                                       UNIV_SQL_NULL, DATA_FIXBINARY, 0);
 
 2125         UNIV_MEM_ASSERT_RW_ABORT(stat_description, strlen(stat_description));
 
 2129         ret = dict_stats_exec_sql(
 
 2131                 "PROCEDURE INDEX_STATS_SAVE_INSERT () IS\n" 
 2133                 "INSERT INTO \"" INDEX_STATS_NAME 
"\"\n" 
 2143                 ":stat_description\n" 
 2147         if (ret == DB_DUPLICATE_KEY) {
 
 2152                 UNIV_MEM_ASSERT_RW_ABORT(index->
name, strlen(index->
name));
 
 2154                 UNIV_MEM_ASSERT_RW_ABORT(&last_update, 4);
 
 2156                 UNIV_MEM_ASSERT_RW_ABORT(stat_name, strlen(stat_name));
 
 2158                 UNIV_MEM_ASSERT_RW_ABORT(&stat_value, 8);
 
 2160                 if (sample_size != NULL) {
 
 2161                         UNIV_MEM_ASSERT_RW_ABORT(sample_size, 8);
 
 2165                                               UNIV_SQL_NULL, DATA_FIXBINARY, 0);
 
 2167                 UNIV_MEM_ASSERT_RW_ABORT(stat_description, strlen(stat_description));
 
 2171                 ret = dict_stats_exec_sql(
 
 2173                         "PROCEDURE INDEX_STATS_SAVE_UPDATE () IS\n" 
 2175                         "UPDATE \"" INDEX_STATS_NAME 
"\" SET\n" 
 2176                         "last_update = :last_update,\n" 
 2177                         "stat_value = :stat_value,\n" 
 2178                         "sample_size = :sample_size,\n" 
 2179                         "stat_description = :stat_description\n" 
 2181                         "database_name = :database_name AND\n" 
 2182                         "table_name = :table_name AND\n" 
 2183                         "index_name = :index_name AND\n" 
 2184                         "stat_name = :stat_name;\n" 
 2188         if (ret != DB_SUCCESS) {
 
 2189                 char    buf_table[MAX_FULL_NAME_LEN];
 
 2190                 char    buf_index[MAX_FULL_NAME_LEN];
 
 2193                         " InnoDB: Cannot save index statistics for table " 
 2194                         "%s, index %s, stat name \"%s\": %s\n",
 
 2196                                        buf_table, 
sizeof(buf_table)),
 
 2198                                        buf_index, 
sizeof(buf_index)),
 
 2218         char            db_utf8[MAX_DB_UTF8_LEN];
 
 2219         char            table_utf8[MAX_TABLE_UTF8_LEN];
 
 2221         table = dict_stats_snapshot_create(table_orig);
 
 2224                      table_utf8, 
sizeof(table_utf8));
 
 2234 #define PREPARE_PINFO_FOR_TABLE_SAVE(p, t, n)                           \ 
 2236         pars_info_add_str_literal((p), "database_name", db_utf8);       \ 
 2237         pars_info_add_str_literal((p), "table_name", table_utf8);       \ 
 2238         pars_info_add_int4_literal((p), "last_update", (n));            \ 
 2239         pars_info_add_ull_literal((p), "n_rows", (t)->stat_n_rows);     \ 
 2240         pars_info_add_ull_literal((p), "clustered_index_size",          \ 
 2241                 (t)->stat_clustered_index_size);                        \ 
 2242         pars_info_add_ull_literal((p), "sum_of_other_index_sizes",      \ 
 2243                 (t)->stat_sum_of_other_index_sizes);                    \ 
 2248         PREPARE_PINFO_FOR_TABLE_SAVE(pinfo, table, now);
 
 2250         ret = dict_stats_exec_sql(
 
 2252                 "PROCEDURE TABLE_STATS_SAVE_INSERT () IS\n" 
 2254                 "INSERT INTO \"" TABLE_STATS_NAME 
"\"\n" 
 2261                 ":clustered_index_size,\n" 
 2262                 ":sum_of_other_index_sizes\n" 
 2266         if (ret == DB_DUPLICATE_KEY) {
 
 2269                 PREPARE_PINFO_FOR_TABLE_SAVE(pinfo, table, now);
 
 2271                 ret = dict_stats_exec_sql(
 
 2273                         "PROCEDURE TABLE_STATS_SAVE_UPDATE () IS\n" 
 2275                         "UPDATE \"" TABLE_STATS_NAME 
"\" SET\n" 
 2276                         "last_update = :last_update,\n" 
 2277                         "n_rows = :n_rows,\n" 
 2278                         "clustered_index_size = :clustered_index_size,\n" 
 2279                         "sum_of_other_index_sizes = " 
 2280                         "  :sum_of_other_index_sizes\n" 
 2282                         "database_name = :database_name AND\n" 
 2283                         "table_name = :table_name;\n" 
 2287         if (ret != DB_SUCCESS) {
 
 2288                 char    buf[MAX_FULL_NAME_LEN];
 
 2291                         " InnoDB: Cannot save table statistics for table " 
 2300         for (index = dict_table_get_first_index(table);
 
 2302              index = dict_table_get_next_index(index)) {
 
 2308                 ut_ad(!dict_index_is_univ(index));
 
 2310                 ret = dict_stats_save_index_stat(index, now, 
"size",
 
 2315                 if (ret != DB_SUCCESS) {
 
 2319                 ret = dict_stats_save_index_stat(index, now, 
"n_leaf_pages",
 
 2322                                                  "Number of leaf pages " 
 2324                 if (ret != DB_SUCCESS) {
 
 2328                 for (ulint i = 0; i < index->
n_uniq; i++) {
 
 2331                         char    stat_description[1024];
 
 2335                                     "n_diff_pfx%02lu", i + 1);
 
 2339                                     sizeof(stat_description),
 
 2341                         for (j = 1; j <= 
i; j++) {
 
 2344                                 len = strlen(stat_description);
 
 2347                                             sizeof(stat_description) - len,
 
 2351                         ret = dict_stats_save_index_stat(
 
 2352                                 index, now, stat_name,
 
 2357                         if (ret != DB_SUCCESS) {
 
 2367         dict_stats_snapshot_free(table);
 
 2380 dict_stats_fetch_table_stats_step(
 
 2392         for (cnode = static_cast<que_common_t*>(node->
select_list), i = 0;
 
 2402                 data = 
static_cast<const byte*
>(dfield_get_data(dfield));
 
 2456 struct index_fetch_t {
 
 2458         bool            stats_were_modified; 
 
 2481 dict_stats_fetch_index_stats_step(
 
 2488         index_fetch_t*  arg = (index_fetch_t*) arg_void;
 
 2492         const char*     stat_name = NULL;
 
 2493         ulint           stat_name_len = ULINT_UNDEFINED;
 
 2494         ib_uint64_t     stat_value = UINT64_UNDEFINED;
 
 2495         ib_uint64_t     sample_size = UINT64_UNDEFINED;
 
 2500         for (cnode = static_cast<que_common_t*>(node->
select_list), i = 0;
 
 2507                 dtype_t*        type = dfield_get_type(dfield);
 
 2510                 data = 
static_cast<const byte*
>(dfield_get_data(dfield));
 
 2520                         for (index = dict_table_get_first_index(table);
 
 2522                              index = dict_table_get_next_index(index)) {
 
 2524                                 if (strlen(index->
name) == len
 
 2525                                     && memcmp(index->
name, data, len) == 0) {
 
 2538                         if (index == NULL) {
 
 2549                         ut_a(index != NULL);
 
 2551                         stat_name = (
const char*) data;
 
 2552                         stat_name_len = len;
 
 2561                         ut_a(index != NULL);
 
 2562                         ut_a(stat_name != NULL);
 
 2563                         ut_a(stat_name_len != ULINT_UNDEFINED);
 
 2572                         ut_a(len == 8 || len == UNIV_SQL_NULL);
 
 2574                         ut_a(index != NULL);
 
 2575                         ut_a(stat_name != NULL);
 
 2576                         ut_a(stat_name_len != ULINT_UNDEFINED);
 
 2577                         ut_a(stat_value != UINT64_UNDEFINED);
 
 2579                         if (len == UNIV_SQL_NULL) {
 
 2604         ut_a(index != NULL);
 
 2605         ut_a(stat_name != NULL);
 
 2606         ut_a(stat_name_len != ULINT_UNDEFINED);
 
 2607         ut_a(stat_value != UINT64_UNDEFINED);
 
 2610 #define PFX     "n_diff_pfx" 
 2613         if (stat_name_len == 4 
 
 2614             && strncasecmp(
"size", stat_name, stat_name_len) == 0) {
 
 2616                 arg->stats_were_modified = 
true;
 
 2617         } 
else if (stat_name_len == 12 
 
 2618                    && strncasecmp(
"n_leaf_pages", stat_name, stat_name_len)
 
 2621                 arg->stats_were_modified = 
true;
 
 2622         } 
else if (stat_name_len > PFX_LEN 
 
 2623                    && strncasecmp(PFX, stat_name, PFX_LEN) == 0) {
 
 2625                 const char*     num_ptr;
 
 2626                 unsigned long   n_pfx;
 
 2629                 num_ptr = stat_name + PFX_LEN;
 
 2633                 if (stat_name_len != PFX_LEN + 2
 
 2634                     || num_ptr[0] < 
'0' || num_ptr[0] > 
'9' 
 2635                     || num_ptr[1] < 
'0' || num_ptr[1] > 
'9') {
 
 2637                         char    db_utf8[MAX_DB_UTF8_LEN];
 
 2638                         char    table_utf8[MAX_TABLE_UTF8_LEN];
 
 2641                                      table_utf8, 
sizeof(table_utf8));
 
 2645                                 " InnoDB: Ignoring strange row from " 
 2647                                 "database_name = '%s' AND " 
 2648                                 "table_name = '%s' AND " 
 2649                                 "index_name = '%s' AND " 
 2650                                 "stat_name = '%.*s'; because stat_name " 
 2652                                 INDEX_STATS_NAME_PRINT,
 
 2656                                 (
int) stat_name_len,
 
 2664                 n_pfx = (num_ptr[0] - 
'0') * 10 + (num_ptr[1] - 
'0');
 
 2666                 ulint   n_uniq = index->
n_uniq;
 
 2668                 if (n_pfx == 0 || n_pfx > n_uniq) {
 
 2670                         char    db_utf8[MAX_DB_UTF8_LEN];
 
 2671                         char    table_utf8[MAX_TABLE_UTF8_LEN];
 
 2674                                      table_utf8, 
sizeof(table_utf8));
 
 2678                                 " InnoDB: Ignoring strange row from " 
 2680                                 "database_name = '%s' AND " 
 2681                                 "table_name = '%s' AND " 
 2682                                 "index_name = '%s' AND " 
 2683                                 "stat_name = '%.*s'; because stat_name is " 
 2684                                 "out of range, the index has %lu unique " 
 2686                                 INDEX_STATS_NAME_PRINT,
 
 2690                                 (
int) stat_name_len,
 
 2699                 if (sample_size != UINT64_UNDEFINED) {
 
 2707                 index->stat_n_non_null_key_vals[n_pfx - 1] = 0;
 
 2709                 arg->stats_were_modified = 
true;
 
 2724 dict_stats_fetch_from_ps(
 
 2728         index_fetch_t   index_fetch_arg;
 
 2732         char            db_utf8[MAX_DB_UTF8_LEN];
 
 2733         char            table_utf8[MAX_TABLE_UTF8_LEN];
 
 2741         dict_stats_empty_table(table);
 
 2751         trx_start_if_not_started(trx);
 
 2754                      table_utf8, 
sizeof(table_utf8));
 
 2763                                "fetch_table_stats_step",
 
 2764                                dict_stats_fetch_table_stats_step,
 
 2767         index_fetch_arg.table = 
table;
 
 2768         index_fetch_arg.stats_were_modified = 
false;
 
 2770                                 "fetch_index_stats_step",
 
 2771                                 dict_stats_fetch_index_stats_step,
 
 2775                            "PROCEDURE FETCH_STATS () IS\n" 
 2777                            "DECLARE FUNCTION fetch_table_stats_step;\n" 
 2778                            "DECLARE FUNCTION fetch_index_stats_step;\n" 
 2779                            "DECLARE CURSOR table_stats_cur IS\n" 
 2785                            "  clustered_index_size,\n" 
 2786                            "  sum_of_other_index_sizes\n" 
 2787                            "  FROM \"" TABLE_STATS_NAME 
"\"\n" 
 2789                            "  database_name = :database_name AND\n" 
 2790                            "  table_name = :table_name;\n" 
 2791                            "DECLARE CURSOR index_stats_cur IS\n" 
 2800                            "  FROM \"" INDEX_STATS_NAME 
"\"\n" 
 2802                            "  database_name = :database_name AND\n" 
 2803                            "  table_name = :table_name;\n" 
 2807                            "OPEN table_stats_cur;\n" 
 2808                            "FETCH table_stats_cur INTO\n" 
 2809                            "  fetch_table_stats_step();\n" 
 2810                            "IF (SQL % NOTFOUND) THEN\n" 
 2811                            "  CLOSE table_stats_cur;\n" 
 2814                            "CLOSE table_stats_cur;\n" 
 2816                            "OPEN index_stats_cur;\n" 
 2818                            "WHILE found = 1 LOOP\n" 
 2819                            "  FETCH index_stats_cur INTO\n" 
 2820                            "    fetch_index_stats_step();\n" 
 2821                            "  IF (SQL % NOTFOUND) THEN\n" 
 2825                            "CLOSE index_stats_cur;\n" 
 2835         if (!index_fetch_arg.stats_were_modified) {
 
 2850         DBUG_ENTER(
"dict_stats_update_for_index");
 
 2856                 if (dict_stats_persistent_storage_check(
false)) {
 
 2858                         dict_stats_analyze_index(index);
 
 2860                         dict_stats_save(index->
table);
 
 2867                 char    buf_table[MAX_FULL_NAME_LEN];
 
 2868                 char    buf_index[MAX_FULL_NAME_LEN];
 
 2871                         " InnoDB: Recalculation of persistent statistics " 
 2872                         "requested for table %s index %s but the required " 
 2873                         "persistent statistics storage is not present or is " 
 2874                         "corrupted. Using transient stats instead.\n",
 
 2876                                        buf_table, 
sizeof(buf_table)),
 
 2878                                        buf_index, 
sizeof(buf_index)));
 
 2882         dict_stats_update_transient_for_index(index);
 
 2897         dict_stats_upd_option_t stats_upd_option)
 
 2903         char                    buf[MAX_FULL_NAME_LEN];
 
 2910                         " InnoDB: cannot calculate statistics for table %s " 
 2911                         "because the .ibd file is missing. For help, please " 
 2912                         "refer to " REFMAN 
"innodb-troubleshooting.html\n",
 
 2914                 dict_stats_empty_table(table);
 
 2920                 dict_stats_empty_table(table);
 
 2924         switch (stats_upd_option) {
 
 2925         case DICT_STATS_RECALC_PERSISTENT:
 
 2939                 ut_a(strchr(table->
name, 
'/') != NULL);
 
 2945                 if (dict_stats_persistent_storage_check(
false)) {
 
 2949                         err = dict_stats_update_persistent(table);
 
 2951                         if (err != DB_SUCCESS) {
 
 2955                         err = dict_stats_save(table);
 
 2965                         " InnoDB: Recalculation of persistent statistics " 
 2966                         "requested for table %s but the required persistent " 
 2967                         "statistics storage is not present or is corrupted. " 
 2968                         "Using transient stats instead.\n",
 
 2973         case DICT_STATS_RECALC_TRANSIENT:
 
 2977         case DICT_STATS_EMPTY_TABLE:
 
 2979                 dict_stats_empty_table(table);
 
 2986                         if (dict_stats_persistent_storage_check(
false)) {
 
 2988                                 return(dict_stats_save(table));
 
 2996         case DICT_STATS_FETCH_ONLY_IF_NOT_IN_MEMORY:
 
 3007                 ut_a(strchr(table->
name, 
'/') != NULL);
 
 3009                 if (!dict_stats_persistent_storage_check(
false)) {
 
 3015                                 " InnoDB: Error: Fetch of persistent " 
 3016                                 "statistics requested for table %s but the " 
 3017                                 "required system tables %s and %s are not " 
 3018                                 "present or have unexpected structure. " 
 3019                                 "Using transient stats instead.\n",
 
 3022                                 TABLE_STATS_NAME_PRINT,
 
 3023                                 INDEX_STATS_NAME_PRINT);
 
 3032                 t = dict_stats_table_clone_create(table);
 
 3034                 dberr_t err = dict_stats_fetch_from_ps(t);
 
 3048                         dict_stats_empty_table(table);
 
 3050                         dict_stats_copy(table, t);
 
 3052                         dict_stats_assert_initialized(table);
 
 3056                         dict_stats_table_clone_free(t);
 
 3061                         dict_stats_table_clone_free(t);
 
 3070                                                 DICT_STATS_RECALC_PERSISTENT));
 
 3076                                 " InnoDB: Trying to use table %s which has " 
 3077                                 "persistent statistics enabled, but auto " 
 3078                                 "recalculation turned off and the statistics " 
 3079                                 "do not exist in %s and %s. Please either run " 
 3080                                 "\"ANALYZE TABLE %s;\" manually or enable the " 
 3081                                 "auto recalculation with " 
 3082                                 "\"ALTER TABLE %s STATS_AUTO_RECALC=1;\". " 
 3083                                 "InnoDB will now use transient statistics for " 
 3085                                 buf, TABLE_STATS_NAME, INDEX_STATS_NAME, buf,
 
 3091                         dict_stats_table_clone_free(t);
 
 3095                                 " InnoDB: Error fetching persistent statistics " 
 3096                                 "for table %s from %s and %s: %s. " 
 3097                                 "Using transient stats method instead.\n",
 
 3136         const char*     db_and_table,
 
 3142         char            db_utf8[MAX_DB_UTF8_LEN];
 
 3143         char            table_utf8[MAX_TABLE_UTF8_LEN];
 
 3151         if (strchr(db_and_table, 
'/') == NULL) {
 
 3157                      table_utf8, 
sizeof(table_utf8));
 
 3170         ret = dict_stats_exec_sql(
 
 3172                 "PROCEDURE DROP_INDEX_STATS () IS\n" 
 3174                 "DELETE FROM \"" INDEX_STATS_NAME 
"\" WHERE\n" 
 3175                 "database_name = :database_name AND\n" 
 3176                 "table_name = :table_name AND\n" 
 3177                 "index_name = :index_name;\n" 
 3187         if (ret != DB_SUCCESS) {
 
 3189                             "Unable to delete statistics for index %s " 
 3190                             "from %s%s: %s. They can be deleted later using " 
 3191                             "DELETE FROM %s WHERE " 
 3192                             "database_name = '%s' AND " 
 3193                             "table_name = '%s' AND " 
 3194                             "index_name = '%s';",
 
 3196                             INDEX_STATS_NAME_PRINT,
 
 3198                              ? 
" because the rows are locked" 
 3201                             INDEX_STATS_NAME_PRINT,
 
 3207                 fprintf(stderr, 
" InnoDB: %s\n", errstr);
 
 3223         const char*     database_name,  
 
 3229 #ifdef UNIV_SYNC_DEBUG 
 3239         ret = dict_stats_exec_sql(
 
 3241                 "PROCEDURE DELETE_FROM_TABLE_STATS () IS\n" 
 3243                 "DELETE FROM \"" TABLE_STATS_NAME 
"\" WHERE\n" 
 3244                 "database_name = :database_name AND\n" 
 3245                 "table_name = :table_name;\n" 
 3261         const char*     database_name,  
 
 3267 #ifdef UNIV_SYNC_DEBUG 
 3277         ret = dict_stats_exec_sql(
 
 3279                 "PROCEDURE DELETE_FROM_INDEX_STATS () IS\n" 
 3281                 "DELETE FROM \"" INDEX_STATS_NAME 
"\" WHERE\n" 
 3282                 "database_name = :database_name AND\n" 
 3283                 "table_name = :table_name;\n" 
 3298         const char*     db_and_table,   
 
 3303         char            db_utf8[MAX_DB_UTF8_LEN];
 
 3304         char            table_utf8[MAX_TABLE_UTF8_LEN];
 
 3307 #ifdef UNIV_SYNC_DEBUG 
 3314         if (strchr(db_and_table, 
'/') == NULL) {
 
 3320         if (strcmp(db_and_table, TABLE_STATS_NAME) == 0
 
 3321             || strcmp(db_and_table, INDEX_STATS_NAME) == 0) {
 
 3327                      table_utf8, 
sizeof(table_utf8));
 
 3331         if (ret == DB_SUCCESS) {
 
 3339         if (ret != DB_SUCCESS) {
 
 3342                             "Unable to delete statistics for table %s.%s: %s. " 
 3343                             "They can be deleted later using " 
 3345                             "DELETE FROM %s WHERE " 
 3346                             "database_name = '%s' AND " 
 3347                             "table_name = '%s'; " 
 3349                             "DELETE FROM %s WHERE " 
 3350                             "database_name = '%s' AND " 
 3351                             "table_name = '%s';",
 
 3353                             db_utf8, table_utf8,
 
 3356                             INDEX_STATS_NAME_PRINT,
 
 3357                             db_utf8, table_utf8,
 
 3359                             TABLE_STATS_NAME_PRINT,
 
 3360                             db_utf8, table_utf8);
 
 3377         const char*     old_dbname_utf8,
 
 3378         const char*     old_tablename_utf8,
 
 3379         const char*     new_dbname_utf8,
 
 3380         const char*     new_tablename_utf8)
 
 3385 #ifdef UNIV_SYNC_DEBUG 
 3397         ret = dict_stats_exec_sql(
 
 3399                 "PROCEDURE RENAME_IN_TABLE_STATS () IS\n" 
 3401                 "UPDATE \"" TABLE_STATS_NAME 
"\" SET\n" 
 3402                 "database_name = :new_dbname_utf8,\n" 
 3403                 "table_name = :new_tablename_utf8\n" 
 3405                 "database_name = :old_dbname_utf8 AND\n" 
 3406                 "table_name = :old_tablename_utf8;\n" 
 3423         const char*     old_dbname_utf8,
 
 3424         const char*     old_tablename_utf8,
 
 3425         const char*     new_dbname_utf8,
 
 3426         const char*     new_tablename_utf8)
 
 3431 #ifdef UNIV_SYNC_DEBUG 
 3443         ret = dict_stats_exec_sql(
 
 3445                 "PROCEDURE RENAME_IN_INDEX_STATS () IS\n" 
 3447                 "UPDATE \"" INDEX_STATS_NAME 
"\" SET\n" 
 3448                 "database_name = :new_dbname_utf8,\n" 
 3449                 "table_name = :new_tablename_utf8\n" 
 3451                 "database_name = :old_dbname_utf8 AND\n" 
 3452                 "table_name = :old_tablename_utf8;\n" 
 3466         const char*     old_name,       
 
 3467         const char*     new_name,       
 
 3472         char            old_db_utf8[MAX_DB_UTF8_LEN];
 
 3473         char            new_db_utf8[MAX_DB_UTF8_LEN];
 
 3474         char            old_table_utf8[MAX_TABLE_UTF8_LEN];
 
 3475         char            new_table_utf8[MAX_TABLE_UTF8_LEN];
 
 3478 #ifdef UNIV_SYNC_DEBUG 
 3484         if (strcmp(old_name, TABLE_STATS_NAME) == 0
 
 3485             || strcmp(old_name, INDEX_STATS_NAME) == 0
 
 3486             || strcmp(new_name, TABLE_STATS_NAME) == 0
 
 3487             || strcmp(new_name, INDEX_STATS_NAME) == 0) {
 
 3492         dict_fs2utf8(old_name, old_db_utf8, 
sizeof(old_db_utf8),
 
 3493                      old_table_utf8, 
sizeof(old_table_utf8));
 
 3495         dict_fs2utf8(new_name, new_db_utf8, 
sizeof(new_db_utf8),
 
 3496                      new_table_utf8, 
sizeof(new_table_utf8));
 
 3501         ulint   n_attempts = 0;
 
 3506                         old_db_utf8, old_table_utf8,
 
 3507                         new_db_utf8, new_table_utf8);
 
 3509                 if (ret == DB_DUPLICATE_KEY) {
 
 3511                                 new_db_utf8, new_table_utf8);
 
 3518                 if (ret != DB_SUCCESS) {
 
 3525         } 
while ((ret == DB_DEADLOCK
 
 3526                   || ret == DB_DUPLICATE_KEY
 
 3530         if (ret != DB_SUCCESS) {
 
 3532                             "Unable to rename statistics from " 
 3533                             "%s.%s to %s.%s in %s: %s. " 
 3534                             "They can be renamed later using " 
 3537                             "database_name = '%s', " 
 3538                             "table_name = '%s' " 
 3540                             "database_name = '%s' AND " 
 3541                             "table_name = '%s';",
 
 3543                             old_db_utf8, old_table_utf8,
 
 3544                             new_db_utf8, new_table_utf8,
 
 3545                             TABLE_STATS_NAME_PRINT,
 
 3548                             TABLE_STATS_NAME_PRINT,
 
 3549                             new_db_utf8, new_table_utf8,
 
 3550                             old_db_utf8, old_table_utf8);
 
 3562                         old_db_utf8, old_table_utf8,
 
 3563                         new_db_utf8, new_table_utf8);
 
 3565                 if (ret == DB_DUPLICATE_KEY) {
 
 3567                                 new_db_utf8, new_table_utf8);
 
 3574                 if (ret != DB_SUCCESS) {
 
 3581         } 
while ((ret == DB_DEADLOCK
 
 3582                   || ret == DB_DUPLICATE_KEY
 
 3589         if (ret != DB_SUCCESS) {
 
 3591                             "Unable to rename statistics from " 
 3592                             "%s.%s to %s.%s in %s: %s. " 
 3593                             "They can be renamed later using " 
 3596                             "database_name = '%s', " 
 3597                             "table_name = '%s' " 
 3599                             "database_name = '%s' AND " 
 3600                             "table_name = '%s';",
 
 3602                             old_db_utf8, old_table_utf8,
 
 3603                             new_db_utf8, new_table_utf8,
 
 3604                             INDEX_STATS_NAME_PRINT,
 
 3607                             INDEX_STATS_NAME_PRINT,
 
 3608                             new_db_utf8, new_table_utf8,
 
 3609                             old_db_utf8, old_table_utf8);
 
 3616 #ifdef UNIV_COMPILE_TEST_FUNCS 
 3624 test_dict_table_schema_check()
 
 3639                 {
"c01", DATA_VARCHAR, 0, 123},
 
 3640                 {
"c02", DATA_INT, 0, 4},
 
 3641                 {
"c03", DATA_INT, DATA_NOT_NULL, 4},
 
 3642                 {
"c04", DATA_INT, DATA_UNSIGNED, 4},
 
 3643                 {
"c05", DATA_INT, 0, 8},
 
 3644                 {
"c06", DATA_INT, DATA_NOT_NULL | DATA_UNSIGNED, 8},
 
 3645                 {
"c07", DATA_INT, 0, 4},
 
 3646                 {
"c_extra", DATA_INT, 0, 4}
 
 3655         ut_snprintf(errstr, 
sizeof(errstr), 
"Table not found");
 
 3666                 printf(
"OK: test.tcheck ok\n");
 
 3668                 printf(
"ERROR: %s\n", errstr);
 
 3669                 printf(
"ERROR: test.tcheck not present or corrupted\n");
 
 3670                 goto test_dict_table_schema_check_end;
 
 3674         schema.columns[1].len = 8;
 
 3677                 printf(
"OK: test.tcheck.c02 has different length and is " 
 3678                        "reported as corrupted\n");
 
 3680                 printf(
"OK: test.tcheck.c02 has different length but is " 
 3681                        "reported as ok\n");
 
 3682                 goto test_dict_table_schema_check_end;
 
 3684         schema.columns[1].len = 4;
 
 3688         schema.columns[1].prtype_mask |= DATA_NOT_NULL;
 
 3691                 printf(
"OK: test.tcheck.c02 does not have NOT NULL while " 
 3692                        "it should and is reported as corrupted\n");
 
 3694                 printf(
"ERROR: test.tcheck.c02 does not have NOT NULL while " 
 3695                        "it should and is not reported as corrupted\n");
 
 3696                 goto test_dict_table_schema_check_end;
 
 3698         schema.columns[1].prtype_mask &= ~DATA_NOT_NULL;
 
 3704                 printf(
"ERROR: test.tcheck has more columns but is not " 
 3705                        "reported as corrupted\n");
 
 3706                 goto test_dict_table_schema_check_end;
 
 3708                 printf(
"OK: test.tcheck has more columns and is " 
 3709                        "reported as corrupted\n");
 
 3716                 printf(
"OK: test.tcheck has missing columns and is " 
 3717                        "reported as corrupted\n");
 
 3719                 printf(
"ERROR: test.tcheck has missing columns but is " 
 3720                        "reported as ok\n");
 
 3721                 goto test_dict_table_schema_check_end;
 
 3725         schema.table_name = 
"test/tcheck_nonexistent";
 
 3728                 printf(
"OK: test.tcheck_nonexistent is not present\n");
 
 3730                 printf(
"ERROR: test.tcheck_nonexistent is present!?\n");
 
 3731                 goto test_dict_table_schema_check_end;
 
 3734 test_dict_table_schema_check_end:
 
 3741 #define TEST_DATABASE_NAME              "foobardb" 
 3742 #define TEST_TABLE_NAME                 "test_dict_stats" 
 3744 #define TEST_N_ROWS                     111 
 3745 #define TEST_CLUSTERED_INDEX_SIZE       222 
 3746 #define TEST_SUM_OF_OTHER_INDEX_SIZES   333 
 3748 #define TEST_IDX1_NAME                  "tidx1" 
 3749 #define TEST_IDX1_COL1_NAME             "tidx1_col1" 
 3750 #define TEST_IDX1_INDEX_SIZE            123 
 3751 #define TEST_IDX1_N_LEAF_PAGES          234 
 3752 #define TEST_IDX1_N_DIFF1               50 
 3753 #define TEST_IDX1_N_DIFF1_SAMPLE_SIZE   500 
 3755 #define TEST_IDX2_NAME                  "tidx2" 
 3756 #define TEST_IDX2_COL1_NAME             "tidx2_col1" 
 3757 #define TEST_IDX2_COL2_NAME             "tidx2_col2" 
 3758 #define TEST_IDX2_COL3_NAME             "tidx2_col3" 
 3759 #define TEST_IDX2_COL4_NAME             "tidx2_col4" 
 3760 #define TEST_IDX2_INDEX_SIZE            321 
 3761 #define TEST_IDX2_N_LEAF_PAGES          432 
 3762 #define TEST_IDX2_N_DIFF1               60 
 3763 #define TEST_IDX2_N_DIFF1_SAMPLE_SIZE   600 
 3764 #define TEST_IDX2_N_DIFF2               61 
 3765 #define TEST_IDX2_N_DIFF2_SAMPLE_SIZE   610 
 3766 #define TEST_IDX2_N_DIFF3               62 
 3767 #define TEST_IDX2_N_DIFF3_SAMPLE_SIZE   620 
 3768 #define TEST_IDX2_N_DIFF4               63 
 3769 #define TEST_IDX2_N_DIFF4_SAMPLE_SIZE   630 
 3774 test_dict_stats_save()
 
 3779         ib_uint64_t     index1_stat_n_diff_key_vals[1];
 
 3780         ib_uint64_t     index1_stat_n_sample_sizes[1];
 
 3783         ib_uint64_t     index2_stat_n_diff_key_vals[4];
 
 3784         ib_uint64_t     index2_stat_n_sample_sizes[4];
 
 3788         table.
name = (
char*) (TEST_DATABASE_NAME 
"/" TEST_TABLE_NAME);
 
 3795         ut_d(table.magic_n = DICT_TABLE_MAGIC_N);
 
 3796         ut_d(index1.magic_n = DICT_INDEX_MAGIC_N);
 
 3798         index1.
name = TEST_IDX1_NAME;
 
 3802         index1.
fields = index1_fields;
 
 3807         index1_fields[0].
name = TEST_IDX1_COL1_NAME;
 
 3808         index1_stat_n_diff_key_vals[0] = TEST_IDX1_N_DIFF1;
 
 3809         index1_stat_n_sample_sizes[0] = TEST_IDX1_N_DIFF1_SAMPLE_SIZE;
 
 3811         ut_d(index2.magic_n = DICT_INDEX_MAGIC_N);
 
 3812         index2.
name = TEST_IDX2_NAME;
 
 3816         index2.
fields = index2_fields;
 
 3821         index2_fields[0].
name = TEST_IDX2_COL1_NAME;
 
 3822         index2_fields[1].
name = TEST_IDX2_COL2_NAME;
 
 3823         index2_fields[2].
name = TEST_IDX2_COL3_NAME;
 
 3824         index2_fields[3].
name = TEST_IDX2_COL4_NAME;
 
 3825         index2_stat_n_diff_key_vals[0] = TEST_IDX2_N_DIFF1;
 
 3826         index2_stat_n_diff_key_vals[1] = TEST_IDX2_N_DIFF2;
 
 3827         index2_stat_n_diff_key_vals[2] = TEST_IDX2_N_DIFF3;
 
 3828         index2_stat_n_diff_key_vals[3] = TEST_IDX2_N_DIFF4;
 
 3829         index2_stat_n_sample_sizes[0] = TEST_IDX2_N_DIFF1_SAMPLE_SIZE;
 
 3830         index2_stat_n_sample_sizes[1] = TEST_IDX2_N_DIFF2_SAMPLE_SIZE;
 
 3831         index2_stat_n_sample_sizes[2] = TEST_IDX2_N_DIFF3_SAMPLE_SIZE;
 
 3832         index2_stat_n_sample_sizes[3] = TEST_IDX2_N_DIFF4_SAMPLE_SIZE;
 
 3834         ret = dict_stats_save(&table);
 
 3836         ut_a(ret == DB_SUCCESS);
 
 3838         printf(
"\nOK: stats saved successfully, now go ahead and read " 
 3839                "what's inside %s and %s:\n\n",
 
 3840                TABLE_STATS_NAME_PRINT,
 
 3841                INDEX_STATS_NAME_PRINT);
 
 3843         printf(
"SELECT COUNT(*) = 1 AS table_stats_saved_successfully\n" 
 3846                "database_name = '%s' AND\n" 
 3847                "table_name = '%s' AND\n" 
 3849                "clustered_index_size = %d AND\n" 
 3850                "sum_of_other_index_sizes = %d;\n" 
 3852                TABLE_STATS_NAME_PRINT,
 
 3856                TEST_CLUSTERED_INDEX_SIZE,
 
 3857                TEST_SUM_OF_OTHER_INDEX_SIZES);
 
 3859         printf(
"SELECT COUNT(*) = 3 AS tidx1_stats_saved_successfully\n" 
 3862                "database_name = '%s' AND\n" 
 3863                "table_name = '%s' AND\n" 
 3864                "index_name = '%s' AND\n" 
 3866                " (stat_name = 'size' AND stat_value = %d AND" 
 3867                "  sample_size IS NULL) OR\n" 
 3868                " (stat_name = 'n_leaf_pages' AND stat_value = %d AND" 
 3869                "  sample_size IS NULL) OR\n" 
 3870                " (stat_name = 'n_diff_pfx01' AND stat_value = %d AND" 
 3871                "  sample_size = '%d' AND stat_description = '%s')\n" 
 3874                INDEX_STATS_NAME_PRINT,
 
 3878                TEST_IDX1_INDEX_SIZE,
 
 3879                TEST_IDX1_N_LEAF_PAGES,
 
 3881                TEST_IDX1_N_DIFF1_SAMPLE_SIZE,
 
 3882                TEST_IDX1_COL1_NAME);
 
 3884         printf(
"SELECT COUNT(*) = 6 AS tidx2_stats_saved_successfully\n" 
 3887                "database_name = '%s' AND\n" 
 3888                "table_name = '%s' AND\n" 
 3889                "index_name = '%s' AND\n" 
 3891                " (stat_name = 'size' AND stat_value = %d AND" 
 3892                "  sample_size IS NULL) OR\n" 
 3893                " (stat_name = 'n_leaf_pages' AND stat_value = %d AND" 
 3894                "  sample_size IS NULL) OR\n" 
 3895                " (stat_name = 'n_diff_pfx01' AND stat_value = %d AND" 
 3896                "  sample_size = '%d' AND stat_description = '%s') OR\n" 
 3897                " (stat_name = 'n_diff_pfx02' AND stat_value = %d AND" 
 3898                "  sample_size = '%d' AND stat_description = '%s,%s') OR\n" 
 3899                " (stat_name = 'n_diff_pfx03' AND stat_value = %d AND" 
 3900                "  sample_size = '%d' AND stat_description = '%s,%s,%s') OR\n" 
 3901                " (stat_name = 'n_diff_pfx04' AND stat_value = %d AND" 
 3902                "  sample_size = '%d' AND stat_description = '%s,%s,%s,%s')\n" 
 3905                INDEX_STATS_NAME_PRINT,
 
 3909                TEST_IDX2_INDEX_SIZE,
 
 3910                TEST_IDX2_N_LEAF_PAGES,
 
 3912                TEST_IDX2_N_DIFF1_SAMPLE_SIZE, TEST_IDX2_COL1_NAME,
 
 3914                TEST_IDX2_N_DIFF2_SAMPLE_SIZE,
 
 3915                TEST_IDX2_COL1_NAME, TEST_IDX2_COL2_NAME,
 
 3917                TEST_IDX2_N_DIFF3_SAMPLE_SIZE,
 
 3918                TEST_IDX2_COL1_NAME, TEST_IDX2_COL2_NAME, TEST_IDX2_COL3_NAME,
 
 3920                TEST_IDX2_N_DIFF4_SAMPLE_SIZE,
 
 3921                TEST_IDX2_COL1_NAME, TEST_IDX2_COL2_NAME, TEST_IDX2_COL3_NAME,
 
 3922                TEST_IDX2_COL4_NAME);
 
 3928 test_dict_stats_fetch_from_ps()
 
 3932         ib_uint64_t     index1_stat_n_diff_key_vals[1];
 
 3933         ib_uint64_t     index1_stat_n_sample_sizes[1];
 
 3935         ib_uint64_t     index2_stat_n_diff_key_vals[4];
 
 3936         ib_uint64_t     index2_stat_n_sample_sizes[4];
 
 3940         table.
name = (
char*) (TEST_DATABASE_NAME 
"/" TEST_TABLE_NAME);
 
 3944         ut_d(table.magic_n = DICT_TABLE_MAGIC_N);
 
 3946         index1.
name = TEST_IDX1_NAME;
 
 3947         ut_d(index1.magic_n = DICT_INDEX_MAGIC_N);
 
 3953         index2.
name = TEST_IDX2_NAME;
 
 3954         ut_d(index2.magic_n = DICT_INDEX_MAGIC_N);
 
 3960         ret = dict_stats_fetch_from_ps(&table);
 
 3962         ut_a(ret == DB_SUCCESS);
 
 3967              == TEST_SUM_OF_OTHER_INDEX_SIZES);
 
 3971         ut_a(index1_stat_n_diff_key_vals[0] == TEST_IDX1_N_DIFF1);
 
 3972         ut_a(index1_stat_n_sample_sizes[0] == TEST_IDX1_N_DIFF1_SAMPLE_SIZE);
 
 3976         ut_a(index2_stat_n_diff_key_vals[0] == TEST_IDX2_N_DIFF1);
 
 3977         ut_a(index2_stat_n_sample_sizes[0] == TEST_IDX2_N_DIFF1_SAMPLE_SIZE);
 
 3978         ut_a(index2_stat_n_diff_key_vals[1] == TEST_IDX2_N_DIFF2);
 
 3979         ut_a(index2_stat_n_sample_sizes[1] == TEST_IDX2_N_DIFF2_SAMPLE_SIZE);
 
 3980         ut_a(index2_stat_n_diff_key_vals[2] == TEST_IDX2_N_DIFF3);
 
 3981         ut_a(index2_stat_n_sample_sizes[2] == TEST_IDX2_N_DIFF3_SAMPLE_SIZE);
 
 3982         ut_a(index2_stat_n_diff_key_vals[3] == TEST_IDX2_N_DIFF4);
 
 3983         ut_a(index2_stat_n_sample_sizes[3] == TEST_IDX2_N_DIFF4_SAMPLE_SIZE);
 
 3985         printf(
"OK: fetch successful\n");
 
 3991 test_dict_stats_all()
 
 3993         test_dict_table_schema_check();
 
 3995         test_dict_stats_save();
 
 3997         test_dict_stats_fetch_from_ps();