Commit 4102605f authored by Sergey Petrunia's avatar Sergey Petrunia

MWL#17: Table elimination

- Moved table elimination code to sql/opt_table_elimination.cc
- Added comments 

.bzrignore:
  MWL#17: Table elimination
  - Moved table elimination code to sql/opt_table_elimination.cc
libmysqld/Makefile.am:
  MWL#17: Table elimination
  - Moved table elimination code to sql/opt_table_elimination.cc
sql/CMakeLists.txt:
  MWL#17: Table elimination
  - Moved table elimination code to sql/opt_table_elimination.cc
sql/Makefile.am:
  MWL#17: Table elimination
  - Moved table elimination code to sql/opt_table_elimination.cc
parent defbdce7
...@@ -1905,3 +1905,4 @@ sql/share/swedish ...@@ -1905,3 +1905,4 @@ sql/share/swedish
sql/share/ukrainian sql/share/ukrainian
libmysqld/examples/mysqltest.cc libmysqld/examples/mysqltest.cc
extra/libevent/event-config.h extra/libevent/event-config.h
libmysqld/opt_table_elimination.cc
...@@ -76,7 +76,7 @@ sqlsources = derror.cc field.cc field_conv.cc strfunc.cc filesort.cc \ ...@@ -76,7 +76,7 @@ sqlsources = derror.cc field.cc field_conv.cc strfunc.cc filesort.cc \
rpl_filter.cc sql_partition.cc sql_builtin.cc sql_plugin.cc \ rpl_filter.cc sql_partition.cc sql_builtin.cc sql_plugin.cc \
sql_tablespace.cc \ sql_tablespace.cc \
rpl_injector.cc my_user.c partition_info.cc \ rpl_injector.cc my_user.c partition_info.cc \
sql_servers.cc event_parse_data.cc sql_servers.cc event_parse_data.cc opt_table_elimination.cc
libmysqld_int_a_SOURCES= $(libmysqld_sources) libmysqld_int_a_SOURCES= $(libmysqld_sources)
nodist_libmysqld_int_a_SOURCES= $(libmysqlsources) $(sqlsources) nodist_libmysqld_int_a_SOURCES= $(libmysqlsources) $(sqlsources)
......
...@@ -73,7 +73,7 @@ ADD_EXECUTABLE(mysqld ...@@ -73,7 +73,7 @@ ADD_EXECUTABLE(mysqld
partition_info.cc rpl_utility.cc rpl_injector.cc sql_locale.cc partition_info.cc rpl_utility.cc rpl_injector.cc sql_locale.cc
rpl_rli.cc rpl_mi.cc sql_servers.cc rpl_rli.cc rpl_mi.cc sql_servers.cc
sql_connect.cc scheduler.cc sql_connect.cc scheduler.cc
sql_profile.cc event_parse_data.cc sql_profile.cc event_parse_data.cc opt_table_elimination.cc
${PROJECT_SOURCE_DIR}/sql/sql_yacc.cc ${PROJECT_SOURCE_DIR}/sql/sql_yacc.cc
${PROJECT_SOURCE_DIR}/sql/sql_yacc.h ${PROJECT_SOURCE_DIR}/sql/sql_yacc.h
${PROJECT_SOURCE_DIR}/include/mysqld_error.h ${PROJECT_SOURCE_DIR}/include/mysqld_error.h
......
...@@ -121,7 +121,8 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \ ...@@ -121,7 +121,8 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \
event_queue.cc event_db_repository.cc events.cc \ event_queue.cc event_db_repository.cc events.cc \
sql_plugin.cc sql_binlog.cc \ sql_plugin.cc sql_binlog.cc \
sql_builtin.cc sql_tablespace.cc partition_info.cc \ sql_builtin.cc sql_tablespace.cc partition_info.cc \
sql_servers.cc event_parse_data.cc sql_servers.cc event_parse_data.cc \
opt_table_elimination.cc
nodist_mysqld_SOURCES = mini_client_errors.c pack.c client.c my_time.c my_user.c nodist_mysqld_SOURCES = mini_client_errors.c pack.c client.c my_time.c my_user.c
......
...@@ -1915,17 +1915,22 @@ void Item_field::reset_field(Field *f) ...@@ -1915,17 +1915,22 @@ void Item_field::reset_field(Field *f)
name= (char*) f->field_name; name= (char*) f->field_name;
} }
bool Item_field::check_column_usage_processor(uchar *arg) bool Item_field::check_column_usage_processor(uchar *arg)
{ {
Field_processor_info* info=(Field_processor_info*)arg; Field_processor_info* info=(Field_processor_info*)arg;
/* It is ok if this is a column of an allowed table: */
if (used_tables() & ~info->allowed_tables) if (used_tables() & ~info->allowed_tables)
return FALSE; return FALSE;
if (field->table == info->table) if (field->table == info->table)
{ {
/* It is not ok to use columns that are not part of the key of interest: */
if (!(field->part_of_key.is_set(info->keyno))) if (!(field->part_of_key.is_set(info->keyno)))
return TRUE; return TRUE;
/* Find which key part we're using and mark it in needed_key_parts */
KEY *key= &field->table->key_info[info->keyno]; KEY *key= &field->table->key_info[info->keyno];
for (uint part= 0; part < key->key_parts; part++) for (uint part= 0; part < key->key_parts; part++)
{ {
...@@ -1935,10 +1940,17 @@ bool Item_field::check_column_usage_processor(uchar *arg) ...@@ -1935,10 +1940,17 @@ bool Item_field::check_column_usage_processor(uchar *arg)
break; break;
} }
} }
return FALSE;
} }
return FALSE;
/*
We get here when this refers to a table that's neither the table of
interest, nor one of the allowed tables.
*/
return TRUE;
} }
const char *Item_ident::full_name() const const char *Item_ident::full_name() const
{ {
char *tmp; char *tmp;
......
...@@ -731,7 +731,11 @@ public: ...@@ -731,7 +731,11 @@ public:
virtual bool val_bool_result() { return val_bool(); } virtual bool val_bool_result() { return val_bool(); }
virtual bool is_null_result() { return is_null(); } virtual bool is_null_result() { return is_null(); }
/* bit map of tables used by item */ /*
Bitmap of tables used by item
(note: if you need to check dependencies on individual columns, check out
check_column_usage_processor)
*/
virtual table_map used_tables() const { return (table_map) 0L; } virtual table_map used_tables() const { return (table_map) 0L; }
/* /*
Return table map of tables that can't be NULL tables (tables that are Return table map of tables that can't be NULL tables (tables that are
...@@ -1013,7 +1017,7 @@ public: ...@@ -1013,7 +1017,7 @@ public:
bool eq_by_collation(Item *item, bool binary_cmp, CHARSET_INFO *cs); bool eq_by_collation(Item *item, bool binary_cmp, CHARSET_INFO *cs);
}; };
/* Data for Item::check_column_usage_processor */
typedef struct typedef struct
{ {
table_map allowed_tables; table_map allowed_tables;
...@@ -1022,6 +1026,7 @@ typedef struct ...@@ -1022,6 +1026,7 @@ typedef struct
uint needed_key_parts; uint needed_key_parts;
} Field_processor_info; } Field_processor_info;
class sp_head; class sp_head;
......
...@@ -250,7 +250,7 @@ bool Item_subselect::walk(Item_processor processor, bool walk_subquery, ...@@ -250,7 +250,7 @@ bool Item_subselect::walk(Item_processor processor, bool walk_subquery,
if (lex->having && (lex->having)->walk(processor, walk_subquery, if (lex->having && (lex->having)->walk(processor, walk_subquery,
argument)) argument))
return 1; return 1;
/* TODO: why doesn't this walk the OUTER JOINs' ON expressions */ /* TODO: why does this walk WHERE/HAVING but not ON expressions of outer joins? */
while ((item=li++)) while ((item=li++))
{ {
......
...@@ -351,9 +351,10 @@ public: ...@@ -351,9 +351,10 @@ public:
Return bitmap of tables that are needed to evaluate the item. Return bitmap of tables that are needed to evaluate the item.
The implementation takes into account the used strategy: items resolved The implementation takes into account the used strategy: items resolved
at optimization phase report 0. at optimization phase will report 0.
Items that depend on the number of rows only, e.g. COUNT(*) will report Items that depend on the number of join output records, but not columns
zero, but will still false from const_item(). of any particular table (like COUNT(*)) will report 0 from used_tables(),
but will still return false from const_item().
*/ */
table_map used_tables() const { return used_tables_cache; } table_map used_tables() const { return used_tables_cache; }
void update_used_tables (); void update_used_tables ();
......
This diff is collapsed.
This diff is collapsed.
...@@ -28,6 +28,11 @@ ...@@ -28,6 +28,11 @@
#include "procedure.h" #include "procedure.h"
#include <myisam.h> #include <myisam.h>
#define FT_KEYPART (MAX_REF_PARTS+10)
/* Values in optimize */
#define KEY_OPTIMIZE_EXISTS 1
#define KEY_OPTIMIZE_REF_OR_NULL 2
typedef struct keyuse_t { typedef struct keyuse_t {
TABLE *table; TABLE *table;
Item *val; /**< or value if no field */ Item *val; /**< or value if no field */
...@@ -51,6 +56,14 @@ typedef struct keyuse_t { ...@@ -51,6 +56,14 @@ typedef struct keyuse_t {
NULL - Otherwise (the source equality can't be turned off) NULL - Otherwise (the source equality can't be turned off)
*/ */
bool *cond_guard; bool *cond_guard;
/*
TRUE <=> This keyuse can be used to construct key access.
FALSE <=> Otherwise. Currently unusable KEYUSEs represent equalities
where one table column refers to another one, like this:
t.keyXpartA=func(t.keyXpartB)
This equality cannot be used for index access but is useful
for table elimination.
*/
bool usable; bool usable;
} KEYUSE; } KEYUSE;
...@@ -734,9 +747,13 @@ bool error_if_full_join(JOIN *join); ...@@ -734,9 +747,13 @@ bool error_if_full_join(JOIN *join);
int report_error(TABLE *table, int error); int report_error(TABLE *table, int error);
int safe_index_read(JOIN_TAB *tab); int safe_index_read(JOIN_TAB *tab);
COND *remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value); COND *remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value);
void set_position(JOIN *join,uint idx,JOIN_TAB *table,KEYUSE *key);
inline bool optimizer_flag(THD *thd, uint flag) inline bool optimizer_flag(THD *thd, uint flag)
{ {
return (thd->variables.optimizer_switch & flag); return (thd->variables.optimizer_switch & flag);
} }
void eliminate_tables(JOIN *join, uint *const_tbl_count,
table_map *const_tables);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment