diff options
author | unknown <bar@mysql.com> | 2004-10-25 17:51:26 +0500 |
---|---|---|
committer | unknown <bar@mysql.com> | 2004-10-25 17:51:26 +0500 |
commit | 712326d6846ae718bf5c7c5961ec3173bbf29b06 (patch) | |
tree | 7a9462068baaf8b0e98b30d9e65951269bac98e5 | |
parent | 7df41480849074ad0b1a907d244b5d3b41403f32 (diff) | |
download | mariadb-git-712326d6846ae718bf5c7c5961ec3173bbf29b06.tar.gz |
Bug#6202: ENUMs are not case sensitive even if declared BINARY
-rw-r--r-- | include/typelib.h | 1 | ||||
-rw-r--r-- | mysql-test/r/type_enum.result | 18 | ||||
-rw-r--r-- | mysql-test/t/type_enum.test | 13 | ||||
-rw-r--r-- | sql/field.cc | 2 | ||||
-rw-r--r-- | sql/ha_berkeley.cc | 2 | ||||
-rw-r--r-- | sql/ha_myisam.cc | 2 | ||||
-rw-r--r-- | sql/handler.cc | 2 | ||||
-rw-r--r-- | sql/item_timefunc.cc | 4 | ||||
-rw-r--r-- | sql/mysql_priv.h | 1 | ||||
-rw-r--r-- | sql/mysqld.cc | 2 | ||||
-rw-r--r-- | sql/repl_failsafe.cc | 4 | ||||
-rw-r--r-- | sql/set_var.cc | 5 | ||||
-rw-r--r-- | sql/sql_cache.cc | 2 | ||||
-rw-r--r-- | sql/sql_db.cc | 4 | ||||
-rw-r--r-- | sql/sql_parse.cc | 18 | ||||
-rw-r--r-- | sql/sql_show.cc | 2 | ||||
-rw-r--r-- | sql/strfunc.cc | 41 | ||||
-rw-r--r-- | sql/table.cc | 31 |
18 files changed, 131 insertions, 23 deletions
diff --git a/include/typelib.h b/include/typelib.h index 1b049d19a11..4d6a90ad51e 100644 --- a/include/typelib.h +++ b/include/typelib.h @@ -22,6 +22,7 @@ typedef struct st_typelib { /* Different types saved here */ unsigned int count; /* How many types */ const char *name; /* Name of typelib */ const char **type_names; + unsigned int *type_lengths; } TYPELIB; extern int find_type(char *x,TYPELIB *typelib,unsigned int full_name); diff --git a/mysql-test/r/type_enum.result b/mysql-test/r/type_enum.result index a94e90885db..27539953aa9 100644 --- a/mysql-test/r/type_enum.result +++ b/mysql-test/r/type_enum.result @@ -1677,3 +1677,21 @@ Field Type Null Key Default Extra a int(11) YES 1 b enum('value','öäü_value','ÊÃÕ') value drop table t1; +CREATE TABLE t1 (c enum('a', 'A') BINARY); +Warnings: +Note 1291 Column 'c' has duplicated value 'a' in ENUM +INSERT INTO t1 VALUES ('a'),('A'); +SELECT * FROM t1; +c +a +A +DROP TABLE t1; +CREATE TABLE t1 (c enum('ae','oe','ue','ss') collate latin1_german2_ci); +INSERT INTO t1 VALUES ('ä'),('ö'),('ü'),('ß'); +SELECT * FROM t1; +c +ae +oe +ue +ss +DROP TABLE t1; diff --git a/mysql-test/t/type_enum.test b/mysql-test/t/type_enum.test index 2f1e11810af..dc2e4d0f469 100644 --- a/mysql-test/t/type_enum.test +++ b/mysql-test/t/type_enum.test @@ -59,3 +59,16 @@ CREATE TABLE t1 ( show create table t1; show columns from t1; drop table t1; + +# +# Bugs #6154, 6206: ENUMs are not case sensitive even if declared BINARY +# +CREATE TABLE t1 (c enum('a', 'A') BINARY); +INSERT INTO t1 VALUES ('a'),('A'); +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (c enum('ae','oe','ue','ss') collate latin1_german2_ci); +INSERT INTO t1 VALUES ('ä'),('ö'),('ü'),('ß'); +SELECT * FROM t1; +DROP TABLE t1; diff --git a/sql/field.cc b/sql/field.cc index aae507cd0ec..e7631fb08aa 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -5514,7 +5514,7 @@ int Field_enum::store(const char *from,uint length,CHARSET_INFO *cs) /* Remove end space */ while (length > 0 && my_isspace(system_charset_info,from[length-1])) length--; - uint tmp=find_type(typelib, from, length, 0); + uint tmp=find_type2(typelib, from, length, field_charset); if (!tmp) { if (length < 6) // Can't be more than 99999 enums diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc index c688f3c3597..09b3e340d1f 100644 --- a/sql/ha_berkeley.cc +++ b/sql/ha_berkeley.cc @@ -90,7 +90,7 @@ const char *berkeley_lock_names[] = u_int32_t berkeley_lock_types[]= { DB_LOCK_DEFAULT, DB_LOCK_OLDEST, DB_LOCK_RANDOM }; TYPELIB berkeley_lock_typelib= {array_elements(berkeley_lock_names)-1,"", - berkeley_lock_names}; + berkeley_lock_names, NULL}; static void berkeley_print_error(const char *db_errpfx, char *buffer); static byte* bdb_get_key(BDB_SHARE *share,uint *length, diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc index 6504dd321a0..a7beae664b9 100644 --- a/sql/ha_myisam.cc +++ b/sql/ha_myisam.cc @@ -37,7 +37,7 @@ ulong myisam_recover_options= HA_RECOVER_NONE; const char *myisam_recover_names[] = { "DEFAULT", "BACKUP", "FORCE", "QUICK", NullS}; TYPELIB myisam_recover_typelib= {array_elements(myisam_recover_names)-1,"", - myisam_recover_names}; + myisam_recover_names, NULL}; /***************************************************************************** diff --git a/sql/handler.cc b/sql/handler.cc index cecf5689464..f7a1a6ef0bf 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -107,7 +107,7 @@ const char *tx_isolation_names[] = { "READ-UNCOMMITTED", "READ-COMMITTED", "REPEATABLE-READ", "SERIALIZABLE", NullS}; TYPELIB tx_isolation_typelib= {array_elements(tx_isolation_names)-1,"", - tx_isolation_names}; + tx_isolation_names, NULL}; enum db_type ha_resolve_by_name(const char *name, uint namelen) { diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 48c1f2c5443..3c8dbb013a9 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -36,7 +36,7 @@ static const char *month_names[]= }; TYPELIB month_names_typelib= -{ array_elements(month_names)-1,"", month_names }; +{ array_elements(month_names)-1,"", month_names, NULL }; static const char *day_names[]= { @@ -45,7 +45,7 @@ static const char *day_names[]= }; TYPELIB day_names_typelib= -{ array_elements(day_names)-1,"", day_names}; +{ array_elements(day_names)-1,"", day_names, NULL}; /* diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 391199942e0..6dac0d9a38f 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -812,6 +812,7 @@ extern bool check_reserved_words(LEX_STRING *name); ulonglong find_set(TYPELIB *typelib,const char *x, uint length, char **err_pos, uint *err_len, bool *set_warning); uint find_type(TYPELIB *lib, const char *find, uint length, bool part_match); +uint find_type2(TYPELIB *lib, const char *find, uint length, CHARSET_INFO *cs); uint check_word(TYPELIB *lib, const char *val, const char *end, const char **end_of_word); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 384f76029f9..7062334edbb 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -219,7 +219,7 @@ const char *sql_mode_names[] = "NO_AUTO_VALUE_ON_ZERO", NullS }; TYPELIB sql_mode_typelib= { array_elements(sql_mode_names)-1,"", - sql_mode_names }; + sql_mode_names, NULL }; const char *first_keyword= "first", *binary_keyword= "BINARY"; const char *my_localhost= "localhost", *delayed_user= "DELAYED"; #if SIZEOF_OFF_T > 4 && defined(BIG_TABLES) diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc index 66c6e7c508d..83fceca80ef 100644 --- a/sql/repl_failsafe.cc +++ b/sql/repl_failsafe.cc @@ -35,7 +35,7 @@ HASH slave_list; const char *rpl_role_type[] = {"MASTER","SLAVE",NullS}; TYPELIB rpl_role_typelib = {array_elements(rpl_role_type)-1,"", - rpl_role_type}; + rpl_role_type, NULL}; const char* rpl_status_type[]= { @@ -43,7 +43,7 @@ const char* rpl_status_type[]= "RECOVERY_CAPTAIN","NULL",NullS }; TYPELIB rpl_status_typelib= {array_elements(rpl_status_type)-1,"", - rpl_status_type}; + rpl_status_type, NULL}; static Slave_log_event* find_slave_event(IO_CACHE* log, diff --git a/sql/set_var.cc b/sql/set_var.cc index b5e479b9985..60a51314742 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -73,13 +73,14 @@ static HASH system_variable_hash; const char *bool_type_names[]= { "OFF", "ON", NullS }; TYPELIB bool_typelib= { - array_elements(bool_type_names)-1, "", bool_type_names + array_elements(bool_type_names)-1, "", bool_type_names, NULL }; const char *delay_key_write_type_names[]= { "OFF", "ON", "ALL", NullS }; TYPELIB delay_key_write_typelib= { - array_elements(delay_key_write_type_names)-1, "", delay_key_write_type_names + array_elements(delay_key_write_type_names)-1, "", + delay_key_write_type_names, NULL }; static int sys_check_charset(THD *thd, set_var *var); diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 7aa0ef83238..0b338ebccb8 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -363,7 +363,7 @@ TODO list: const char *query_cache_type_names[]= { "OFF", "ON", "DEMAND",NullS }; TYPELIB query_cache_type_typelib= { - array_elements(query_cache_type_names)-1,"", query_cache_type_names + array_elements(query_cache_type_names)-1,"", query_cache_type_names, NULL }; /***************************************************************************** diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 426f7d36633..eb851e79d2e 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -28,12 +28,12 @@ const char *del_exts[]= {".frm", ".BAK", ".TMD",".opt", NullS}; static TYPELIB deletable_extentions= -{array_elements(del_exts)-1,"del_exts", del_exts}; +{array_elements(del_exts)-1,"del_exts", del_exts, NULL}; const char *known_exts[]= {".ISM",".ISD",".ISM",".MRG",".MYI",".MYD",".db", ".ibd", NullS}; static TYPELIB known_extentions= -{array_elements(known_exts)-1,"known_exts", known_exts}; +{array_elements(known_exts)-1,"known_exts", known_exts, NULL}; static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, const char *path, diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index fd037ac2da4..dfe6fc049e0 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -4090,6 +4090,7 @@ bool mysql_test_parse_for_slave(THD *thd, char *inBuf, uint length) } #endif + /***************************************************************************** ** Store field definition for create ** Return 0 if ok @@ -4405,10 +4406,14 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type, new_field->pack_length=8; new_field->interval=interval; new_field->length=0; - for (const char **pos=interval->type_names; *pos ; pos++) + uint *lengths; + const char **pos; + for (pos=interval->type_names, + lengths= interval->type_lengths; *pos ; pos++, lengths++) { - uint length= (uint) strip_sp((char*) *pos)+1; CHARSET_INFO *cs= thd->variables.character_set_client; + uint length= (uint) strip_sp((char*) *pos)+1; + set_if_smaller(*lengths, length); length= cs->cset->numchars(cs, *pos, *pos+length); new_field->length+= length; } @@ -4438,10 +4443,15 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type, new_field->interval=interval; new_field->pack_length=interval->count < 256 ? 1 : 2; // Should be safe new_field->length=(uint) strip_sp((char*) interval->type_names[0]); - for (const char **pos=interval->type_names+1; *pos ; pos++) + set_if_smaller(interval->type_lengths[0], new_field->length); + uint *lengths; + const char **pos; + for (pos= interval->type_names+1, + lengths= interval->type_lengths+1; *pos ; pos++, lengths++) { - uint length=(uint) strip_sp((char*) *pos); CHARSET_INFO *cs= thd->variables.character_set_client; + uint length=(uint) strip_sp((char*) *pos); + set_if_smaller(*lengths, length); length= cs->cset->numchars(cs, *pos, *pos+length); set_if_bigger(new_field->length,length); } diff --git a/sql/sql_show.cc b/sql/sql_show.cc index e030db2caf7..3bf11c0d6b8 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -34,7 +34,7 @@ static const char *grant_names[]={ #ifndef NO_EMBEDDED_ACCESS_CHECKS static TYPELIB grant_types = { sizeof(grant_names)/sizeof(char **), "grant_types", - grant_names}; + grant_names, NULL}; #endif static int diff --git a/sql/strfunc.cc b/sql/strfunc.cc index d00e57df5a1..ea67a5a4343 100644 --- a/sql/strfunc.cc +++ b/sql/strfunc.cc @@ -117,6 +117,47 @@ uint find_type(TYPELIB *lib, const char *find, uint length, bool part_match) /* + Find a string in a list of strings according to collation + + SYNOPSIS + find_type2() + lib TYPELIB (struct of pointer to values + count) + x String to find + length String length + cs Character set + collation to use for comparison + + NOTES + + RETURN + 0 No matching value + >0 Offset+1 in typelib for matched string +*/ + +uint find_type2(TYPELIB *typelib, const char *x, uint length, CHARSET_INFO *cs) +{ + int find,pos,findpos; + const char *j; + DBUG_ENTER("find_type2"); + DBUG_PRINT("enter",("x: '%s' lib: 0x%lx",x,typelib)); + + if (!typelib->count) + { + DBUG_PRINT("exit",("no count")); + DBUG_RETURN(0); + } + LINT_INIT(findpos); + for (find=0, pos=0 ; (j=typelib->type_names[pos]) ; pos++) + { + if (!my_strnncoll(cs, (const uchar*) x, length, + (const uchar*) j, typelib->type_lengths[pos])) + DBUG_RETURN(pos+1); + } + DBUG_PRINT("exit",("Couldn't find type")); + DBUG_RETURN(0); +} /* find_type */ + + +/* Check if the first word in a string is one of the ones in TYPELIB SYNOPSIS diff --git a/sql/table.cc b/sql/table.cc index 7b64ef7a48c..3ae3d668407 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -356,6 +356,24 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, fix_type_pointers(&int_array,&outparam->fieldnames,1,&names); fix_type_pointers(&int_array,outparam->intervals,interval_count, &names); + + { + /* Set ENUM and SET lengths */ + TYPELIB *interval; + for (interval= outparam->intervals; + interval < outparam->intervals + interval_count; + interval++) + { + uint count= (uint) (interval->count + 1) * sizeof(uint); + if (!(interval->type_lengths= (uint *) alloc_root(&outparam->mem_root, + count))) + goto err_not_open; + for (count= 0; count < interval->count; count++) + interval->type_lengths[count]= strlen(interval->type_names[count]); + interval->type_lengths[count]= 0; + } + } + if (keynames) fix_type_pointers(&int_array,&outparam->keynames,1,&keynames); VOID(my_close(file,MYF(MY_WME))); @@ -1007,14 +1025,19 @@ TYPELIB *typelib(List<String> &strings) return 0; result->count=strings.elements; result->name=""; - if (!(result->type_names=(const char **) sql_alloc(sizeof(char *)* - (result->count+1)))) + uint nbytes= (sizeof(char*) + sizeof(uint)) * (result->count + 1); + if (!(result->type_names= (const char**) sql_alloc(nbytes))) return 0; + result->type_lengths= (uint*) (result->type_names + result->count + 1); List_iterator<String> it(strings); String *tmp; for (uint i=0; (tmp=it++) ; i++) - result->type_names[i]=tmp->ptr(); - result->type_names[result->count]=0; // End marker + { + result->type_names[i]= tmp->ptr(); + result->type_lengths[i]= tmp->length(); + } + result->type_names[result->count]= 0; // End marker + result->type_lengths[result->count]= 0; return result; } |