Below is the list of changes that have just been committed into a local
4.1 repository of bar. When bar does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet@stripped, 2006-08-16 09:31:24+05:00, bar@stripped +3 -0
Merge mysql.com:/usr/home/bar/mysql-4.1
into mysql.com:/usr/home/bar/mysql-4.1.b9509
MERGE: 1.2458.10.1
mysql-test/r/ctype_utf8.result@stripped, 2006-08-16 09:31:19+05:00, bar@stripped +0 -0
Auto merged
MERGE: 1.69.1.5
mysql-test/t/ctype_utf8.test@stripped, 2006-08-16 09:31:19+05:00, bar@stripped +0 -0
Auto merged
MERGE: 1.71.1.5
sql/sql_select.cc@stripped, 2006-08-16 09:31:19+05:00, bar@stripped +0 -0
Auto merged
MERGE: 1.451.1.13
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: bar
# Host: bar.intranet.mysql.r18.ru
# Root: /usr/home/bar/mysql-4.1.b9509/RESYNC
--- 1.452/sql/sql_select.cc 2006-08-16 09:31:29 +05:00
+++ 1.453/sql/sql_select.cc 2006-08-16 09:31:29 +05:00
@@ -114,6 +114,10 @@
static uint find_shortest_key(TABLE *table, const key_map *usable_keys);
static bool test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,
ha_rows select_limit, bool no_changes);
+static bool list_contains_unique_index(TABLE *table,
+ bool (*find_func) (Field *, void *), void *data);
+static bool find_field_in_item_list (Field *field, void *data);
+static bool find_field_in_order_list (Field *field, void *data);
static int create_sort_index(THD *thd, JOIN *join, ORDER *order,
ha_rows filesort_limit, ha_rows select_limit);
static int remove_duplicates(JOIN *join,TABLE *entry,List<Item> &fields,
@@ -171,7 +175,7 @@
register SELECT_LEX *select_lex = &lex->select_lex;
DBUG_ENTER("handle_select");
- if (select_lex->next_select())
+ if (select_lex->next_select() || select_lex->master_unit()->fake_select_lex)
res=mysql_union(thd, lex, result, &lex->unit);
else
res= mysql_select(thd, &select_lex->ref_pointer_array,
@@ -501,12 +505,24 @@
DBUG_RETURN(1);
}
- if (cond_value == Item::COND_FALSE ||
- (!unit->select_limit_cnt && !(select_options & OPTION_FOUND_ROWS)))
- { /* Impossible cond */
- zero_result_cause= "Impossible WHERE";
- error= 0;
- DBUG_RETURN(0);
+ {
+ Item::cond_result having_value;
+ having= optimize_cond(thd, having, &having_value);
+ if (thd->net.report_error)
+ {
+ error= 1;
+ DBUG_PRINT("error",("Error from optimize_cond"));
+ DBUG_RETURN(1);
+ }
+
+ if (cond_value == Item::COND_FALSE || having_value == Item::COND_FALSE ||
+ (!unit->select_limit_cnt && !(select_options & OPTION_FOUND_ROWS)))
+ { /* Impossible cond */
+ zero_result_cause= having_value == Item::COND_FALSE ?
+ "Impossible HAVING" : "Impossible WHERE";
+ error= 0;
+ DBUG_RETURN(0);
+ }
}
/* Optimize count(*), min() and max() */
@@ -531,6 +547,24 @@
}
zero_result_cause= "Select tables optimized away";
tables_list= 0; // All tables resolved
+ /*
+ Extract all table-independent conditions and replace the WHERE
+ clause with them. All other conditions were computed by opt_sum_query
+ and the MIN/MAX/COUNT function(s) have been replaced by constants,
+ so there is no need to compute the whole WHERE clause again.
+ Notice that make_cond_for_table() will always succeed to remove all
+ computed conditions, because opt_sum_query() is applicable only to
+ conjunctions.
+ */
+ if (conds)
+ {
+ COND *table_independent_conds=
+ make_cond_for_table(conds, PSEUDO_TABLE_BITS, 0);
+ DBUG_EXECUTE("where",
+ print_where(table_independent_conds,
+ "where after opt_sum_query()"););
+ conds= table_independent_conds;
+ }
}
}
if (!tables_list)
@@ -683,6 +717,36 @@
if (old_group_list && !group_list)
select_distinct= 0;
}
+ /*
+ Check if we can optimize away GROUP BY/DISTINCT.
+ We can do that if there are no aggregate functions and the
+ fields in DISTINCT clause (if present) and/or columns in GROUP BY
+ (if present) contain direct references to all key parts of
+ an unique index (in whatever order).
+ Note that the unique keys for DISTINCT and GROUP BY should not
+ be the same (as long as they are unique).
+
+ The FROM clause must contain a single non-constant table.
+ */
+ if (tables - const_tables == 1 && (group_list || select_distinct) &&
+ !tmp_table_param.sum_func_count)
+ {
+ if (group_list &&
+ list_contains_unique_index(join_tab[const_tables].table,
+ find_field_in_order_list,
+ (void *) group_list))
+ {
+ group_list= 0;
+ group= 0;
+ }
+ if (select_distinct &&
+ list_contains_unique_index(join_tab[const_tables].table,
+ find_field_in_item_list,
+ (void *) &fields_list))
+ {
+ select_distinct= 0;
+ }
+ }
if (!group_list && group)
{
order=0; // The output has only one row
@@ -876,8 +940,9 @@
group_list ? 0 : select_distinct,
group_list && simple_group,
select_options,
- (order == 0 || skip_sort_order) ? select_limit :
- HA_POS_ERROR,
+ (order == 0 || skip_sort_order ||
+ test(select_options & OPTION_BUFFER_RESULT)) ?
+ select_limit : HA_POS_ERROR,
(char *) "")))
DBUG_RETURN(1);
@@ -2090,13 +2155,17 @@
new_fields->null_rejecting);
}
else if (old->eq_func && new_fields->eq_func &&
- (old->val->is_null() || new_fields->val->is_null()))
+ ((!old->val->used_tables() && old->val->is_null()) ||
+ new_fields->val->is_null()))
{
/* field = expression OR field IS NULL */
old->level= and_level;
old->optimize= KEY_OPTIMIZE_REF_OR_NULL;
- /* Remember the NOT NULL value */
- if (old->val->is_null())
+ /*
+ Remember the NOT NULL value unless the value does not depend
+ on other tables.
+ */
+ if (!old->val->used_tables() && old->val->is_null())
old->val= new_fields->val;
/* The referred expression can be NULL: */
old->null_rejecting= 0;
@@ -3421,7 +3490,7 @@
*/
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;
@@ -3432,7 +3501,7 @@
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;
@@ -3797,6 +3866,7 @@
{
uint i;
bool statistics= test(!(join->select_options & SELECT_DESCRIBE));
+ bool ordered_set= 0;
DBUG_ENTER("make_join_readinfo");
for (i=join->const_tables ; i < join->tables ; i++)
@@ -3806,6 +3876,22 @@
tab->read_record.table= table;
tab->read_record.file=table->file;
tab->next_select=sub_select; /* normal select */
+
+ /*
+ Determine if the set is already ordered for ORDER BY, so it can
+ disable join cache because it will change the ordering of the results.
+ Code handles sort table that is at any location (not only first after
+ the const tables) despite the fact that it's currently prohibited.
+ */
+ if (!ordered_set &&
+ (table == join->sort_by_table &&
+ (!join->order || join->skip_sort_order ||
+ test_if_skip_sort_order(tab, join->order, join->select_limit,
+ 1))
+ ) ||
+ (join->sort_by_table == (TABLE *) 1 && i != join->const_tables))
+ ordered_set= 1;
+
switch (tab->type) {
case JT_SYSTEM: // Only happens with left join
table->status=STATUS_NO_RECORD;
@@ -3876,10 +3962,11 @@
case JT_ALL:
/*
If previous table use cache
+ If the incoming data set is already sorted don't use cache.
*/
table->status=STATUS_NO_RECORD;
if (i != join->const_tables && !(options & SELECT_NO_JOIN_CACHE)
&&
- tab->use_quick != 2 && !tab->on_expr)
+ tab->use_quick != 2 && !tab->on_expr && !ordered_set)
{
if ((options & SELECT_DESCRIBE) ||
!join_init_cache(join->thd,join->join_tab+join->const_tables,
@@ -4386,10 +4473,16 @@
DBUG_RETURN(0);
}
-
+/*
+ used only in JOIN::clear
+*/
static void clear_tables(JOIN *join)
{
- for (uint i=0 ; i < join->tables ; i++)
+ /*
+ must clear only the non-const tables, as const tables
+ are not re-calculated.
+ */
+ for (uint i=join->const_tables ; i < join->tables ; i++)
mark_as_null_row(join->table[i]); // All fields are NULL
}
@@ -4615,10 +4708,8 @@
DBUG_EXECUTE("info", print_where(conds, "after remove"););
}
else
- {
*cond_value= Item::COND_TRUE;
- select->prep_where= 0;
- }
+
DBUG_RETURN(conds);
}
@@ -4712,7 +4803,7 @@
Field *field=((Item_field*) args[0])->field;
if (field->flags & AUTO_INCREMENT_FLAG &&
!field->table->maybe_null &&
(thd->options & OPTION_AUTO_IS_NULL) &&
- thd->insert_id())
+ thd->insert_id() && thd->substitute_null_with_insert_id)
{
#ifdef HAVE_QUERY_CACHE
query_cache_abort(&thd->net);
@@ -4726,7 +4817,7 @@
cond=new_cond;
cond->fix_fields(thd, 0, &cond);
}
- thd->insert_id(0); // Clear for next request
+ thd->substitute_null_with_insert_id= FALSE; // Clear for next request
}
/* fix to replace 'NULL' dates with '0' (shreeve@stripped) */
else if (((field->type() == FIELD_TYPE_DATE) ||
@@ -5180,12 +5271,14 @@
param->group_length : 0,
NullS))
{
- bitmap_clear_bit(&temp_pool, temp_pool_slot);
+ if (temp_pool_slot != MY_BIT_NONE)
+ bitmap_clear_bit(&temp_pool, temp_pool_slot);
DBUG_RETURN(NULL); /* purecov: inspected */
}
if (!(param->copy_field=copy=new Copy_field[field_count]))
{
- bitmap_clear_bit(&temp_pool, temp_pool_slot);
+ if (temp_pool_slot != MY_BIT_NONE)
+ bitmap_clear_bit(&temp_pool, temp_pool_slot);
my_free((gptr) table,MYF(0)); /* purecov: inspected */
DBUG_RETURN(NULL); /* purecov: inspected */
}
@@ -5523,6 +5616,11 @@
keyinfo->key_length+= key_part_info->length;
}
}
+ else
+ {
+ set_if_smaller(table->max_rows, rows_limit);
+ param->end_write_records= rows_limit;
+ }
if (distinct && field_count != param->hidden_field_count)
{
@@ -5537,8 +5635,6 @@
null_pack_length-=hidden_null_pack_length;
keyinfo->key_parts= ((field_count-param->hidden_field_count)+
test(null_pack_length));
- set_if_smaller(table->max_rows, rows_limit);
- param->end_write_records= rows_limit;
table->distinct=1;
table->keys=1;
if (blob_count)
@@ -5605,7 +5701,8 @@
*/
*table->blob_field= 0;
free_tmp_table(thd,table); /* purecov: inspected */
- bitmap_clear_bit(&temp_pool, temp_pool_slot);
+ if (temp_pool_slot != MY_BIT_NONE)
+ bitmap_clear_bit(&temp_pool, temp_pool_slot);
DBUG_RETURN(NULL); /* purecov: inspected */
}
@@ -5768,7 +5865,8 @@
my_free((gptr) entry->record[0],MYF(0));
free_io_cache(entry);
- bitmap_clear_bit(&temp_pool, entry->temp_pool_slot);
+ if (entry->temp_pool_slot != MY_BIT_NONE)
+ bitmap_clear_bit(&temp_pool, entry->temp_pool_slot);
my_free((gptr) entry,MYF(0));
thd->proc_info=save_proc_info;
@@ -6735,8 +6833,13 @@
{
if (!join->first_record)
{
+ List_iterator_fast<Item> it(*join->fields);
+ Item *item;
/* No matching rows for group function */
join->clear();
+
+ while ((item= it++))
+ item->no_rows_in_result();
}
if (join->having && join->having->val_int() == 0)
error= -1; // Didn't satisfy having
@@ -7090,7 +7193,7 @@
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);
}
}
}
@@ -7364,6 +7467,140 @@
}
return best;
}
+
+
+/*
+ Check if GROUP BY/DISTINCT can be optimized away because the set is
+ already known to be distinct.
+
+ SYNOPSIS
+ list_contains_unique_index ()
+ table The table to operate on.
+ find_func function to iterate over the list and search
+ for a field
+
+ DESCRIPTION
+ Used in removing the GROUP BY/DISTINCT of the following types of
+ statements:
+ SELECT [DISTINCT] <unique_key_cols>... FROM <single_table_ref>
+ [GROUP BY <unique_key_cols>,...]
+
+ If (a,b,c is distinct)
+ then <any combination of a,b,c>,{whatever} is also distinct
+
+ This function checks if all the key parts of any of the unique keys
+ of the table are referenced by a list : either the select list
+ through find_field_in_item_list or GROUP BY list through
+ find_field_in_order_list.
+ If the above holds then we can safely remove the GROUP BY/DISTINCT,
+ as no result set can be more distinct than an unique key.
+
+ RETURN VALUE
+ 1 found
+ 0 not found.
+*/
+
+static bool
+list_contains_unique_index(TABLE *table,
+ bool (*find_func) (Field *, void *), void *data)
+{
+ for (uint keynr= 0; keynr < table->keys; keynr++)
+ {
+ if (keynr == table->primary_key ||
+ (table->key_info[keynr].flags & HA_NOSAME))
+ {
+ KEY *keyinfo= table->key_info + keynr;
+ KEY_PART_INFO *key_part, *key_part_end;
+
+ for (key_part=keyinfo->key_part,
+ key_part_end=key_part+ keyinfo->key_parts;
+ key_part < key_part_end;
+ key_part++)
+ {
+ if (!find_func(key_part->field, data))
+ break;
+ }
+ if (key_part == key_part_end)
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+/*
+ Helper function for list_contains_unique_index.
+ Find a field reference in a list of ORDER structures.
+
+ SYNOPSIS
+ find_field_in_order_list ()
+ field The field to search for.
+ data ORDER *.The list to search in
+
+ DESCRIPTION
+ Finds a direct reference of the Field in the list.
+
+ RETURN VALUE
+ 1 found
+ 0 not found.
+*/
+
+static bool
+find_field_in_order_list (Field *field, void *data)
+{
+ ORDER *group= (ORDER *) data;
+ bool part_found= 0;
+ for (ORDER *tmp_group= group; tmp_group; tmp_group=tmp_group->next)
+ {
+ Item *item= (*tmp_group->item)->real_item();
+ if (item->type() == Item::FIELD_ITEM &&
+ ((Item_field*) item)->field->eq(field))
+ {
+ part_found= 1;
+ break;
+ }
+ }
+ return part_found;
+}
+
+
+/*
+ Helper function for list_contains_unique_index.
+ Find a field reference in a dynamic list of Items.
+
+ SYNOPSIS
+ find_field_in_item_list ()
+ field in The field to search for.
+ data in List<Item> *.The list to search in
+
+ DESCRIPTION
+ Finds a direct reference of the Field in the list.
+
+ RETURN VALUE
+ 1 found
+ 0 not found.
+*/
+
+static bool
+find_field_in_item_list (Field *field, void *data)
+{
+ List<Item> *fields= (List<Item> *) data;
+ bool part_found= 0;
+ List_iterator<Item> li(*fields);
+ Item *item;
+
+ while ((item= li++))
+ {
+ if (item->type() == Item::FIELD_ITEM &&
+ ((Item_field*) item)->field->eq(field))
+ {
+ part_found= 1;
+ break;
+ }
+ }
+ return part_found;
+}
+
/*
Test if we can skip the ORDER BY by using an index.
--- 1.70/mysql-test/r/ctype_utf8.result 2006-08-16 09:31:29 +05:00
+++ 1.71/mysql-test/r/ctype_utf8.result 2006-08-16 09:31:29 +05:00
@@ -1155,3 +1155,188 @@
Table Op Msg_type Msg_text
test.t1 check status OK
drop table t1;
+SET NAMES utf8;
+CREATE TABLE t1 (id int PRIMARY KEY,
+a varchar(16) collate utf8_unicode_ci NOT NULL default '',
+b int,
+f varchar(128) default 'XXX',
+INDEX (a(4))
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
+INSERT INTO t1(id, a, b) VALUES
+(1, 'cccc', 50), (2, 'cccc', 70), (3, 'cccc', 30),
+(4, 'cccc', 30), (5, 'cccc', 20), (6, 'bbbbbb', 40),
+(7, 'dddd', 30), (8, 'aaaa', 10), (9, 'aaaa', 50),
+(10, 'eeeee', 40), (11, 'bbbbbb', 60);
+SELECT id, a, b FROM t1;
+id a b
+1 cccc 50
+2 cccc 70
+3 cccc 30
+4 cccc 30
+5 cccc 20
+6 bbbbbb 40
+7 dddd 30
+8 aaaa 10
+9 aaaa 50
+10 eeeee 40
+11 bbbbbb 60
+SELECT id, a, b FROM t1 WHERE a BETWEEN 'aaaa' AND 'bbbbbb';
+id a b
+8 aaaa 10
+9 aaaa 50
+6 bbbbbb 40
+11 bbbbbb 60
+SELECT id, a FROM t1 WHERE a='bbbbbb';
+id a
+6 bbbbbb
+11 bbbbbb
+SELECT id, a FROM t1 WHERE a='bbbbbb' ORDER BY b;
+id a
+6 bbbbbb
+11 bbbbbb
+DROP TABLE t1;
+SET NAMES utf8;
+CREATE TABLE t1 (
+a CHAR(13) DEFAULT '',
+INDEX(a)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
+INSERT INTO t1 VALUES
+('Käli Käli 2-4'), ('Käli Käli 2-4'),
+('Käli Käli 2+4'), ('Käli Käli 2+4'),
+('Käli Käli 2-6'), ('Käli Käli 2-6');
+INSERT INTO t1 SELECT * FROM t1;
+CREATE TABLE t2 (
+a CHAR(13) DEFAULT '',
+INDEX(a)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;
+INSERT INTO t2 VALUES
+('Kali Kali 2-4'), ('Kali Kali 2-4'),
+('Kali Kali 2+4'), ('Kali Kali 2+4'),
+('Kali Kali 2-6'), ('Kali Kali 2-6');
+INSERT INTO t2 SELECT * FROM t2;
+SELECT a FROM t1 WHERE a LIKE 'Käli Käli 2+4';
+a
+Käli Käli 2+4
+Käli Käli 2+4
+Käli Käli 2+4
+Käli Käli 2+4
+SELECT a FROM t2 WHERE a LIKE 'Kali Kali 2+4';
+a
+Kali Kali 2+4
+Kali Kali 2+4
+Kali Kali 2+4
+Kali Kali 2+4
+EXPLAIN SELECT a FROM t1 WHERE a LIKE 'Käli Käli 2+4';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range a a 40 NULL 4 Using where; Using index
+EXPLAIN SELECT a FROM t1 WHERE a = 'Käli Käli 2+4';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref a a 40 const 4 Using where; Using index
+EXPLAIN SELECT a FROM t2 WHERE a LIKE 'Kali Kali 2+4';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range a a 14 NULL 4 Using where; Using index
+EXPLAIN SELECT a FROM t2 WHERE a = 'Kali Kali 2+4';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ref a a 14 const 4 Using where; Using index
+DROP TABLE t1,t2;
+CREATE TABLE t1 (
+a char(255) DEFAULT '',
+KEY(a(10))
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
+INSERT INTO t1 VALUES ('Käli Käli 2-4');
+SELECT * FROM t1 WHERE a LIKE 'Käli Käli 2%';
+a
+Käli Käli 2-4
+INSERT INTO t1 VALUES ('Käli Käli 2-4');
+SELECT * FROM t1 WHERE a LIKE 'Käli Käli 2%';
+a
+Käli Käli 2-4
+Käli Käli 2-4
+DROP TABLE t1;
+CREATE TABLE t1 (
+a char(255) DEFAULT ''
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
+INSERT INTO t1 VALUES ('Käli Käli 2-4');
+INSERT INTO t1 VALUES ('Käli Käli 2-4');
+SELECT * FROM t1 WHERE a LIKE 'Käli Käli 2%';
+a
+Käli Käli 2-4
+Käli Käli 2-4
+ALTER TABLE t1 ADD KEY (a(10));
+SELECT * FROM t1 WHERE a LIKE 'Käli Käli 2%';
+a
+Käli Käli 2-4
+Käli Käli 2-4
+DROP TABLE t1;
+SET NAMES latin2;
+CREATE TABLE t1 (
+id int(11) NOT NULL default '0',
+tid int(11) NOT NULL default '0',
+val text NOT NULL,
+INDEX idx(tid, val(10))
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+INSERT INTO t1 VALUES
+(40988,72,'VOLNÝ ADSL'),(41009,72,'VOLNÝ ADSL'),
+(41032,72,'VOLNÝ ADSL'),(41038,72,'VOLNÝ ADSL'),
+(41063,72,'VOLNÝ ADSL'),(41537,72,'VOLNÝ ADSL Office'),
+(42141,72,'VOLNÝ ADSL'),(42565,72,'VOLNÝ ADSL Combi'),
+(42749,72,'VOLNÝ ADSL'),(44205,72,'VOLNÝ ADSL');
+SELECT * FROM t1 WHERE tid=72 and val LIKE 'VOLNY ADSL';
+id tid val
+40988 72 VOLNÝ ADSL
+41009 72 VOLNÝ ADSL
+41032 72 VOLNÝ ADSL
+41038 72 VOLNÝ ADSL
+41063 72 VOLNÝ ADSL
+42141 72 VOLNÝ ADSL
+42749 72 VOLNÝ ADSL
+44205 72 VOLNÝ ADSL
+SELECT * FROM t1 WHERE tid=72 and val LIKE 'VOLNÝ ADSL';
+id tid val
+40988 72 VOLNÝ ADSL
+41009 72 VOLNÝ ADSL
+41032 72 VOLNÝ ADSL
+41038 72 VOLNÝ ADSL
+41063 72 VOLNÝ ADSL
+42141 72 VOLNÝ ADSL
+42749 72 VOLNÝ ADSL
+44205 72 VOLNÝ ADSL
+SELECT * FROM t1 WHERE tid=72 and val LIKE '%VOLNÝ ADSL';
+id tid val
+40988 72 VOLNÝ ADSL
+41009 72 VOLNÝ ADSL
+41032 72 VOLNÝ ADSL
+41038 72 VOLNÝ ADSL
+41063 72 VOLNÝ ADSL
+42141 72 VOLNÝ ADSL
+42749 72 VOLNÝ ADSL
+44205 72 VOLNÝ ADSL
+ALTER TABLE t1 DROP KEY idx;
+ALTER TABLE t1 ADD KEY idx (tid,val(11));
+SELECT * FROM t1 WHERE tid=72 and val LIKE 'VOLNÝ ADSL';
+id tid val
+40988 72 VOLNÝ ADSL
+41009 72 VOLNÝ ADSL
+41032 72 VOLNÝ ADSL
+41038 72 VOLNÝ ADSL
+41063 72 VOLNÝ ADSL
+42141 72 VOLNÝ ADSL
+42749 72 VOLNÝ ADSL
+44205 72 VOLNÝ ADSL
+DROP TABLE t1;
+create table t1(a char(200) collate utf8_unicode_ci NOT NULL default '')
+default charset=utf8 collate=utf8_unicode_ci;
+insert into t1 values (unhex('65')), (unhex('C3A9')), (unhex('65'));
+explain select distinct a from t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using temporary
+select distinct a from t1;
+a
+e
+explain select a from t1 group by a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using temporary; Using filesort
+select a from t1 group by a;
+a
+e
+drop table t1;
--- 1.72/mysql-test/t/ctype_utf8.test 2006-08-16 09:31:29 +05:00
+++ 1.73/mysql-test/t/ctype_utf8.test 2006-08-16 09:31:29 +05:00
@@ -944,4 +944,132 @@
check table t1;
drop table t1;
+#
+# Bug#14896: Comparison with a key in a partial index over mb chararacter field
+#
+
+SET NAMES utf8;
+CREATE TABLE t1 (id int PRIMARY KEY,
+ a varchar(16) collate utf8_unicode_ci NOT NULL default '',
+ b int,
+ f varchar(128) default 'XXX',
+ INDEX (a(4))
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
+INSERT INTO t1(id, a, b) VALUES
+ (1, 'cccc', 50), (2, 'cccc', 70), (3, 'cccc', 30),
+ (4, 'cccc', 30), (5, 'cccc', 20), (6, 'bbbbbb', 40),
+ (7, 'dddd', 30), (8, 'aaaa', 10), (9, 'aaaa', 50),
+ (10, 'eeeee', 40), (11, 'bbbbbb', 60);
+
+SELECT id, a, b FROM t1;
+
+SELECT id, a, b FROM t1 WHERE a BETWEEN 'aaaa' AND 'bbbbbb';
+
+SELECT id, a FROM t1 WHERE a='bbbbbb';
+SELECT id, a FROM t1 WHERE a='bbbbbb' ORDER BY b;
+
+DROP TABLE t1;
+
+#
+# Bug#16674: LIKE predicate for a utf8 character set column
+#
+
+SET NAMES utf8;
+
+CREATE TABLE t1 (
+ a CHAR(13) DEFAULT '',
+ INDEX(a)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
+INSERT INTO t1 VALUES
+ ('Käli Käli 2-4'), ('Käli Käli 2-4'),
+ ('Käli Käli 2+4'), ('Käli Käli 2+4'),
+ ('Käli Käli 2-6'), ('Käli Käli 2-6');
+INSERT INTO t1 SELECT * FROM t1;
+
+CREATE TABLE t2 (
+ a CHAR(13) DEFAULT '',
+ INDEX(a)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;
+
+INSERT INTO t2 VALUES
+ ('Kali Kali 2-4'), ('Kali Kali 2-4'),
+ ('Kali Kali 2+4'), ('Kali Kali 2+4'),
+ ('Kali Kali 2-6'), ('Kali Kali 2-6');
+INSERT INTO t2 SELECT * FROM t2;
+
+SELECT a FROM t1 WHERE a LIKE 'Käli Käli 2+4';
+SELECT a FROM t2 WHERE a LIKE 'Kali Kali 2+4';
+
+EXPLAIN SELECT a FROM t1 WHERE a LIKE 'Käli Käli 2+4';
+EXPLAIN SELECT a FROM t1 WHERE a = 'Käli Käli 2+4';
+EXPLAIN SELECT a FROM t2 WHERE a LIKE 'Kali Kali 2+4';
+EXPLAIN SELECT a FROM t2 WHERE a = 'Kali Kali 2+4';
+
+DROP TABLE t1,t2;
+
+CREATE TABLE t1 (
+ a char(255) DEFAULT '',
+ KEY(a(10))
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
+INSERT INTO t1 VALUES ('Käli Käli 2-4');
+SELECT * FROM t1 WHERE a LIKE 'Käli Käli 2%';
+INSERT INTO t1 VALUES ('Käli Käli 2-4');
+SELECT * FROM t1 WHERE a LIKE 'Käli Käli 2%';
+DROP TABLE t1;
+
+CREATE TABLE t1 (
+ a char(255) DEFAULT ''
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
+INSERT INTO t1 VALUES ('Käli Käli 2-4');
+INSERT INTO t1 VALUES ('Käli Käli 2-4');
+SELECT * FROM t1 WHERE a LIKE 'Käli Käli 2%';
+ALTER TABLE t1 ADD KEY (a(10));
+SELECT * FROM t1 WHERE a LIKE 'Käli Käli 2%';
+DROP TABLE t1;
+
+#
+# Bug#18359: LIKE predicate for a 'utf8' text column with a partial index
+# (see bug #16674 as well)
+#
+
+SET NAMES latin2;
+
+CREATE TABLE t1 (
+ id int(11) NOT NULL default '0',
+ tid int(11) NOT NULL default '0',
+ val text NOT NULL,
+ INDEX idx(tid, val(10))
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
+INSERT INTO t1 VALUES
+ (40988,72,'VOLNÝ ADSL'),(41009,72,'VOLNÝ ADSL'),
+ (41032,72,'VOLNÝ ADSL'),(41038,72,'VOLNÝ ADSL'),
+ (41063,72,'VOLNÝ ADSL'),(41537,72,'VOLNÝ ADSL Office'),
+ (42141,72,'VOLNÝ ADSL'),(42565,72,'VOLNÝ ADSL Combi'),
+ (42749,72,'VOLNÝ ADSL'),(44205,72,'VOLNÝ ADSL');
+
+SELECT * FROM t1 WHERE tid=72 and val LIKE 'VOLNY ADSL';
+SELECT * FROM t1 WHERE tid=72 and val LIKE 'VOLNÝ ADSL';
+SELECT * FROM t1 WHERE tid=72 and val LIKE '%VOLNÝ ADSL';
+
+ALTER TABLE t1 DROP KEY idx;
+ALTER TABLE t1 ADD KEY idx (tid,val(11));
+
+SELECT * FROM t1 WHERE tid=72 and val LIKE 'VOLNÝ ADSL';
+
+DROP TABLE t1;
+
+#
+# Bug 20709: problem with utf8 fields in temporary tables
+#
+
+create table t1(a char(200) collate utf8_unicode_ci NOT NULL default '')
+ default charset=utf8 collate=utf8_unicode_ci;
+insert into t1 values (unhex('65')), (unhex('C3A9')), (unhex('65'));
+explain select distinct a from t1;
+select distinct a from t1;
+explain select a from t1 group by a;
+select a from t1 group by a;
+drop table t1;
+
# End of 4.1 tests
| Thread |
|---|
| • bk commit into 4.1 tree (bar:1.2534) | bar | 16 Aug |