summaryrefslogtreecommitdiff
path: root/sql/sql_select.cc
diff options
context:
space:
mode:
authorunknown <monty@mashka.mysql.fi>2003-09-11 20:31:40 +0300
committerunknown <monty@mashka.mysql.fi>2003-09-11 20:31:40 +0300
commit41824a35338012ff8196eb975f961d5e0f0e2a22 (patch)
tree1475a169c541e6b7aedb36103dd255fe52fc0517 /sql/sql_select.cc
parent07bc35e1d024e5e3b81b131a47878510f0521609 (diff)
parentd32bdcb1bfc274476cdd945e66e00f3ec31253c3 (diff)
downloadmariadb-git-41824a35338012ff8196eb975f961d5e0f0e2a22.tar.gz
merge with 4.1 tree
client/mysqltest.c: Auto merged include/mysql.h: Auto merged libmysql/errmsg.c: Auto merged libmysql/libmysql.c: Auto merged mysql-test/mysql-test-run.sh: Auto merged sql/field.cc: Auto merged sql/item.cc: Auto merged sql/item.h: Auto merged sql/item_cmpfunc.cc: Auto merged sql/item_func.cc: Auto merged sql/item_func.h: Auto merged sql/mysql_priv.h: Auto merged sql/mysqld.cc: Auto merged sql/share/portuguese/errmsg.txt: Auto merged sql/share/spanish/errmsg.txt: Auto merged sql/sql_select.cc: Auto merged sql/sql_table.cc: Auto merged sql/sql_yacc.yy: Auto merged tests/client_test.c: Auto merged
Diffstat (limited to 'sql/sql_select.cc')
-rw-r--r--sql/sql_select.cc100
1 files changed, 67 insertions, 33 deletions
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 12d39bfacb0..ccc6e10dee8 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -158,7 +158,7 @@ static void copy_sum_funcs(Item_sum **func_ptr);
static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab);
static bool init_sum_functions(Item_sum **func, Item_sum **end);
static bool update_sum_func(Item_sum **func);
-static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
+static void select_describe(JOIN *join, bool need_tmp_table,bool need_order,
bool distinct, const char *message=NullS);
static Item *remove_additional_cond(Item* conds);
@@ -2055,28 +2055,34 @@ merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end,
static void
add_key_field(KEY_FIELD **key_fields,uint and_level,
- Field *field,bool eq_func,Item *value,
+ Field *field,bool eq_func,Item **value, uint num_values,
table_map usable_tables)
{
uint exists_optimize= 0;
if (!(field->flags & PART_KEY_FLAG))
{
// Don't remove column IS NULL on a LEFT JOIN table
- if (!eq_func || !value || value->type() != Item::NULL_ITEM ||
- !field->table->maybe_null || field->null_ptr)
+ if (!eq_func || (*value)->type() != Item::NULL_ITEM ||
+ !field->table->maybe_null || field->null_ptr)
return; // Not a key. Skip it
exists_optimize= KEY_OPTIMIZE_EXISTS;
}
else
{
table_map used_tables=0;
- if (value && ((used_tables=value->used_tables()) &
- (field->table->map | RAND_TABLE_BIT)))
+ bool optimizable=0;
+ for (uint i=0; i<num_values; i++)
+ {
+ used_tables|=(*value)->used_tables();
+ if (!((*value)->used_tables() & (field->table->map | RAND_TABLE_BIT)))
+ optimizable=1;
+ }
+ if (!optimizable)
return;
if (!(usable_tables & field->table->map))
{
- if (!eq_func || !value || value->type() != Item::NULL_ITEM ||
- !field->table->maybe_null || field->null_ptr)
+ if (!eq_func || (*value)->type() != Item::NULL_ITEM ||
+ !field->table->maybe_null || field->null_ptr)
return; // Can't use left join optimize
exists_optimize= KEY_OPTIMIZE_EXISTS;
}
@@ -2087,12 +2093,6 @@ add_key_field(KEY_FIELD **key_fields,uint and_level,
field->table->keys_in_use_for_query);
stat[0].keys|= possible_keys; // Add possible keys
- if (!value)
- { // Probably BETWEEN or IN
- stat[0].const_keys |= possible_keys;
- return; // Can't be used as eq key
- }
-
/*
Save the following cases:
Field op constant
@@ -2101,26 +2101,38 @@ add_key_field(KEY_FIELD **key_fields,uint and_level,
Field op formula
Field IS NULL
Field IS NOT NULL
+ Field BETWEEN ...
+ Field IN ...
*/
stat[0].key_dependent|=used_tables;
- if (value->const_item())
- stat[0].const_keys |= possible_keys;
+ bool is_const=1;
+ for (uint i=0; i<num_values; i++)
+ is_const&= (*value)->const_item();
+ if (is_const)
+ stat[0].const_keys |= possible_keys;
/*
We can't always use indexes when comparing a string index to a
- number. cmp_type() is checked to allow compare of dates to numbers
- */
+ number. cmp_type() is checked to allow compare of dates to numbers.
+ eq_func is NEVER true when num_values > 1
+ */
if (!eq_func ||
field->result_type() == STRING_RESULT &&
- value->result_type() != STRING_RESULT &&
- field->cmp_type() != value->result_type())
+ (*value)->result_type() != STRING_RESULT &&
+ field->cmp_type() != (*value)->result_type())
return;
}
}
+ DBUG_ASSERT(num_values == 1);
+ /*
+ For the moment eq_func is always true. This slot is reserved for future
+ extensions where we want to remembers other things than just eq comparisons
+ */
+ DBUG_ASSERT(eq_func);
/* Store possible eq field */
(*key_fields)->field= field;
(*key_fields)->eq_func= eq_func;
- (*key_fields)->val= value;
+ (*key_fields)->val= *value;
(*key_fields)->level= and_level;
(*key_fields)->optimize= exists_optimize;
(*key_fields)++;
@@ -2169,12 +2181,14 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
case Item_func::OPTIMIZE_NONE:
break;
case Item_func::OPTIMIZE_KEY:
+ // BETWEEN or IN
if (cond_func->key_item()->real_item()->type() == Item::FIELD_ITEM &&
!(cond_func->used_tables() & OUTER_REF_TABLE_BIT))
add_key_field(key_fields,*and_level,
- ((Item_field*) (cond_func->key_item()->real_item()))
- ->field,
- 0,(Item*) 0,usable_tables);
+ ((Item_field*) (cond_func->key_item()->real_item()))->field, 0,
+ cond_func->arguments()+1, cond_func->argument_count()-1,
+#endif
+ usable_tables);
break;
case Item_func::OPTIMIZE_OP:
{
@@ -2188,7 +2202,7 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
((Item_field*) (cond_func->arguments()[0])->real_item())
->field,
equal_func,
- (cond_func->arguments()[1]),usable_tables);
+ cond_func->arguments()+1, 1, usable_tables);
}
if (cond_func->arguments()[1]->real_item()->type() == Item::FIELD_ITEM &&
cond_func->functype() != Item_func::LIKE_FUNC &&
@@ -2198,7 +2212,7 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
((Item_field*) (cond_func->arguments()[1])->real_item())
->field,
equal_func,
- (cond_func->arguments()[0]),usable_tables);
+ cond_func->arguments(),1,usable_tables);
}
break;
}
@@ -2207,11 +2221,14 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
if (cond_func->arguments()[0]->real_item()->type() == Item::FIELD_ITEM &&
!(cond_func->used_tables() & OUTER_REF_TABLE_BIT))
{
+ Item *tmp=new Item_null;
+ if (!tmp) // Should never be true
+ return;
add_key_field(key_fields,*and_level,
((Item_field*) (cond_func->arguments()[0])->real_item())
->field,
cond_func->functype() == Item_func::ISNULL_FUNC,
- new Item_null, usable_tables);
+ &tmp, 1, usable_tables);
}
break;
}
@@ -3330,13 +3347,30 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
join->best_positions[i].records_read &&
!(join->select_options & OPTION_FOUND_ROWS)))
{
+ /* Join with outer join condition */
+ COND *orig_cond=sel->cond;
+ sel->cond=and_conds(sel->cond,tab->on_expr);
if (sel->test_quick_select(tab->keys,
used_tables & ~ current_map,
(join->select_options &
OPTION_FOUND_ROWS ?
HA_POS_ERROR :
join->unit->select_limit_cnt)) < 0)
- DBUG_RETURN(1); // Impossible range
+ { /* before reporting "Impossible WHERE" for the whole query
+ we have to check isn't it only "impossible ON" instead */
+ sel->cond=orig_cond;
+ if (!tab->on_expr ||
+ sel->test_quick_select(tab->keys,
+ used_tables & ~ current_map,
+ (join->select_options &
+ OPTION_FOUND_ROWS ?
+ HA_POS_ERROR :
+ join->thd->select_limit)) < 0)
+ DBUG_RETURN(1); // Impossible WHERE
+ }
+ else
+ sel->cond=orig_cond;
+
/* Fix for EXPLAIN */
if (sel->quick)
join->best_positions[i].records_read= sel->quick->records;
@@ -4034,7 +4068,7 @@ static Item *remove_additional_cond(Item* conds)
}
static void
-propagate_cond_constants(I_List<COND_CMP> *save_list,COND *and_level,
+propagate_cond_constants(I_List<COND_CMP> *save_list,COND *and_father,
COND *cond)
{
if (cond->type() == Item::COND_ITEM)
@@ -4060,7 +4094,7 @@ propagate_cond_constants(I_List<COND_CMP> *save_list,COND *and_level,
cond_cmp->cmp_func->arguments()[1]);
}
}
- else if (and_level != cond && !cond->marker) // In a AND group
+ else if (and_father != cond && !cond->marker) // In a AND group
{
if (cond->type() == Item::FUNC_ITEM &&
(((Item_func*) cond)->functype() == Item_func::EQ_FUNC ||
@@ -4078,7 +4112,7 @@ propagate_cond_constants(I_List<COND_CMP> *save_list,COND *and_level,
func->arguments()[1]=resolve_const_item(func->arguments()[1],
func->arguments()[0]);
func->update_used_tables();
- change_cond_ref_to_const(save_list,and_level,and_level,
+ change_cond_ref_to_const(save_list,and_father,and_father,
func->arguments()[0],
func->arguments()[1]);
}
@@ -4087,7 +4121,7 @@ propagate_cond_constants(I_List<COND_CMP> *save_list,COND *and_level,
func->arguments()[0]=resolve_const_item(func->arguments()[0],
func->arguments()[1]);
func->update_used_tables();
- change_cond_ref_to_const(save_list,and_level,and_level,
+ change_cond_ref_to_const(save_list,and_father,and_father,
func->arguments()[1],
func->arguments()[0]);
}
@@ -8248,7 +8282,7 @@ update_tmptable_sum_func(Item_sum **func_ptr,
{
Item_sum *func;
while ((func= *(func_ptr++)))
- func->update_field(0);
+ func->update_field();
}