summaryrefslogtreecommitdiff
path: root/sql/sql_statistics.cc
diff options
context:
space:
mode:
authorSergei Golubchik <serg@mariadb.org>2015-11-19 15:52:14 +0100
committerSergei Golubchik <serg@mariadb.org>2015-11-19 15:52:14 +0100
commitbeded7d9c9592ca8fdfc367f7c64f89c35995c44 (patch)
treea215a54ed5043bb17fe7d69a69439e05b21682d5 /sql/sql_statistics.cc
parentaf71da5d2f90c82b2357e808640003907c488bc2 (diff)
parent2553f143fdeb9068eb02a8fda58750c24071f5ef (diff)
downloadmariadb-git-beded7d9c9592ca8fdfc367f7c64f89c35995c44.tar.gz
Merge branch '10.0' into 10.1
Diffstat (limited to 'sql/sql_statistics.cc')
-rw-r--r--sql/sql_statistics.cc142
1 files changed, 132 insertions, 10 deletions
diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc
index 021e4c37e86..28e76ae43f1 100644
--- a/sql/sql_statistics.cc
+++ b/sql/sql_statistics.cc
@@ -592,6 +592,8 @@ public:
stat_file->extra(HA_EXTRA_FLUSH);
return FALSE;
}
+
+ friend class Stat_table_write_iter;
};
@@ -888,7 +890,7 @@ public:
@note
A value from the field min_value/max_value is always converted
- into a utf8 string. If the length of the column 'min_value'/'max_value'
+ into a varbinary string. If the length of the column 'min_value'/'max_value'
is less than the length of the string the string is trimmed to fit the
length of the column.
*/
@@ -896,7 +898,7 @@ public:
void store_stat_fields()
{
char buff[MAX_FIELD_WIDTH];
- String val(buff, sizeof(buff), &my_charset_utf8_bin);
+ String val(buff, sizeof(buff), &my_charset_bin);
for (uint i= COLUMN_STAT_MIN_VALUE; i <= COLUMN_STAT_HISTOGRAM; i++)
{
@@ -913,7 +915,7 @@ public:
else
{
table_field->collected_stats->min_value->val_str(&val);
- stat_field->store(val.ptr(), val.length(), &my_charset_utf8_bin);
+ stat_field->store(val.ptr(), val.length(), &my_charset_bin);
}
break;
case COLUMN_STAT_MAX_VALUE:
@@ -922,7 +924,7 @@ public:
else
{
table_field->collected_stats->max_value->val_str(&val);
- stat_field->store(val.ptr(), val.length(), &my_charset_utf8_bin);
+ stat_field->store(val.ptr(), val.length(), &my_charset_bin);
}
break;
case COLUMN_STAT_NULLS_RATIO:
@@ -983,7 +985,7 @@ public:
if (find_stat())
{
char buff[MAX_FIELD_WIDTH];
- String val(buff, sizeof(buff), &my_charset_utf8_bin);
+ String val(buff, sizeof(buff), &my_charset_bin);
for (uint i= COLUMN_STAT_MIN_VALUE; i <= COLUMN_STAT_HIST_TYPE; i++)
{
@@ -1002,12 +1004,12 @@ public:
case COLUMN_STAT_MIN_VALUE:
stat_field->val_str(&val);
table_field->read_stats->min_value->store(val.ptr(), val.length(),
- &my_charset_utf8_bin);
+ &my_charset_bin);
break;
case COLUMN_STAT_MAX_VALUE:
stat_field->val_str(&val);
table_field->read_stats->max_value->store(val.ptr(), val.length(),
- &my_charset_utf8_bin);
+ &my_charset_bin);
break;
case COLUMN_STAT_NULLS_RATIO:
table_field->read_stats->set_nulls_ratio(stat_field->val_real());
@@ -1053,7 +1055,7 @@ public:
if (find_stat())
{
char buff[MAX_FIELD_WIDTH];
- String val(buff, sizeof(buff), &my_charset_utf8_bin);
+ String val(buff, sizeof(buff), &my_charset_bin);
uint fldno= COLUMN_STAT_HISTOGRAM;
Field *stat_field= stat_table->field[fldno];
table_field->read_stats->set_not_null(fldno);
@@ -1264,6 +1266,117 @@ public:
};
+
+/*
+ An iterator to enumerate statistics table rows which allows to modify
+ the rows while reading them.
+
+ Used by RENAME TABLE handling to assign new dbname.tablename to statistic
+ rows.
+*/
+class Stat_table_write_iter
+{
+ Stat_table *owner;
+ IO_CACHE io_cache;
+ uchar *rowid_buf;
+ uint rowid_size;
+
+public:
+ Stat_table_write_iter(Stat_table *stat_table_arg)
+ : owner(stat_table_arg), rowid_buf(NULL),
+ rowid_size(owner->stat_file->ref_length)
+ {
+ my_b_clear(&io_cache);
+ }
+
+ /*
+ Initialize the iterator. It will return rows with n_keyparts matching the
+ curernt values.
+
+ @return false - OK
+ true - Error
+ */
+ bool init(uint n_keyparts)
+ {
+ if (!(rowid_buf= (uchar*)my_malloc(rowid_size, MYF(0))))
+ return true;
+
+ if (open_cached_file(&io_cache, mysql_tmpdir, TEMP_PREFIX,
+ 1024, MYF(MY_WME)))
+ return true;
+
+ handler *h= owner->stat_file;
+ uchar key[MAX_KEY_LENGTH];
+ uint prefix_len= 0;
+ for (uint i= 0; i < n_keyparts; i++)
+ prefix_len += owner->stat_key_info->key_part[i].store_length;
+
+ key_copy(key, owner->record[0], owner->stat_key_info,
+ prefix_len);
+ key_part_map prefix_map= (key_part_map) ((1 << n_keyparts) - 1);
+ h->ha_index_init(owner->stat_key_idx, false);
+ int res= h->ha_index_read_map(owner->record[0], key, prefix_map,
+ HA_READ_KEY_EXACT);
+ if (res)
+ {
+ reinit_io_cache(&io_cache, READ_CACHE, 0L, 0, 0);
+ /* "Key not found" is not considered an error */
+ return (res == HA_ERR_KEY_NOT_FOUND)? false: true;
+ }
+
+ do {
+ h->position(owner->record[0]);
+ my_b_write(&io_cache, h->ref, rowid_size);
+
+ } while (!h->ha_index_next_same(owner->record[0], key, prefix_len));
+
+ /* Prepare for reading */
+ reinit_io_cache(&io_cache, READ_CACHE, 0L, 0, 0);
+ h->ha_index_or_rnd_end();
+ if (h->ha_rnd_init(false))
+ return true;
+
+ return false;
+ }
+
+ /*
+ Read the next row.
+
+ @return
+ false OK
+ true No more rows or error.
+ */
+ bool get_next_row()
+ {
+ if (!my_b_inited(&io_cache) || my_b_read(&io_cache, rowid_buf, rowid_size))
+ return true; /* No more data */
+
+ handler *h= owner->stat_file;
+ /*
+ We should normally be able to find the row that we have rowid for. If we
+ don't, let's consider this an error.
+ */
+ int res= h->ha_rnd_pos(owner->record[0], rowid_buf);
+
+ return (res==0)? false : true;
+ }
+
+ void cleanup()
+ {
+ if (rowid_buf)
+ my_free(rowid_buf);
+ rowid_buf= NULL;
+ owner->stat_file->ha_index_or_rnd_end();
+ close_cached_file(&io_cache);
+ my_b_clear(&io_cache);
+ }
+
+ ~Stat_table_write_iter()
+ {
+ cleanup();
+ }
+};
+
/*
Histogram_builder is a helper class that is used to build histograms
for columns
@@ -3285,25 +3398,34 @@ int rename_table_in_stat_tables(THD *thd, LEX_STRING *db, LEX_STRING *tab,
stat_table= tables[INDEX_STAT].table;
Index_stat index_stat(stat_table, db, tab);
index_stat.set_full_table_name();
- while (index_stat.find_next_stat_for_prefix(2))
+
+ Stat_table_write_iter index_iter(&index_stat);
+ if (index_iter.init(2))
+ rc= 1;
+ while (!index_iter.get_next_row())
{
err= index_stat.update_table_name_key_parts(new_db, new_tab);
if (err & !rc)
rc= 1;
index_stat.set_full_table_name();
}
+ index_iter.cleanup();
/* Rename table in the statistical table column_stats */
stat_table= tables[COLUMN_STAT].table;
Column_stat column_stat(stat_table, db, tab);
column_stat.set_full_table_name();
- while (column_stat.find_next_stat_for_prefix(2))
+ Stat_table_write_iter column_iter(&column_stat);
+ if (column_iter.init(2))
+ rc= 1;
+ while (!column_iter.get_next_row())
{
err= column_stat.update_table_name_key_parts(new_db, new_tab);
if (err & !rc)
rc= 1;
column_stat.set_full_table_name();
}
+ column_iter.cleanup();
/* Rename table in the statistical table table_stats */
stat_table= tables[TABLE_STAT].table;