Commit 217d83a6 authored by bar@mysql.com's avatar bar@mysql.com

Bug#6202: ENUMs are not case sensitive even if declared BINARY

parent e4be2877
......@@ -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);
......
......@@ -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;
......@@ -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;
......@@ -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
......
......@@ -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,
......
......@@ -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};
/*****************************************************************************
......
......@@ -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)
{
......
......@@ -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};
/*
......
......@@ -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);
......
......@@ -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)
......
......@@ -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,
......
......@@ -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);
......
......@@ -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
};
/*****************************************************************************
......
......@@ -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,
......
......@@ -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);
}
......
......@@ -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
......
......@@ -116,6 +116,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
......
......@@ -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;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment