summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <bell@sanja.is.com.ua>2003-10-23 21:09:40 +0300
committerunknown <bell@sanja.is.com.ua>2003-10-23 21:09:40 +0300
commite94666f8e79c01b6ed3d7b0da482cd0a461e4092 (patch)
tree5492ee0331057192a6ffbf9b6deac98f943df4bf /sql
parent9a4aa99769b29cb4084b3b16d2bfb7067d817d2c (diff)
parentd3d001fd022ca69ba2310dce4c932fcea2b330a8 (diff)
downloadmariadb-git-e94666f8e79c01b6ed3d7b0da482cd0a461e4092.tar.gz
Merge
sql/item.cc: Auto merged mysql-test/r/subselect.result: SCCS merged mysql-test/t/subselect.test: SCCS merged
Diffstat (limited to 'sql')
-rw-r--r--sql/item.cc47
-rw-r--r--sql/item_subselect.cc54
-rw-r--r--sql/item_subselect.h15
3 files changed, 107 insertions, 9 deletions
diff --git a/sql/item.cc b/sql/item.cc
index ea1eaf29373..0462a78376f 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -819,9 +819,11 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
// Prevent using outer fields in subselects, that is not supported now
SELECT_LEX *cursel=(SELECT_LEX *) thd->lex.current_select;
if (cursel->master_unit()->first_select()->linkage != DERIVED_TABLE_TYPE)
- for (SELECT_LEX *sl= cursel->outer_select();
+ {
+ SELECT_LEX_UNIT *prev_unit= cursel->master_unit();
+ for (SELECT_LEX *sl= prev_unit->outer_select();
sl;
- sl= sl->outer_select())
+ sl= (prev_unit= sl->master_unit())->outer_select())
{
table_list= (last= sl)->get_table_list();
if (sl->resolve_mode == SELECT_LEX::INSERT_MODE && table_list)
@@ -829,19 +831,38 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
// it is primary INSERT st_select_lex => skip first table resolving
table_list= table_list->next;
}
+
+ Item_subselect *prev_subselect_item= prev_unit->item;
if ((tmp= find_field_in_tables(thd, this,
table_list, &where,
0)) != not_found_field)
+ {
+ prev_subselect_item->used_tables_cache|= tmp->table->map;
+ prev_subselect_item->const_item_cache= 0;
break;
+ }
if (sl->resolve_mode == SELECT_LEX::SELECT_MODE &&
(refer= find_item_in_list(this, sl->item_list, &counter,
REPORT_EXCEPT_NOT_FOUND)) !=
(Item **) not_found_item)
+ {
+ if (*refer && (*refer)->fixed) // Avoid crash in case of error
+ {
+ prev_subselect_item->used_tables_cache|= (*refer)->used_tables();
+ prev_subselect_item->const_item_cache&= (*refer)->const_item();
+ }
break;
+ }
+
+ // Reference is not found => depend from outer (or just error)
+ prev_subselect_item->used_tables_cache|= OUTER_REF_TABLE_BIT;
+ prev_subselect_item->const_item_cache= 0;
+
if (sl->master_unit()->first_select()->linkage ==
DERIVED_TABLE_TYPE)
break; // do not look over derived table
}
+ }
if (!tmp)
return -1;
else if (!refer)
@@ -1360,7 +1381,8 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
if (!ref)
{
TABLE_LIST *where= 0, *table_list;
- SELECT_LEX *sl= thd->lex.current_select->outer_select();
+ SELECT_LEX_UNIT *prev_unit= thd->lex.current_select->master_unit();
+ SELECT_LEX *sl= prev_unit->outer_select();
/*
Finding only in current select will be performed for selects that have
not outer one and for derived tables (which not support using outer
@@ -1388,15 +1410,23 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
cause error ER_NON_UNIQ_ERROR in find_item_in_list.
*/
SELECT_LEX *last=0;
- for ( ; sl ; sl= sl->outer_select())
+ for ( ; sl ; sl= (prev_unit= sl->master_unit())->outer_select())
{
last= sl;
+ Item_subselect *prev_subselect_item= prev_unit->item;
if (sl->resolve_mode == SELECT_LEX::SELECT_MODE &&
(ref= find_item_in_list(this, sl->item_list,
&counter,
REPORT_EXCEPT_NOT_FOUND)) !=
(Item **)not_found_item)
+ {
+ if (*ref && (*ref)->fixed) // Avoid crash in case of error
+ {
+ prev_subselect_item->used_tables_cache|= (*ref)->used_tables();
+ prev_subselect_item->const_item_cache&= (*ref)->const_item();
+ }
break;
+ }
table_list= sl->get_table_list();
if (sl->resolve_mode == SELECT_LEX::INSERT_MODE && table_list)
{
@@ -1406,7 +1436,16 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
if ((tmp= find_field_in_tables(thd, this,
table_list, &where,
0)) != not_found_field)
+ {
+ prev_subselect_item->used_tables_cache|= tmp->table->map;
+ prev_subselect_item->const_item_cache= 0;
break;
+ }
+
+ // Reference is not found => depend from outer (or just error)
+ prev_subselect_item->used_tables_cache|= OUTER_REF_TABLE_BIT;
+ prev_subselect_item->const_item_cache= 0;
+
if (sl->master_unit()->first_select()->linkage ==
DERIVED_TABLE_TYPE)
break; // do not look over derived table
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 5e0221ad6c7..704681dd511 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -36,7 +36,8 @@ inline Item * and_items(Item* cond, Item *item)
Item_subselect::Item_subselect():
Item_result_field(), engine_owner(1), value_assigned(0), substitution(0),
- engine(0), have_to_be_excluded(0), engine_changed(0)
+ engine(0), used_tables_cache(0), have_to_be_excluded(0),
+ const_item_cache(1), engine_changed(0)
{
reset();
/*
@@ -111,6 +112,11 @@ bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref)
}
fix_length_and_dec();
}
+ if (engine->uncacheable())
+ {
+ const_item_cache= 0;
+ used_tables_cache|= RAND_TABLE_BIT;
+ }
fixed= 1;
thd->where= save_where;
return res;
@@ -146,10 +152,24 @@ void Item_subselect::fix_length_and_dec()
engine->fix_length_and_dec(0);
}
-inline table_map Item_subselect::used_tables() const
+table_map Item_subselect::used_tables() const
+{
+ return (table_map) (engine->dependent() ? used_tables_cache : 0L);
+}
+
+bool Item_subselect::const_item() const
+{
+ return const_item_cache;
+}
+
+void Item_subselect::update_used_tables()
{
- return (table_map) (engine->dependent() ? 1L :
- (engine->uncacheable() ? RAND_TABLE_BIT : 0L));
+ if (!engine->uncacheable())
+ {
+ // did all used tables become ststic?
+ if ((used_tables_cache & ~engine->upper_select_const_tables()))
+ const_item_cache= 1;
+ }
}
Item_singlerow_subselect::Item_singlerow_subselect(st_select_lex *select_lex)
@@ -1138,3 +1158,29 @@ void subselect_uniquesubquery_engine::exclude()
//this never should be called
DBUG_ASSERT(0);
}
+
+
+table_map subselect_engine::calc_const_tables(TABLE_LIST *table)
+{
+ table_map map= 0;
+ for(; table; table= table->next)
+ {
+ TABLE *tbl= table->table;
+ if (tbl && tbl->const_table)
+ map|= tbl->map;
+ }
+ return map;
+}
+
+
+table_map subselect_single_select_engine::upper_select_const_tables()
+{
+ return calc_const_tables((TABLE_LIST *) select_lex->outer_select()->
+ table_list.first);
+}
+
+table_map subselect_union_engine::upper_select_const_tables()
+{
+ return calc_const_tables((TABLE_LIST *) unit->outer_select()->
+ table_list.first);
+}
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
index 312b453a5a2..3a543ff288c 100644
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@ -41,11 +41,15 @@ protected:
/* substitution instead of subselect in case of optimization */
Item *substitution;
/* engine that perform execution of subselect (single select or union) */
- subselect_engine *engine;
+ subselect_engine *engine;
+ /* cache of used external tables */
+ table_map used_tables_cache;
/* allowed number of columns (1 for single value subqueries) */
uint max_columns;
/* work with 'substitution' */
bool have_to_be_excluded;
+ /* cache of constante state */
+ bool const_item_cache;
public:
/* changed engine indicator */
@@ -85,6 +89,8 @@ public:
bool exec();
virtual void fix_length_and_dec();
table_map used_tables() const;
+ bool const_item() const;
+ void update_used_tables();
void print(String *str)
{
if (name)
@@ -101,6 +107,8 @@ public:
friend class select_subselect;
friend class Item_in_optimizer;
+ friend bool Item_field::fix_fields(THD *, TABLE_LIST *, Item **);
+ friend bool Item_ref::fix_fields(THD *, TABLE_LIST *, Item **);
};
/* single value subselect */
@@ -264,6 +272,8 @@ public:
enum Item_result type() { return res_type; }
virtual void exclude()= 0;
bool may_be_null() { return maybe_null; };
+ virtual table_map upper_select_const_tables()= 0;
+ static table_map calc_const_tables(TABLE_LIST *);
};
@@ -285,6 +295,7 @@ public:
bool dependent();
bool uncacheable();
void exclude();
+ table_map upper_select_const_tables();
};
@@ -302,6 +313,7 @@ public:
bool dependent();
bool uncacheable();
void exclude();
+ table_map upper_select_const_tables();
};
@@ -328,6 +340,7 @@ public:
bool dependent() { return 1; }
bool uncacheable() { return 1; }
void exclude();
+ table_map upper_select_const_tables() { return 0; }
};