summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <igor@rurik.mysql.com>2006-06-02 14:14:57 -0700
committerunknown <igor@rurik.mysql.com>2006-06-02 14:14:57 -0700
commite3e0658779bffacd5323efb54ecb7f42ded19231 (patch)
tree73c42f8475188528c843bc2d2a7f64fa2f122d1e /sql
parenta9824f263dcaedaabfbbc9e398eb55117f19a41f (diff)
downloadmariadb-git-e3e0658779bffacd5323efb54ecb7f42ded19231.tar.gz
Fixed bug #18206.
The bug report revealed two problems related to min/max optimization: 1. If the length of a constant key used in a SARGable condition for for the MIN/MAX fields is greater than the length of the field an unwanted warning on key truncation is issued; 2. If MIN/MAX optimization is applied to a partial index, like INDEX(b(4)) than can lead to returning a wrong result set. mysql-test/r/func_group.result: Added test cases for bug #18206. mysql-test/t/func_group.test: Added test cases for bug #18206. sql/opt_sum.cc: Fixed bug #18206. Suppressed the warning about data truncation when store_val_in_field was used to store keys for the field used in MIN/MAX optimization. Blocked MIN/MAX optimization for partial keys, such as in INDEX(b(4)). sql/sql_select.cc: Fixed bug #18206. Added a parameter for the function store_val_in_field allowing to control setting warnings about data truncation in the function. sql/sql_select.h: Fixed bug #18206. Added a parameter for the function store_val_in_field allowing to control setting warnings about data truncation in the function.
Diffstat (limited to 'sql')
-rw-r--r--sql/opt_sum.cc17
-rw-r--r--sql/sql_select.cc6
-rw-r--r--sql/sql_select.h2
3 files changed, 18 insertions, 7 deletions
diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc
index cfb5b3695a3..82211120c57 100644
--- a/sql/opt_sum.cc
+++ b/sql/opt_sum.cc
@@ -543,6 +543,10 @@ static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo,
break; // Found a part od the key for the field
}
+#if 0
+ if (part->length != (((Item_field*) args[0])->field)->field_length)
+ return 0;
+#endif
bool is_field_part= part == field_part;
if (!(is_field_part || eq_type))
return 0;
@@ -582,7 +586,8 @@ static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo,
}
else
{
- store_val_in_field(part->field, args[between && max_fl ? 2 : 1]);
+ store_val_in_field(part->field, args[between && max_fl ? 2 : 1],
+ CHECK_FIELD_IGNORE);
if (part->null_bit)
*key_ptr++= (byte) test(part->field->is_null());
part->field->get_key_image((char*) key_ptr, part->length,
@@ -638,6 +643,8 @@ static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo,
field BETWEEN const1 AND const2
3. all references to the columns from the same table as column field
occur only in conjucts mentioned above.
+ 4. each of k first components the index is not partial, i.e. is not
+ defined on a fixed length proper prefix of the field.
If such an index exists the function through the ref parameter
returns the key value to find max/min for the field using the index,
@@ -647,8 +654,8 @@ static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo,
of the whole search key)
NOTE
- This function may set table->key_read to 1, which must be reset after
- index is used! (This can only happen when function returns 1)
+ This function may set table->key_read to 1, which must be reset after
+ index is used! (This can only happen when function returns 1)
RETURN
0 Index can not be used to optimize MIN(field)/MAX(field)
@@ -682,6 +689,10 @@ static bool find_key_for_maxmin(bool max_fl, TABLE_REF *ref,
if (!(table->file->index_flags(idx, jdx, 0) & HA_READ_ORDER))
return 0;
+ /* Check whether the index component is partial */
+ if (part->length < table->field[part->fieldnr-1]->pack_length())
+ break;
+
if (field->eq(part->field))
{
ref->key= idx;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 57fb9738612..5a7e9e52aed 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -3434,7 +3434,7 @@ get_store_key(THD *thd, KEYUSE *keyuse, table_map used_tables,
*/
bool
-store_val_in_field(Field *field,Item *item)
+store_val_in_field(Field *field, Item *item, enum_check_fields check_flag)
{
bool error;
THD *thd=current_thd;
@@ -3445,7 +3445,7 @@ store_val_in_field(Field *field,Item *item)
with select_insert, which make count_cuted_fields= 1
*/
enum_check_fields old_count_cuted_fields= thd->count_cuted_fields;
- thd->count_cuted_fields= CHECK_FIELD_WARN;
+ thd->count_cuted_fields= check_flag;
error= item->save_in_field(field, 1);
thd->count_cuted_fields= old_count_cuted_fields;
return error || cuted_fields != thd->cuted_fields;
@@ -7097,7 +7097,7 @@ static bool test_if_ref(Item_field *left_item,Item *right_item)
field->real_type() != FIELD_TYPE_VAR_STRING &&
(field->type() != FIELD_TYPE_FLOAT || field->decimals() == 0))
{
- return !store_val_in_field(field,right_item);
+ return !store_val_in_field(field, right_item, CHECK_FIELD_WARN);
}
}
}
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 94cc8839466..75cd0b4d797 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -335,7 +335,7 @@ extern const char *join_type_str[];
void TEST_join(JOIN *join);
/* Extern functions in sql_select.cc */
-bool store_val_in_field(Field *field,Item *val);
+bool store_val_in_field(Field *field, Item *val, enum_check_fields check_flag);
TABLE *create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
ORDER *group, bool distinct, bool save_sum_fields,
ulong select_options, ha_rows rows_limit,