diff options
author | Igor Babaev <igor@askmonty.org> | 2012-05-22 20:55:07 -0700 |
---|---|---|
committer | Igor Babaev <igor@askmonty.org> | 2012-05-22 20:55:07 -0700 |
commit | 055477ae522b805d3b2e890af9fe520cc1e3290d (patch) | |
tree | 6f45830161e7fa5f2a690046fc6f118f9331b3b2 /sql | |
parent | 2a1afc29f252fb189f6e93a2e0d3a1939f8220d5 (diff) | |
download | mariadb-git-055477ae522b805d3b2e890af9fe520cc1e3290d.tar.gz |
Support of the extended syntax for ANALYZE.
Diffstat (limited to 'sql')
-rw-r--r-- | sql/sql_admin.cc | 68 | ||||
-rw-r--r-- | sql/sql_lex.cc | 2 | ||||
-rw-r--r-- | sql/sql_lex.h | 2 | ||||
-rw-r--r-- | sql/sql_statistics.cc | 27 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 89 |
5 files changed, 172 insertions, 16 deletions
diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index c2d06a149e8..4e2581b885c 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -27,6 +27,7 @@ #include "sql_acl.h" // *_ACL #include "sp.h" // Sroutine_hash_entry #include "sql_parse.h" // check_table_access +#include "strfunc.h" #include "sql_admin.h" /* Prepare, run and cleanup for mysql_recreate_table() */ @@ -628,16 +629,75 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, } } - result_code= compl_result_code= 0; - if (operator_func != &handler::ha_analyze || - thd->variables.optimizer_use_stat_tables < 3) + result_code= compl_result_code= HA_ADMIN_OK; + + if (operator_func == &handler::ha_analyze) + { + TABLE *tab= table->table; + Field **field_ptr= tab->field; + + if (!lex->column_list) + { + uint fields= 0; + for ( ; *field_ptr; field_ptr++, fields++) ; + bitmap_set_prefix(tab->read_set, fields); + } + else + { + int pos; + LEX_STRING *column_name; + List_iterator_fast<LEX_STRING> it(*lex->column_list); + + bitmap_clear_all(tab->read_set); + while ((column_name= it++)) + { + if (tab->s->fieldnames.type_names == 0 || + (pos= find_type(&tab->s->fieldnames, column_name->str, + column_name->length, 1)) <= 0) + { + compl_result_code= result_code= HA_ADMIN_INVALID; + break; + } + bitmap_set_bit(tab->read_set, --pos); + } + } + + if (!lex->index_list) + { + tab->keys_in_use_for_query.init(tab->s->keys); + } + else + { + int pos; + LEX_STRING *index_name; + List_iterator_fast<LEX_STRING> it(*lex->index_list); + + tab->keys_in_use_for_query.clear_all(); + while ((index_name= it++)) + { + if (tab->s->keynames.type_names == 0 || + (pos= find_type(&tab->s->keynames, index_name->str, + index_name->length, 1)) <= 0) + { + compl_result_code= result_code= HA_ADMIN_INVALID; + break; + } + tab->keys_in_use_for_query.set_bit(--pos); + } + } + } + + if (result_code == HA_ADMIN_OK && + (operator_func != &handler::ha_analyze || + thd->variables.optimizer_use_stat_tables < 3)) { DBUG_PRINT("admin", ("calling operator_func '%s'", operator_name)); result_code = (table->table->file->*operator_func)(thd, check_opt); DBUG_PRINT("admin", ("operator_func returned: %d", result_code)); } - if (operator_func == &handler::ha_analyze && opt_with_stat_tables && + if (compl_result_code == HA_ADMIN_OK && + operator_func == &handler::ha_analyze && opt_with_stat_tables && thd->variables.optimizer_use_stat_tables > 0) { if (!(compl_result_code= diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 246f03a7754..bff3ebb3450 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -456,6 +456,8 @@ void lex_start(THD *thd) lex->set_var_list.empty(); lex->param_list.empty(); lex->view_list.empty(); + lex->column_list= NULL; + lex->index_list= NULL; lex->prepared_stmt_params.empty(); lex->auxiliary_table_list.empty(); lex->unit.next= lex->unit.master= diff --git a/sql/sql_lex.h b/sql/sql_lex.h index f1ee6cf22ec..70c97613f55 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -2383,6 +2383,8 @@ struct LEX: public Query_tables_list List<Item_func_set_user_var> set_var_list; // in-query assignment list List<Item_param> param_list; List<LEX_STRING> view_list; // view list (list of field names in view) + List<LEX_STRING> *column_list; // list of column names (in ANALYZE) + List<LEX_STRING> *index_list; // list of index names (in ANALYZE) /* A stack of name resolution contexts for the query. This stack is used at parse time to set local name resolution contexts for various parts diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc index 44f25115f00..aeaecf537cb 100644 --- a/sql/sql_statistics.cc +++ b/sql/sql_statistics.cc @@ -1289,6 +1289,8 @@ int collect_statistics_for_table(THD *thd, TABLE *table) { table_field= *field_ptr; uint max_heap_table_size= thd->variables.max_heap_table_size; + if (!bitmap_is_set(table->read_set, table_field->field_index)) + continue; set_nulls_for_write_column_stat_values(table_field); table_field->nulls= 0; table_field->column_total_length= 0; @@ -1306,8 +1308,6 @@ int collect_statistics_for_table(THD *thd, TABLE *table) table_field->count_distinct= NULL; } - bitmap_set_all(table->read_set); - /* Perform a full table scan to collect statistics on 'table's columns */ if (!(rc= file->ha_rnd_init(TRUE))) { @@ -1319,6 +1319,8 @@ int collect_statistics_for_table(THD *thd, TABLE *table) for (field_ptr= table->field; *field_ptr; field_ptr++) { table_field= *field_ptr; + if (!bitmap_is_set(table->read_set, table_field->field_index)) + continue; if (table_field->is_null()) table_field->nulls++; else @@ -1357,6 +1359,8 @@ int collect_statistics_for_table(THD *thd, TABLE *table) for (field_ptr= table->field; *field_ptr; field_ptr++) { table_field= *field_ptr; + if (!bitmap_is_set(table->read_set, table_field->field_index)) + continue; table_field->write_stat.nulls_ratio= (double) table_field->nulls/rows; table_field->write_stat.avg_length= (double) table_field->column_total_length / (rows-table_field->nulls); @@ -1380,12 +1384,13 @@ int collect_statistics_for_table(THD *thd, TABLE *table) if (!rc) { - uint keys= table->s->keys ; - + uint key; + key_map::Iterator it(table->keys_in_use_for_query); + /* Collect statistics for indexes */ - for (uint i= 0; i < keys; i++) + while ((key= it++) != key_map::Iterator::BITMAP_END) { - if ((rc= collect_statistics_for_index(table, i))) + if ((rc= collect_statistics_for_index(table, key))) break; } } @@ -1439,7 +1444,6 @@ int update_statistics_for_table(THD *thd, TABLE *table) int err; int rc= 0; TABLE *stat_table; - uint keys= table->s->keys; DBUG_ENTER("update_statistics_for_table"); @@ -1466,6 +1470,8 @@ int update_statistics_for_table(THD *thd, TABLE *table) for (Field **field_ptr= table->field; *field_ptr; field_ptr++) { Field *table_field= *field_ptr; + if (!bitmap_is_set(table->read_set, table_field->field_index)) + continue; restore_record(stat_table, s->default_values); column_stat.set_key_fields(table_field); err= column_stat.update_stat(); @@ -1475,12 +1481,13 @@ int update_statistics_for_table(THD *thd, TABLE *table) /* Update the statistical table index_stat */ stat_table= tables[INDEX_STAT].table; + uint key; + key_map::Iterator it(table->keys_in_use_for_query); Index_stat index_stat(stat_table, table); - KEY *key_info, *key_info_end; - for (key_info= table->key_info, key_info_end= table->key_info+keys; - key_info < key_info_end; key_info++) + while ((key= it++) != key_map::Iterator::BITMAP_END) { + KEY *key_info= table->key_info+key; uint key_parts= table->actual_n_key_parts(key_info); for (i= 0; i < key_parts; i++) { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 34e015e1f9b..ff72d27647d 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1593,7 +1593,12 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); show describe load alter optimize keycache preload flush reset purge begin commit rollback savepoint release slave master_def master_defs master_file_def slave_until_opts - repair analyze check start checksum + repair analyze + analyze_table_list analyze_table_elem_spec + opt_persistent_stat_clause persistent_stat_spec + persistent_column_stat_spec persistent_index_stat_spec + table_column_list table_index_list + check start checksum field_list field_list_item field_spec kill column_def key_def keycache_list keycache_list_or_parts assign_to_keycache assign_to_keycache_parts @@ -7212,7 +7217,7 @@ analyze: /* Will be overriden during execution. */ YYPS->m_lock_type= TL_UNLOCK; } - table_list + analyze_table_list { THD *thd= YYTHD; LEX* lex= thd->lex; @@ -7223,6 +7228,86 @@ analyze: } ; +analyze_table_list: + analyze_table_elem_spec + | analyze_table_list ',' analyze_table_elem_spec + ; + +analyze_table_elem_spec: + table_name opt_persistent_stat_clause + ; + +opt_persistent_stat_clause: + /* empty */ + {} + | PERSISTENT_SYM FOR_SYM persistent_stat_spec + {} + ; + +persistent_stat_spec: + ALL + {} + | COLUMNS persistent_column_stat_spec INDEXES persistent_index_stat_spec + {} + +persistent_column_stat_spec: + ALL {} + | '(' + { + THD *thd= YYTHD; + LEX* lex= thd->lex; + lex->column_list= new List<LEX_STRING>; + if (lex->column_list == NULL) + MYSQL_YYABORT; + } + table_column_list + ')' + ; + +persistent_index_stat_spec: + ALL {} + | '(' + { + THD *thd= YYTHD; + LEX* lex= thd->lex; + lex->index_list= new List<LEX_STRING>; + if (lex->index_list == NULL) + MYSQL_YYABORT; + } + table_index_list + ')' + ; + +table_column_list: + /* empty */ + {} + | ident + { + Lex->column_list->push_back((LEX_STRING*) + sql_memdup(&$1, sizeof(LEX_STRING))); + } + | table_column_list ',' ident + { + Lex->column_list->push_back((LEX_STRING*) + sql_memdup(&$3, sizeof(LEX_STRING))); + } + ; + +table_index_list: + /* empty */ + {} + | ident + { + Lex->index_list->push_back((LEX_STRING*) + sql_memdup(&$1, sizeof(LEX_STRING))); + } + | table_index_list ',' ident + { + Lex->index_list->push_back((LEX_STRING*) + sql_memdup(&$3, sizeof(LEX_STRING))); + } + ; + binlog_base64_event: BINLOG_SYM TEXT_STRING_sys { |