]> git.pld-linux.org Git - packages/mysql.git/blobdiff - innodb_stats.patch
- upgrade trigger: mysql_upgrade works remotely, so --datadir is not used, use -...
[packages/mysql.git] / innodb_stats.patch
index 5192d11d8ed29317c2b56e8d4ecfa66b23b4ec60..8d8d78317089bd6f45291431841b25fad362caa1 100644 (file)
@@ -5,9 +5,8 @@
 #!!! notice !!!
 # Any small change to this file in the main branch
 # should be done or reviewed by the maintainer!
-diff -ruN a/storage/innobase/dict/dict0boot.c b/storage/innobase/dict/dict0boot.c
---- a/storage/innobase/dict/dict0boot.c        2010-12-03 15:48:03.034036843 +0900
-+++ b/storage/innobase/dict/dict0boot.c        2010-12-03 17:19:24.835112632 +0900
+--- a/storage/innobase/dict/dict0boot.c
++++ b/storage/innobase/dict/dict0boot.c
 @@ -266,6 +266,29 @@
        /* Get the dictionary header */
        dict_hdr = dict_hdr_get(&mtr);
@@ -47,22 +46,26 @@ diff -ruN a/storage/innobase/dict/dict0boot.c b/storage/innobase/dict/dict0boot.
  
        index = dict_mem_index_create("SYS_FIELDS", "CLUST_IND",
                                      DICT_HDR_SPACE,
-@@ -442,6 +465,41 @@
+@@ -442,6 +465,45 @@
                                        FALSE);
        ut_a(error == DB_SUCCESS);
  
 +      /*-------------------------*/
-+      table = dict_mem_table_create("SYS_STATS", DICT_HDR_SPACE, 3, 0);
++      table = dict_mem_table_create("SYS_STATS", DICT_HDR_SPACE, 4, 0);
 +      table->n_mysql_handles_opened = 1; /* for pin */
 +
 +      dict_mem_table_add_col(table, heap, "INDEX_ID", DATA_BINARY, 0, 0);
 +      dict_mem_table_add_col(table, heap, "KEY_COLS", DATA_INT, 0, 4);
 +      dict_mem_table_add_col(table, heap, "DIFF_VALS", DATA_BINARY, 0, 0);
++      dict_mem_table_add_col(table, heap, "NON_NULL_VALS", DATA_BINARY, 0, 0);
 +
 +      /* The '+ 2' below comes from the fields DB_TRX_ID, DB_ROLL_PTR */
 +#if DICT_SYS_STATS_DIFF_VALS_FIELD != 2 + 2
 +#error "DICT_SYS_STATS_DIFF_VALS_FIELD != 2 + 2"
 +#endif
++#if DICT_SYS_STATS_NON_NULL_VALS_FIELD != 3 + 2
++#error "DICT_SYS_STATS_NON_NULL_VALS_FIELD != 3 + 2"
++#endif
 +
 +      table->id = DICT_STATS_ID;
 +      dict_table_add_to_cache(table, heap);
@@ -89,7 +92,7 @@ diff -ruN a/storage/innobase/dict/dict0boot.c b/storage/innobase/dict/dict0boot.
        mtr_commit(&mtr);
        /*-------------------------*/
  
-@@ -455,6 +513,7 @@
+@@ -455,6 +517,7 @@
        dict_load_sys_table(dict_sys->sys_columns);
        dict_load_sys_table(dict_sys->sys_indexes);
        dict_load_sys_table(dict_sys->sys_fields);
@@ -97,10 +100,9 @@ diff -ruN a/storage/innobase/dict/dict0boot.c b/storage/innobase/dict/dict0boot.
  
        mutex_exit(&(dict_sys->mutex));
  }
-diff -ruN a/storage/innobase/dict/dict0crea.c b/storage/innobase/dict/dict0crea.c
---- a/storage/innobase/dict/dict0crea.c        2010-12-03 15:48:03.036081059 +0900
-+++ b/storage/innobase/dict/dict0crea.c        2010-12-03 17:19:24.836964976 +0900
-@@ -508,6 +508,51 @@
+--- a/storage/innobase/dict/dict0crea.c
++++ b/storage/innobase/dict/dict0crea.c
+@@ -508,6 +508,56 @@
  }
  
  /*****************************************************************//**
@@ -125,7 +127,7 @@ diff -ruN a/storage/innobase/dict/dict0crea.c b/storage/innobase/dict/dict0crea.
 +
 +      sys_stats = dict_sys->sys_stats;
 +
-+      entry = dtuple_create(heap, 3 + DATA_N_SYS_COLS);
++      entry = dtuple_create(heap, 4 + DATA_N_SYS_COLS);
 +
 +      dict_table_copy_types(entry, sys_stats);
 +
@@ -144,6 +146,11 @@ diff -ruN a/storage/innobase/dict/dict0crea.c b/storage/innobase/dict/dict0crea.
 +      ptr = mem_heap_alloc(heap, 8);
 +      mach_write_to_8(ptr, 0); /* initial value is 0 */
 +      dfield_set_data(dfield, ptr, 8);
++      /* 5: NON_NULL_VALS ------------------*/
++      dfield = dtuple_get_nth_field(entry, 3/*NON_NULL_VALS*/);
++      ptr = mem_heap_alloc(heap, 8);
++      mach_write_to_8(ptr, 0); /* initial value is 0 */
++      dfield_set_data(dfield, ptr, 8);
 +
 +      return(entry);
 +}
@@ -152,7 +159,7 @@ diff -ruN a/storage/innobase/dict/dict0crea.c b/storage/innobase/dict/dict0crea.
  Creates the tuple with which the index entry is searched for writing the index
  tree root page number, if such a tree is created.
  @return       the tuple for search */
-@@ -617,6 +662,27 @@
+@@ -617,6 +667,27 @@
  }
  
  /***************************************************************//**
@@ -180,7 +187,7 @@ diff -ruN a/storage/innobase/dict/dict0crea.c b/storage/innobase/dict/dict0crea.
  Creates an index tree for the index if it is not a member of a cluster.
  @return       DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
  static
-@@ -937,6 +1003,49 @@
+@@ -936,6 +1007,49 @@
                                          dict_sys->sys_fields, heap);
        node->field_def->common.parent = node;
  
@@ -230,7 +237,7 @@ diff -ruN a/storage/innobase/dict/dict0crea.c b/storage/innobase/dict/dict0crea.
        node->commit_node = commit_node_create(heap);
        node->commit_node->common.parent = node;
  
-@@ -1087,6 +1196,7 @@
+@@ -1086,6 +1200,7 @@
  
                node->state = INDEX_BUILD_FIELD_DEF;
                node->field_no = 0;
@@ -238,7 +245,7 @@ diff -ruN a/storage/innobase/dict/dict0crea.c b/storage/innobase/dict/dict0crea.
  
                thr->run_node = node->ind_def;
  
-@@ -1132,7 +1242,31 @@
+@@ -1131,7 +1246,31 @@
                        goto function_exit;
                }
  
@@ -271,16 +278,10 @@ diff -ruN a/storage/innobase/dict/dict0crea.c b/storage/innobase/dict/dict0crea.
        }
  
        if (node->state == INDEX_CREATE_INDEX_TREE) {
-@@ -1178,6 +1312,66 @@
-               return(NULL);
-       }
+@@ -1183,6 +1322,66 @@
+ }
  
-+      thr->run_node = que_node_get_parent(node);
-+
-+      return(thr);
-+}
-+
-+/****************************************************************//**
+ /****************************************************************//**
 +*/
 +UNIV_INTERN
 +que_thr_t*
@@ -335,13 +336,18 @@ diff -ruN a/storage/innobase/dict/dict0crea.c b/storage/innobase/dict/dict0crea.
 +              return(NULL);
 +      }
 +
-       thr->run_node = que_node_get_parent(node);
-       return(thr);
-diff -ruN a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.c
---- a/storage/innobase/dict/dict0dict.c        2010-12-03 15:48:03.040222428 +0900
-+++ b/storage/innobase/dict/dict0dict.c        2010-12-03 17:19:24.841947690 +0900
-@@ -756,7 +756,7 @@
++      thr->run_node = que_node_get_parent(node);
++
++      return(thr);
++}
++
++/****************************************************************//**
+ Creates the foreign key constraints system tables inside InnoDB
+ at database creation or database start if they are not found or are
+ not of the right form.
+--- a/storage/innobase/dict/dict0dict.c
++++ b/storage/innobase/dict/dict0dict.c
+@@ -755,7 +755,7 @@
                print an error message and return without doing
                anything. */
                dict_update_statistics(table, TRUE /* only update stats
@@ -350,7 +356,7 @@ diff -ruN a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.
        }
  
        return(table);
-@@ -4310,6 +4310,240 @@
+@@ -4343,6 +4343,295 @@
  }
  
  /*********************************************************************//**
@@ -402,15 +408,18 @@ diff -ruN a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.
 +      ulint           key_cols;
 +      ulint           n_cols;
 +      const rec_t*    rec;
++      ulint           n_fields;
 +      const byte*     field;
 +      ulint           len;
 +      ib_int64_t*     stat_n_diff_key_vals_tmp;
++      ib_int64_t*     stat_n_non_null_key_vals_tmp;
 +      byte*           buf;
 +      ulint           i;
 +      mtr_t           mtr;
 +
 +      n_cols = dict_index_get_n_unique(index);
 +      stat_n_diff_key_vals_tmp = mem_heap_zalloc(heap, (n_cols + 1) * sizeof(ib_int64_t));
++      stat_n_non_null_key_vals_tmp = mem_heap_zalloc(heap, (n_cols + 1) * sizeof(ib_int64_t));
 +
 +      sys_stats = dict_sys->sys_stats;
 +      sys_index = UT_LIST_GET_FIRST(sys_stats->indexes);
@@ -446,9 +455,13 @@ diff -ruN a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.
 +              }
 +
 +              if (rec_get_deleted_flag(rec, 0)) {
++                      /* don't count */
++                      i--;
 +                      goto next_rec;
 +              }
 +
++              n_fields = rec_get_n_fields_old(rec);
++
 +              field = rec_get_nth_field_old(rec, 1, &len);
 +              ut_a(len == 4);
 +
@@ -460,6 +473,21 @@ diff -ruN a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.
 +              ut_a(len == 8);
 +
 +              stat_n_diff_key_vals_tmp[i] = mach_read_from_8(field);
++
++              if (n_fields > DICT_SYS_STATS_NON_NULL_VALS_FIELD) {
++                      field = rec_get_nth_field_old(rec, DICT_SYS_STATS_NON_NULL_VALS_FIELD, &len);
++                      ut_a(len == 8);
++
++                      stat_n_non_null_key_vals_tmp[i] = mach_read_from_8(field);
++              } else {
++                      /* not enough fields: should be older */
++                      fprintf(stderr, "InnoDB: Notice: stats for %s/%s (%lu/%lu)"
++                                      " in SYS_STATS seems older format. "
++                                      "Please execute ANALYZE TABLE for it.\n",
++                                      index->table_name, index->name, i, n_cols);
++
++                      stat_n_non_null_key_vals_tmp[i] = ((ib_int64_t)(-1));
++              }
 +next_rec:
 +              btr_pcur_move_to_next_user_rec(&pcur, &mtr);
 +      }
@@ -469,6 +497,12 @@ diff -ruN a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.
 +
 +      for (i = 0; i <= n_cols; i++) {
 +              index->stat_n_diff_key_vals[i] = stat_n_diff_key_vals_tmp[i];
++              if (stat_n_non_null_key_vals_tmp[i] == ((ib_int64_t)(-1))) {
++                      /* approximate value */
++                      index->stat_n_non_null_key_vals[i] = stat_n_diff_key_vals_tmp[n_cols];
++              } else {
++                      index->stat_n_non_null_key_vals[i] = stat_n_non_null_key_vals_tmp[i];
++              }
 +      }
 +}
 +/*===========================================*/
@@ -507,18 +541,22 @@ diff -ruN a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.
 +      ulint           n_cols;
 +      ulint           rests;
 +      const rec_t*    rec;
++      ulint           n_fields;
 +      const byte*     field;
 +      ulint           len;
 +      ib_int64_t*     stat_n_diff_key_vals_tmp;
++      ib_int64_t*     stat_n_non_null_key_vals_tmp;
 +      byte*           buf;
 +      ulint           i;
 +      mtr_t           mtr;
 +
 +      n_cols = dict_index_get_n_unique(index);
 +      stat_n_diff_key_vals_tmp = mem_heap_zalloc(heap, (n_cols + 1) * sizeof(ib_int64_t));
++      stat_n_non_null_key_vals_tmp = mem_heap_zalloc(heap, (n_cols + 1) * sizeof(ib_int64_t));
 +
 +      for (i = 0; i <= n_cols; i++) {
 +              stat_n_diff_key_vals_tmp[i] = index->stat_n_diff_key_vals[i];
++              stat_n_non_null_key_vals_tmp[i] = index->stat_n_non_null_key_vals[i];
 +      }
 +
 +      sys_stats = dict_sys->sys_stats;
@@ -551,7 +589,21 @@ diff -ruN a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.
 +                      break;
 +              }
 +
++              btr_pcur_store_position(&pcur, &mtr);
++
 +              if (rec_get_deleted_flag(rec, 0)) {
++                      /* don't count */
++                      i--;
++                      goto next_rec;
++              }
++
++              n_fields = rec_get_n_fields_old(rec);
++
++              if (n_fields <= DICT_SYS_STATS_NON_NULL_VALS_FIELD) {
++                      /* not update for the older smaller format */
++                      fprintf(stderr, "InnoDB: Notice: stats for %s/%s (%lu/%lu)"
++                                      " in SYS_STATS seems older format. Please ANALYZE TABLE it.\n",
++                                      index->table_name, index->name, i, n_cols);
 +                      goto next_rec;
 +              }
 +
@@ -565,9 +617,18 @@ diff -ruN a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.
 +
 +              mlog_write_ull((byte*)field, stat_n_diff_key_vals_tmp[key_cols], &mtr);
 +
++              field = rec_get_nth_field_old(rec, DICT_SYS_STATS_NON_NULL_VALS_FIELD, &len);
++              ut_a(len == 8);
++
++              mlog_write_ull((byte*)field, stat_n_non_null_key_vals_tmp[key_cols], &mtr);
++
 +              rests--;
 +
 +next_rec:
++              mtr_commit(&mtr);
++              mtr_start(&mtr);
++              btr_pcur_restore_position(BTR_MODIFY_LEAF, &pcur, &mtr);
++
 +              btr_pcur_move_to_next_user_rec(&pcur, &mtr);
 +      }
 +      btr_pcur_close(&pcur);
@@ -591,7 +652,7 @@ diff -ruN a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.
  Calculates new estimates for table and index statistics. The statistics
  are used in query optimization. */
  UNIV_INTERN
-@@ -4317,10 +4551,11 @@
+@@ -4350,10 +4639,11 @@
  dict_update_statistics(
  /*===================*/
        dict_table_t*   table,          /*!< in/out: table */
@@ -604,7 +665,7 @@ diff -ruN a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.
  {
        dict_index_t*   index;
        ulint           sum_of_index_sizes      = 0;
-@@ -4337,6 +4572,27 @@
+@@ -4370,6 +4660,27 @@
                return;
        }
  
@@ -632,7 +693,7 @@ diff -ruN a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.
        /* Find out the sizes of the indexes and how many different values
        for the key they approximately have */
  
-@@ -4401,6 +4657,11 @@
+@@ -4434,6 +4745,11 @@
                index = dict_table_get_next_index(index);
        } while (index);
  
@@ -644,7 +705,86 @@ diff -ruN a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.
        index = dict_table_get_first_index(table);
  
        table->stat_n_rows = index->stat_n_diff_key_vals[
-@@ -4495,7 +4756,8 @@
+@@ -4451,6 +4767,78 @@
+       dict_table_stats_unlock(table, RW_X_LATCH);
+ }
++/*********************************************************************//**
++*/
++UNIV_INTERN
++ibool
++dict_is_older_statistics(
++/*=====================*/
++      dict_index_t*   index)
++{
++      mem_heap_t*     heap;
++      dict_table_t*   sys_stats;
++      dict_index_t*   sys_index;
++      btr_pcur_t      pcur;
++      dtuple_t*       tuple;
++      dfield_t*       dfield;
++      const rec_t*    rec;
++      ulint           n_fields;
++      ulint           len;
++      byte*           buf;
++      mtr_t           mtr;
++
++      heap = mem_heap_create(100);
++
++      sys_stats = dict_sys->sys_stats;
++      sys_index = UT_LIST_GET_FIRST(sys_stats->indexes);
++      ut_a(!dict_table_is_comp(sys_stats));
++
++      tuple = dtuple_create(heap, 1);
++      dfield = dtuple_get_nth_field(tuple, 0);
++
++      buf = mem_heap_alloc(heap, 8);
++      mach_write_to_8(buf, index->id);
++
++      dfield_set_data(dfield, buf, 8);
++      dict_index_copy_types(tuple, sys_index, 1);
++
++      mtr_start(&mtr);
++
++      btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
++                                BTR_SEARCH_LEAF, &pcur, &mtr);
++
++next_rec:
++      rec = btr_pcur_get_rec(&pcur);
++
++      if (!btr_pcur_is_on_user_rec(&pcur)
++          || mach_read_from_8(rec_get_nth_field_old(rec, 0, &len))
++              != index->id) {
++              /* not found */
++              btr_pcur_close(&pcur);
++              mtr_commit(&mtr);
++              mem_heap_free(heap);
++              /* no statistics == not older statistics */
++              return(FALSE);
++      }
++
++      if (rec_get_deleted_flag(rec, 0)) {
++              btr_pcur_move_to_next_user_rec(&pcur, &mtr);
++              goto next_rec;
++      }
++
++      n_fields = rec_get_n_fields_old(rec);
++
++      btr_pcur_close(&pcur);
++      mtr_commit(&mtr);
++      mem_heap_free(heap);
++
++      if (n_fields > DICT_SYS_STATS_NON_NULL_VALS_FIELD) {
++              return(FALSE);
++      } else {
++              return(TRUE);
++      }
++}
++
+ /**********************************************************************//**
+ Prints info of a foreign key constraint. */
+ static
+@@ -4528,7 +4916,8 @@
  
        ut_ad(mutex_own(&(dict_sys->mutex)));
  
@@ -654,9 +794,8 @@ diff -ruN a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.
  
        dict_table_stats_lock(table, RW_S_LATCH);
  
-diff -ruN a/storage/innobase/dict/dict0load.c b/storage/innobase/dict/dict0load.c
---- a/storage/innobase/dict/dict0load.c        2010-11-03 07:01:13.000000000 +0900
-+++ b/storage/innobase/dict/dict0load.c        2010-12-03 17:19:24.845947460 +0900
+--- a/storage/innobase/dict/dict0load.c
++++ b/storage/innobase/dict/dict0load.c
 @@ -50,7 +50,8 @@
        "SYS_COLUMNS",
        "SYS_FIELDS",
@@ -682,7 +821,7 @@ diff -ruN a/storage/innobase/dict/dict0load.c b/storage/innobase/dict/dict0load.
        }
  
        return(NULL);
-@@ -582,6 +584,61 @@
+@@ -582,6 +584,75 @@
  //#endif  /* FOREIGN_NOT_USED */
  
  /********************************************************************//**
@@ -697,16 +836,20 @@ diff -ruN a/storage/innobase/dict/dict0load.c b/storage/innobase/dict/dict0load.
 +      const rec_t*    rec,            /*!< in: current SYS_STATS rec */
 +      index_id_t*     index_id,       /*!< out: INDEX_ID */
 +      ulint*          key_cols,       /*!< out: KEY_COLS */
-+      ib_uint64_t*    diff_vals)      /*!< out: DIFF_VALS */
++      ib_uint64_t*    diff_vals,      /*!< out: DIFF_VALS */
++      ib_uint64_t*    non_null_vals)  /*!< out: NON_NULL_VALS */
 +{
 +      ulint           len;
 +      const byte*     field;
++      ulint           n_fields;
 +
 +      if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, 0))) {
 +              return("delete-marked record in SYS_STATS");
 +      }
 +
-+      if (UNIV_UNLIKELY(rec_get_n_fields_old(rec) != 5)) {
++      n_fields = rec_get_n_fields_old(rec);
++
++      if (UNIV_UNLIKELY(n_fields < 5)) {
 +              return("wrong number of columns in SYS_STATS record");
 +      }
 +
@@ -738,24 +881,33 @@ diff -ruN a/storage/innobase/dict/dict0load.c b/storage/innobase/dict/dict0load.
 +      }
 +      *diff_vals = mach_read_from_8(field);
 +
++      if (n_fields < 6) {
++              *non_null_vals = ((ib_uint64_t)(-1));
++      } else {
++              field = rec_get_nth_field_old(rec, 5/*NON_NULL_VALS*/, &len);
++              if (UNIV_UNLIKELY(len != 8)) {
++                      goto err_len;
++              }
++              *non_null_vals = mach_read_from_8(field);
++      }
++
 +      return(NULL);
 +}
 +/********************************************************************//**
  Determine the flags of a table described in SYS_TABLES.
  @return compressed page size in kilobytes; or 0 if the tablespace is
  uncompressed, ULINT_UNDEFINED on error */
-diff -ruN a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
---- a/storage/innobase/handler/ha_innodb.cc    2010-12-03 17:17:03.665960357 +0900
-+++ b/storage/innobase/handler/ha_innodb.cc    2010-12-03 17:22:21.586939783 +0900
-@@ -187,6 +187,7 @@
- static my_bool        innobase_rollback_on_timeout            = FALSE;
+--- a/storage/innobase/handler/ha_innodb.cc
++++ b/storage/innobase/handler/ha_innodb.cc
+@@ -188,6 +188,7 @@
  static my_bool        innobase_create_status_file             = FALSE;
  static my_bool        innobase_stats_on_metadata              = TRUE;
+ static my_bool        innobase_large_prefix                   = FALSE;
 +static my_bool        innobase_use_sys_stats_table            = FALSE;
  
  
  static char*  internal_innobase_data_file_path        = NULL;
-@@ -2407,6 +2408,8 @@
+@@ -2439,6 +2440,8 @@
                goto error;
        }
  
@@ -764,7 +916,7 @@ diff -ruN a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_
        /* -------------- Log files ---------------------------*/
  
        /* The default dir for log files is the datadir of MySQL */
-@@ -5211,6 +5214,10 @@
+@@ -5247,6 +5250,10 @@
  
        error = row_insert_for_mysql((byte*) record, prebuilt);
  
@@ -775,7 +927,7 @@ diff -ruN a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_
        /* Handle duplicate key errors */
        if (auto_inc_used) {
                ulint           err;
-@@ -5547,6 +5554,10 @@
+@@ -5583,6 +5590,10 @@
                }
        }
  
@@ -786,7 +938,7 @@ diff -ruN a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_
        innodb_srv_conc_exit_innodb(trx);
  
        error = convert_error_code_to_mysql(error,
-@@ -5600,6 +5611,10 @@
+@@ -5636,6 +5647,10 @@
  
        error = row_update_for_mysql((byte*) record, prebuilt);
  
@@ -797,31 +949,31 @@ diff -ruN a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_
        innodb_srv_conc_exit_innodb(trx);
  
        error = convert_error_code_to_mysql(
-@@ -5918,6 +5933,11 @@
+@@ -5954,6 +5969,11 @@
        case DB_SUCCESS:
                error = 0;
                table->status = 0;
 +#ifdef EXTENDED_FOR_USERSTAT
 +              rows_read++;
-+              if (active_index >= 0 && active_index < MAX_KEY)
++              if (active_index < MAX_KEY)
 +                      index_rows_read[active_index]++;
 +#endif
                break;
        case DB_RECORD_NOT_FOUND:
                error = HA_ERR_KEY_NOT_FOUND;
-@@ -6127,6 +6147,11 @@
+@@ -6163,6 +6183,11 @@
        case DB_SUCCESS:
                error = 0;
                table->status = 0;
 +#ifdef EXTENDED_FOR_USERSTAT
 +              rows_read++;
-+              if (active_index >= 0 && active_index < MAX_KEY)
++              if (active_index < MAX_KEY)
 +                      index_rows_read[active_index]++;
 +#endif
                break;
        case DB_RECORD_NOT_FOUND:
                error = HA_ERR_END_OF_FILE;
-@@ -8077,11 +8102,31 @@
+@@ -8105,11 +8130,35 @@
                        /* In sql_show we call with this flag: update
                        then statistics so that they are up-to-date */
  
@@ -838,6 +990,10 @@ diff -ruN a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_
 +                              for (index = dict_table_get_first_index(ib_table);
 +                                   index != NULL;
 +                                   index = dict_table_get_next_index(index)) {
++                                      if (dict_is_older_statistics(index)) {
++                                              row_delete_stats_for_mysql(index, prebuilt->trx);
++                                              innobase_commit_low(prebuilt->trx);
++                                      }
 +                                      row_insert_stats_for_mysql(index, prebuilt->trx);
 +                                      innobase_commit_low(prebuilt->trx);
 +                              }
@@ -854,7 +1010,7 @@ diff -ruN a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_
  
                        prebuilt->trx->op_info = "returning various info to MySQL";
                }
-@@ -8159,7 +8204,7 @@
+@@ -8187,7 +8236,7 @@
                are asked by MySQL to avoid locking. Another reason to
                avoid the call is that it uses quite a lot of CPU.
                See Bug#38185. */
@@ -863,7 +1019,7 @@ diff -ruN a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_
                    || !(flag & HA_STATUS_VARIABLE_EXTRA)) {
                        /* We do not update delete_length if no
                        locking is requested so the "old" value can
-@@ -11354,6 +11399,26 @@
+@@ -11401,6 +11450,26 @@
    "The number of index pages to sample when calculating statistics (default 8)",
    NULL, NULL, 8, 1, ~0ULL, 0);
  
@@ -890,7 +1046,7 @@ diff -ruN a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_
  static MYSQL_SYSVAR_BOOL(adaptive_hash_index, btr_search_enabled,
    PLUGIN_VAR_OPCMDARG,
    "Enable InnoDB adaptive hash index (enabled by default).  "
-@@ -11684,6 +11749,9 @@
+@@ -11727,6 +11796,9 @@
    MYSQL_SYSVAR(recovery_update_relay_log),
    MYSQL_SYSVAR(rollback_on_timeout),
    MYSQL_SYSVAR(stats_on_metadata),
@@ -900,7 +1056,7 @@ diff -ruN a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_
    MYSQL_SYSVAR(stats_sample_pages),
    MYSQL_SYSVAR(adaptive_hash_index),
    MYSQL_SYSVAR(stats_method),
-@@ -11753,7 +11821,10 @@
+@@ -11796,7 +11868,10 @@
  i_s_innodb_sys_columns,
  i_s_innodb_sys_fields,
  i_s_innodb_sys_foreign,
@@ -912,9 +1068,8 @@ diff -ruN a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_
  mysql_declare_plugin_end;
  
  /** @brief Initialize the default value of innodb_commit_concurrency.
-diff -ruN a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc
---- a/storage/innobase/handler/i_s.cc  2010-12-03 17:17:03.666956117 +0900
-+++ b/storage/innobase/handler/i_s.cc  2010-12-03 17:19:24.880964526 +0900
+--- a/storage/innobase/handler/i_s.cc
++++ b/storage/innobase/handler/i_s.cc
 @@ -49,6 +49,7 @@
  #include "trx0trx.h" /* for TRX_QUE_STATE_STR_MAX_LEN */
  #include "trx0rseg.h" /* for trx_rseg_struct */
@@ -922,8 +1077,8 @@ diff -ruN a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc
 +#include "dict0dict.h" /* for dict_sys */
  }
  
- static const char plugin_author[] = "Innobase Oy";
-@@ -3457,6 +3458,203 @@
+ #define OK(expr)              \
+@@ -3455,6 +3456,221 @@
        STRUCT_FLD(__reserved1, NULL)
  };
  
@@ -957,6 +1112,15 @@ diff -ruN a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc
 +       STRUCT_FLD(old_name,           ""),
 +       STRUCT_FLD(open_method,        SKIP_OPEN_TABLE)},
 +
++#define SYS_STATS_NON_NULL_VALS       3
++      {STRUCT_FLD(field_name,         "NON_NULL_VALS"),
++       STRUCT_FLD(field_length,       MY_INT64_NUM_DECIMAL_DIGITS),
++       STRUCT_FLD(field_type,         MYSQL_TYPE_LONGLONG),
++       STRUCT_FLD(value,              0),
++       STRUCT_FLD(field_flags,        MY_I_S_UNSIGNED | MY_I_S_MAYBE_NULL),
++       STRUCT_FLD(old_name,           ""),
++       STRUCT_FLD(open_method,        SKIP_OPEN_TABLE)},
++
 +      END_OF_ST_FIELD_INFO
 +};
 +/**********************************************************************//**
@@ -970,6 +1134,7 @@ diff -ruN a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc
 +      index_id_t      index_id,       /*!< in: INDEX_ID */
 +      ulint           key_cols,       /*!< in: KEY_COLS */
 +      ib_uint64_t     diff_vals,      /*!< in: DIFF_VALS */
++      ib_uint64_t     non_null_vals,  /*!< in: NON_NULL_VALS */
 +      TABLE*          table_to_fill)  /*!< in/out: fill this table */
 +{
 +      Field**         fields;
@@ -984,6 +1149,13 @@ diff -ruN a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc
 +
 +      OK(fields[SYS_STATS_DIFF_VALS]->store(longlong(diff_vals), TRUE));
 +
++      if (non_null_vals == ((ib_uint64_t)(-1))) {
++              fields[SYS_STATS_NON_NULL_VALS]->set_null();
++      } else {
++              OK(fields[SYS_STATS_NON_NULL_VALS]->store(longlong(non_null_vals), TRUE));
++              fields[SYS_STATS_NON_NULL_VALS]->set_notnull();
++      }
++
 +      OK(schema_table_store_record(thd, table_to_fill));
 +
 +      DBUG_RETURN(0);
@@ -1022,17 +1194,18 @@ diff -ruN a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc
 +              index_id_t      index_id;
 +              ulint           key_cols;
 +              ib_uint64_t     diff_vals;
++              ib_uint64_t     non_null_vals;
 +
 +              /* Extract necessary information from a SYS_FOREIGN_COLS row */
 +              err_msg = dict_process_sys_stats_rec(
-+                      heap, rec, &index_id, &key_cols, &diff_vals);
++                      heap, rec, &index_id, &key_cols, &diff_vals, &non_null_vals);
 +
 +              mtr_commit(&mtr);
 +              mutex_exit(&dict_sys->mutex);
 +
 +              if (!err_msg) {
 +                      i_s_dict_fill_sys_stats(
-+                              thd, index_id, key_cols, diff_vals,
++                              thd, index_id, key_cols, diff_vals, non_null_vals,
 +                              tables->table);
 +              } else {
 +                      push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
@@ -1091,7 +1264,7 @@ diff -ruN a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc
 +
 +      /* plugin author (for SHOW PLUGINS) */
 +      /* const char* */
-+      STRUCT_FLD(author, plugin_author),
++      STRUCT_FLD(author, "Percona"),
 +
 +      /* general descriptive text (for SHOW PLUGINS) */
 +      /* const char* */
@@ -1127,7 +1300,7 @@ diff -ruN a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc
  /***********************************************************************
  */
  static ST_FIELD_INFO  i_s_innodb_rseg_fields_info[] =
-@@ -3619,3 +3817,347 @@
+@@ -3617,3 +3833,347 @@
        /* void* */
        STRUCT_FLD(__reserved1, NULL)
  };
@@ -1449,7 +1622,7 @@ diff -ruN a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc
 +      STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
 +      STRUCT_FLD(info, &i_s_info),
 +      STRUCT_FLD(name, "INNODB_TABLE_STATS"),
-+      STRUCT_FLD(author, plugin_author),
++      STRUCT_FLD(author, "Percona"),
 +      STRUCT_FLD(descr, "InnoDB table statistics in memory"),
 +      STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
 +      STRUCT_FLD(init, i_s_innodb_table_stats_init),
@@ -1465,7 +1638,7 @@ diff -ruN a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc
 +      STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
 +      STRUCT_FLD(info, &i_s_info),
 +      STRUCT_FLD(name, "INNODB_INDEX_STATS"),
-+      STRUCT_FLD(author, plugin_author),
++      STRUCT_FLD(author, "Percona"),
 +      STRUCT_FLD(descr, "InnoDB index statistics in memory"),
 +      STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
 +      STRUCT_FLD(init, i_s_innodb_index_stats_init),
@@ -1475,10 +1648,9 @@ diff -ruN a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc
 +      STRUCT_FLD(system_vars, NULL),
 +      STRUCT_FLD(__reserved1, NULL)
 +};
-diff -ruN a/storage/innobase/handler/i_s.h b/storage/innobase/handler/i_s.h
---- a/storage/innobase/handler/i_s.h   2010-12-03 17:17:03.668953884 +0900
-+++ b/storage/innobase/handler/i_s.h   2010-12-03 17:19:24.882947826 +0900
-@@ -41,5 +41,8 @@
+--- a/storage/innobase/handler/i_s.h
++++ b/storage/innobase/handler/i_s.h
+@@ -43,5 +43,8 @@
  extern struct st_mysql_plugin   i_s_innodb_sys_foreign;
  extern struct st_mysql_plugin   i_s_innodb_sys_foreign_cols;
  extern struct st_mysql_plugin i_s_innodb_rseg;
@@ -1487,9 +1659,8 @@ diff -ruN a/storage/innobase/handler/i_s.h b/storage/innobase/handler/i_s.h
 +extern struct st_mysql_plugin i_s_innodb_index_stats;
  
  #endif /* i_s_h */
-diff -ruN a/storage/innobase/include/dict0boot.h b/storage/innobase/include/dict0boot.h
---- a/storage/innobase/include/dict0boot.h     2010-11-03 07:01:13.000000000 +0900
-+++ b/storage/innobase/include/dict0boot.h     2010-12-03 17:19:24.885947372 +0900
+--- a/storage/innobase/include/dict0boot.h
++++ b/storage/innobase/include/dict0boot.h
 @@ -104,6 +104,7 @@
  #define DICT_COLUMNS_ID               2
  #define DICT_INDEXES_ID               3
@@ -1512,11 +1683,12 @@ diff -ruN a/storage/innobase/include/dict0boot.h b/storage/innobase/include/dict
  /*-------------------------------------------------------------*/
  
  /* The field number of the page number field in the sys_indexes table
-@@ -144,11 +148,15 @@
+@@ -144,11 +148,16 @@
  #define DICT_SYS_INDEXES_TYPE_FIELD    6
  #define DICT_SYS_INDEXES_NAME_FIELD    4
  
 +#define DICT_SYS_STATS_DIFF_VALS_FIELD         4
++#define DICT_SYS_STATS_NON_NULL_VALS_FIELD    5
 +
  /* When a row id which is zero modulo this number (which must be a power of
  two) is assigned, the field DICT_HDR_ROW_ID on the dictionary header page is
@@ -1528,9 +1700,8 @@ diff -ruN a/storage/innobase/include/dict0boot.h b/storage/innobase/include/dict
  #ifndef UNIV_NONINL
  #include "dict0boot.ic"
  #endif
-diff -ruN a/storage/innobase/include/dict0crea.h b/storage/innobase/include/dict0crea.h
---- a/storage/innobase/include/dict0crea.h     2010-11-03 07:01:13.000000000 +0900
-+++ b/storage/innobase/include/dict0crea.h     2010-12-03 17:19:24.886949643 +0900
+--- a/storage/innobase/include/dict0crea.h
++++ b/storage/innobase/include/dict0crea.h
 @@ -53,6 +53,14 @@
        dict_index_t*   index,  /*!< in: index to create, built as a memory data
                                structure */
@@ -1584,10 +1755,9 @@ diff -ruN a/storage/innobase/include/dict0crea.h b/storage/innobase/include/dict
  
  #ifndef UNIV_NONINL
  #include "dict0crea.ic"
-diff -ruN a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h
---- a/storage/innobase/include/dict0dict.h     2010-12-03 15:48:03.073024387 +0900
-+++ b/storage/innobase/include/dict0dict.h     2010-12-03 17:19:24.888965622 +0900
-@@ -1084,10 +1084,11 @@
+--- a/storage/innobase/include/dict0dict.h
++++ b/storage/innobase/include/dict0dict.h
+@@ -1109,10 +1109,18 @@
  dict_update_statistics(
  /*===================*/
        dict_table_t*   table,          /*!< in/out: table */
@@ -1597,10 +1767,17 @@ diff -ruN a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict
                                        not been initialized yet, otherwise
                                        do nothing */
 +      ibool           sync);
++/*********************************************************************//**
++*/
++UNIV_INTERN
++ibool
++dict_is_older_statistics(
++/*=====================*/
++      dict_index_t*   index);
  /********************************************************************//**
  Reserves the dictionary system mutex for MySQL. */
  UNIV_INTERN
-@@ -1202,6 +1203,7 @@
+@@ -1227,6 +1235,7 @@
        dict_table_t*   sys_columns;    /*!< SYS_COLUMNS table */
        dict_table_t*   sys_indexes;    /*!< SYS_INDEXES table */
        dict_table_t*   sys_fields;     /*!< SYS_FIELDS table */
@@ -1608,9 +1785,8 @@ diff -ruN a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict
  };
  #endif /* !UNIV_HOTBACKUP */
  
-diff -ruN a/storage/innobase/include/dict0load.h b/storage/innobase/include/dict0load.h
---- a/storage/innobase/include/dict0load.h     2010-11-03 07:01:13.000000000 +0900
-+++ b/storage/innobase/include/dict0load.h     2010-12-03 17:19:24.889947481 +0900
+--- a/storage/innobase/include/dict0load.h
++++ b/storage/innobase/include/dict0load.h
 @@ -41,6 +41,7 @@
        SYS_FIELDS,
        SYS_FOREIGN,
@@ -1619,7 +1795,7 @@ diff -ruN a/storage/innobase/include/dict0load.h b/storage/innobase/include/dict
  
        /* This must be last item. Defines the number of system tables. */
        SYS_NUM_SYSTEM_TABLES
-@@ -319,6 +320,19 @@
+@@ -327,6 +328,20 @@
        const char**    ref_col_name,   /*!< out: referenced column name
                                        in referenced table */
        ulint*          pos);           /*!< out: column position */
@@ -1635,13 +1811,13 @@ diff -ruN a/storage/innobase/include/dict0load.h b/storage/innobase/include/dict
 +      const rec_t*    rec,            /*!< in: current SYS_STATS rec */
 +      index_id_t*     index_id,       /*!< out: INDEX_ID */
 +      ulint*          key_cols,       /*!< out: KEY_COLS */
-+      ib_uint64_t*    diff_vals);     /*!< out: DIFF_VALS */
++      ib_uint64_t*    diff_vals,      /*!< out: DIFF_VALS */
++      ib_uint64_t*    non_null_vals); /*!< out: NON_NULL_VALS */
  #ifndef UNIV_NONINL
  #include "dict0load.ic"
  #endif
-diff -ruN a/storage/innobase/include/que0que.h b/storage/innobase/include/que0que.h
---- a/storage/innobase/include/que0que.h       2010-11-03 07:01:13.000000000 +0900
-+++ b/storage/innobase/include/que0que.h       2010-12-03 17:19:24.892947946 +0900
+--- a/storage/innobase/include/que0que.h
++++ b/storage/innobase/include/que0que.h
 @@ -492,6 +492,8 @@
  #define QUE_NODE_CALL         31
  #define QUE_NODE_EXIT         32
@@ -1651,10 +1827,9 @@ diff -ruN a/storage/innobase/include/que0que.h b/storage/innobase/include/que0qu
  /* Query thread states */
  #define QUE_THR_RUNNING               1
  #define QUE_THR_PROCEDURE_WAIT        2
-diff -ruN a/storage/innobase/include/row0mysql.h b/storage/innobase/include/row0mysql.h
---- a/storage/innobase/include/row0mysql.h     2010-11-03 07:01:13.000000000 +0900
-+++ b/storage/innobase/include/row0mysql.h     2010-12-03 17:19:24.904973020 +0900
-@@ -387,6 +387,14 @@
+--- a/storage/innobase/include/row0mysql.h
++++ b/storage/innobase/include/row0mysql.h
+@@ -387,6 +387,22 @@
                                        then checked for not being too
                                        large. */
  /*********************************************************************//**
@@ -1665,14 +1840,21 @@ diff -ruN a/storage/innobase/include/row0mysql.h b/storage/innobase/include/row0
 +/*=======================*/
 +      dict_index_t*   index,
 +      trx_t*          trx);
++/*********************************************************************//**
++*/
++UNIV_INTERN
++int
++row_delete_stats_for_mysql(
++/*=======================*/
++      dict_index_t*   index,
++      trx_t*          trx);
 +/*********************************************************************//**
  Scans a table create SQL string and adds to the data dictionary
  the foreign key constraints declared in the string. This function
  should be called after the indexes for a table have been created.
-diff -ruN a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h
---- a/storage/innobase/include/srv0srv.h       2010-12-03 15:53:54.622036720 +0900
-+++ b/storage/innobase/include/srv0srv.h       2010-12-03 17:19:24.906953188 +0900
-@@ -214,6 +214,9 @@
+--- a/storage/innobase/include/srv0srv.h
++++ b/storage/innobase/include/srv0srv.h
+@@ -211,6 +211,9 @@
  extern ibool  srv_innodb_status;
  
  extern unsigned long long     srv_stats_sample_pages;
@@ -1682,9 +1864,8 @@ diff -ruN a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0sr
  
  extern ibool  srv_use_doublewrite_buf;
  extern ibool  srv_use_checksums;
-diff -ruN a/storage/innobase/que/que0que.c b/storage/innobase/que/que0que.c
---- a/storage/innobase/que/que0que.c   2010-11-03 07:01:13.000000000 +0900
-+++ b/storage/innobase/que/que0que.c   2010-12-03 17:19:24.910953422 +0900
+--- a/storage/innobase/que/que0que.c
++++ b/storage/innobase/que/que0que.c
 @@ -621,11 +621,21 @@
  
                que_graph_free_recursive(cre_ind->ind_def);
@@ -1725,10 +1906,20 @@ diff -ruN a/storage/innobase/que/que0que.c b/storage/innobase/que/que0que.c
        } else if (type == QUE_NODE_ROW_PRINTF) {
                thr = row_printf_step(thr);
        } else {
-diff -ruN a/storage/innobase/row/row0merge.c b/storage/innobase/row/row0merge.c
---- a/storage/innobase/row/row0merge.c 2010-11-03 07:01:13.000000000 +0900
-+++ b/storage/innobase/row/row0merge.c 2010-12-03 17:19:24.914955391 +0900
-@@ -2020,6 +2020,8 @@
+--- a/storage/innobase/row/row0ins.c
++++ b/storage/innobase/row/row0ins.c
+@@ -2013,6 +2013,8 @@
+       }
+ #ifdef UNIV_DEBUG
++      if (!srv_use_sys_stats_table
++          || index != UT_LIST_GET_FIRST(dict_sys->sys_stats->indexes))
+       {
+               page_t* page = btr_cur_get_page(&cursor);
+               rec_t*  first_rec = page_rec_get_next(
+--- a/storage/innobase/row/row0merge.c
++++ b/storage/innobase/row/row0merge.c
+@@ -2019,6 +2019,8 @@
                "UPDATE SYS_INDEXES SET NAME=CONCAT('"
                TEMP_INDEX_PREFIX_STR "', NAME) WHERE ID = :indexid;\n"
                "COMMIT WORK;\n"
@@ -1737,9 +1928,8 @@ diff -ruN a/storage/innobase/row/row0merge.c b/storage/innobase/row/row0merge.c
                /* Drop the field definitions of the index. */
                "DELETE FROM SYS_FIELDS WHERE INDEX_ID = :indexid;\n"
                /* Drop the index definition and the B-tree. */
-diff -ruN a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c
---- a/storage/innobase/row/row0mysql.c 2010-11-03 07:01:13.000000000 +0900
-+++ b/storage/innobase/row/row0mysql.c 2010-12-03 17:19:24.918953476 +0900
+--- a/storage/innobase/row/row0mysql.c
++++ b/storage/innobase/row/row0mysql.c
 @@ -921,6 +921,9 @@
  
        table->stat_modified_counter = counter + 1;
@@ -1759,7 +1949,7 @@ diff -ruN a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c
        }
  }
  
-@@ -2105,6 +2108,45 @@
+@@ -2076,6 +2079,71 @@
  }
  
  /*********************************************************************//**
@@ -1776,7 +1966,7 @@ diff -ruN a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c
 +      que_thr_t*      thr;
 +      ulint           err;
 +
-+      ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
++      //ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
 +
 +      trx->op_info = "try to insert rows to SYS_STATS";
 +
@@ -1801,11 +1991,37 @@ diff -ruN a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c
 +      return((int) err);
 +}
 +
++/*********************************************************************//**
++*/
++UNIV_INTERN
++int
++row_delete_stats_for_mysql(
++/*=============================*/
++      dict_index_t*   index,
++      trx_t*          trx)
++{
++      pars_info_t*    info    = pars_info_create();
++
++      trx->op_info = "delete rows from SYS_STATS";
++
++      trx_start_if_not_started(trx);
++      trx->error_state = DB_SUCCESS;
++
++      pars_info_add_ull_literal(info, "indexid", index->id);
++
++      return((int) que_eval_sql(info,
++                                "PROCEDURE DELETE_STATISTICS_PROC () IS\n"
++                                "BEGIN\n"
++                                "DELETE FROM SYS_STATS WHERE INDEX_ID = :indexid;\n"
++                                "END;\n"
++                                , TRUE, trx));
++}
++
 +/*********************************************************************//**
  Scans a table create SQL string and adds to the data dictionary
  the foreign key constraints declared in the string. This function
  should be called after the indexes for a table have been created.
-@@ -3024,7 +3066,7 @@
+@@ -3000,7 +3068,7 @@
        dict_table_autoinc_initialize(table, 1);
        dict_table_autoinc_unlock(table);
        dict_update_statistics(table, FALSE /* update even if stats are
@@ -1814,7 +2030,7 @@ diff -ruN a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c
  
        trx_commit_for_mysql(trx);
  
-@@ -3326,6 +3368,8 @@
+@@ -3302,6 +3370,8 @@
                           "       IF (SQL % NOTFOUND) THEN\n"
                           "               found := 0;\n"
                           "       ELSE\n"
@@ -1823,10 +2039,75 @@ diff -ruN a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c
                           "               DELETE FROM SYS_FIELDS\n"
                           "               WHERE INDEX_ID = index_id;\n"
                           "               DELETE FROM SYS_INDEXES\n"
-diff -ruN a/storage/innobase/srv/srv0srv.c b/storage/innobase/srv/srv0srv.c
---- a/storage/innobase/srv/srv0srv.c   2010-12-03 15:53:54.625288512 +0900
-+++ b/storage/innobase/srv/srv0srv.c   2010-12-03 17:19:24.922953561 +0900
-@@ -402,6 +402,9 @@
+--- a/storage/innobase/row/row0row.c
++++ b/storage/innobase/row/row0row.c
+@@ -373,6 +373,14 @@
+       rec_len = rec_offs_n_fields(offsets);
++      if (srv_use_sys_stats_table
++          && index == UT_LIST_GET_FIRST(dict_sys->sys_stats->indexes)) {
++              if (rec_len < dict_index_get_n_fields(index)) {
++                      /* the new record should be extended */
++                      rec_len = dict_index_get_n_fields(index);
++              }
++      }
++
+       entry = dtuple_create(heap, rec_len);
+       dtuple_set_n_fields_cmp(entry,
+@@ -384,6 +392,14 @@
+       for (i = 0; i < rec_len; i++) {
+               dfield = dtuple_get_nth_field(entry, i);
++
++              if (srv_use_sys_stats_table
++                  && index == UT_LIST_GET_FIRST(dict_sys->sys_stats->indexes)
++                  && i >= rec_offs_n_fields(offsets)) {
++                      dfield_set_null(dfield);
++                      continue;
++              }
++
+               field = rec_get_nth_field(rec, offsets, i, &len);
+               dfield_set_data(dfield, field, len);
+--- a/storage/innobase/row/row0upd.c
++++ b/storage/innobase/row/row0upd.c
+@@ -439,6 +439,12 @@
+                               0);
+               }
++              if (srv_use_sys_stats_table
++                  && index == UT_LIST_GET_FIRST(dict_sys->sys_stats->indexes)
++                  && upd_field->field_no >= rec_offs_n_fields(offsets)) {
++                      return(TRUE);
++              }
++
+               old_len = rec_offs_nth_size(offsets, upd_field->field_no);
+               if (rec_offs_comp(offsets)
+@@ -879,6 +885,18 @@
+       for (i = 0; i < dtuple_get_n_fields(entry); i++) {
++              if (srv_use_sys_stats_table
++                  && index == UT_LIST_GET_FIRST(dict_sys->sys_stats->indexes)
++                  && i >= rec_offs_n_fields(offsets)) {
++                      dfield = dtuple_get_nth_field(entry, i);
++
++                      upd_field = upd_get_nth_field(update, n_diff);
++                      dfield_copy(&(upd_field->new_val), dfield);
++                      upd_field_set_field_no(upd_field, i, index, trx);
++                      n_diff++;
++                      goto skip_compare;
++              }
++
+               data = rec_get_nth_field(rec, offsets, i, &len);
+               dfield = dtuple_get_nth_field(entry, i);
+--- a/storage/innobase/srv/srv0srv.c
++++ b/storage/innobase/srv/srv0srv.c
+@@ -398,6 +398,9 @@
  /* When estimating number of different key values in an index, sample
  this many index pages */
  UNIV_INTERN unsigned long long        srv_stats_sample_pages = 8;
@@ -1836,3 +2117,35 @@ diff -ruN a/storage/innobase/srv/srv0srv.c b/storage/innobase/srv/srv0srv.c
  
  UNIV_INTERN ibool     srv_use_doublewrite_buf = TRUE;
  UNIV_INTERN ibool     srv_use_checksums = TRUE;
+--- a/storage/innobase/trx/trx0rec.c
++++ b/storage/innobase/trx/trx0rec.c
+@@ -669,15 +669,27 @@
+       /* Save to the undo log the old values of the columns to be updated. */
+       if (update) {
++              ulint   extended = 0;
+               if (trx_undo_left(undo_page, ptr) < 5) {
+                       return(0);
+               }
+-              ptr += mach_write_compressed(ptr, upd_get_n_fields(update));
++              if (srv_use_sys_stats_table
++                  && index == UT_LIST_GET_FIRST(dict_sys->sys_stats->indexes)) {
++                      for (i = 0; i < upd_get_n_fields(update); i++) {
++                              ulint   pos = upd_get_nth_field(update, i)->field_no;
+-              for (i = 0; i < upd_get_n_fields(update); i++) {
++                              if (pos >= rec_offs_n_fields(offsets)) {
++                                      extended++;
++                              }
++                      }
++              }
++
++              ptr += mach_write_compressed(ptr, upd_get_n_fields(update) - extended);
++
++              for (i = 0; i < upd_get_n_fields(update) - extended; i++) {
+                       ulint   pos = upd_get_nth_field(update, i)->field_no;
This page took 0.075862 seconds and 4 git commands to generate.