mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Bug#6202: ENUMs are not case sensitive even if declared BINARY
This commit is contained in:
@ -22,6 +22,7 @@ typedef struct st_typelib { /* Different types saved here */
|
|||||||
unsigned int count; /* How many types */
|
unsigned int count; /* How many types */
|
||||||
const char *name; /* Name of typelib */
|
const char *name; /* Name of typelib */
|
||||||
const char **type_names;
|
const char **type_names;
|
||||||
|
unsigned int *type_lengths;
|
||||||
} TYPELIB;
|
} TYPELIB;
|
||||||
|
|
||||||
extern int find_type(char *x,TYPELIB *typelib,unsigned int full_name);
|
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
|
a int(11) YES 1
|
||||||
b enum('value','<27><><EFBFBD>_value','<27><><EFBFBD>') value
|
b enum('value','<27><><EFBFBD>_value','<27><><EFBFBD>') value
|
||||||
drop table t1;
|
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 ('<27>'),('<27>'),('<27>'),('<27>');
|
||||||
|
SELECT * FROM t1;
|
||||||
|
c
|
||||||
|
ae
|
||||||
|
oe
|
||||||
|
ue
|
||||||
|
ss
|
||||||
|
DROP TABLE t1;
|
||||||
|
@ -59,3 +59,16 @@ CREATE TABLE t1 (
|
|||||||
show create table t1;
|
show create table t1;
|
||||||
show columns from t1;
|
show columns from t1;
|
||||||
drop table 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 ('<27>'),('<27>'),('<27>'),('<27>');
|
||||||
|
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 */
|
/* Remove end space */
|
||||||
while (length > 0 && my_isspace(system_charset_info,from[length-1]))
|
while (length > 0 && my_isspace(system_charset_info,from[length-1]))
|
||||||
length--;
|
length--;
|
||||||
uint tmp=find_type(typelib, from, length, 0);
|
uint tmp=find_type2(typelib, from, length, field_charset);
|
||||||
if (!tmp)
|
if (!tmp)
|
||||||
{
|
{
|
||||||
if (length < 6) // Can't be more than 99999 enums
|
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[]=
|
u_int32_t berkeley_lock_types[]=
|
||||||
{ DB_LOCK_DEFAULT, DB_LOCK_OLDEST, DB_LOCK_RANDOM };
|
{ DB_LOCK_DEFAULT, DB_LOCK_OLDEST, DB_LOCK_RANDOM };
|
||||||
TYPELIB berkeley_lock_typelib= {array_elements(berkeley_lock_names)-1,"",
|
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 void berkeley_print_error(const char *db_errpfx, char *buffer);
|
||||||
static byte* bdb_get_key(BDB_SHARE *share,uint *length,
|
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[] =
|
const char *myisam_recover_names[] =
|
||||||
{ "DEFAULT", "BACKUP", "FORCE", "QUICK", NullS};
|
{ "DEFAULT", "BACKUP", "FORCE", "QUICK", NullS};
|
||||||
TYPELIB myisam_recover_typelib= {array_elements(myisam_recover_names)-1,"",
|
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",
|
{ "READ-UNCOMMITTED", "READ-COMMITTED", "REPEATABLE-READ", "SERIALIZABLE",
|
||||||
NullS};
|
NullS};
|
||||||
TYPELIB tx_isolation_typelib= {array_elements(tx_isolation_names)-1,"",
|
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)
|
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=
|
TYPELIB month_names_typelib=
|
||||||
{ array_elements(month_names)-1,"", month_names };
|
{ array_elements(month_names)-1,"", month_names, NULL };
|
||||||
|
|
||||||
static const char *day_names[]=
|
static const char *day_names[]=
|
||||||
{
|
{
|
||||||
@ -45,7 +45,7 @@ static const char *day_names[]=
|
|||||||
};
|
};
|
||||||
|
|
||||||
TYPELIB day_names_typelib=
|
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,
|
ulonglong find_set(TYPELIB *typelib,const char *x, uint length,
|
||||||
char **err_pos, uint *err_len, bool *set_warning);
|
char **err_pos, uint *err_len, bool *set_warning);
|
||||||
uint find_type(TYPELIB *lib, const char *find, uint length, bool part_match);
|
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,
|
uint check_word(TYPELIB *lib, const char *val, const char *end,
|
||||||
const char **end_of_word);
|
const char **end_of_word);
|
||||||
|
|
||||||
|
@ -219,7 +219,7 @@ const char *sql_mode_names[] =
|
|||||||
"NO_AUTO_VALUE_ON_ZERO", NullS
|
"NO_AUTO_VALUE_ON_ZERO", NullS
|
||||||
};
|
};
|
||||||
TYPELIB sql_mode_typelib= { array_elements(sql_mode_names)-1,"",
|
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 *first_keyword= "first", *binary_keyword= "BINARY";
|
||||||
const char *my_localhost= "localhost", *delayed_user= "DELAYED";
|
const char *my_localhost= "localhost", *delayed_user= "DELAYED";
|
||||||
#if SIZEOF_OFF_T > 4 && defined(BIG_TABLES)
|
#if SIZEOF_OFF_T > 4 && defined(BIG_TABLES)
|
||||||
|
@ -35,7 +35,7 @@ HASH slave_list;
|
|||||||
|
|
||||||
const char *rpl_role_type[] = {"MASTER","SLAVE",NullS};
|
const char *rpl_role_type[] = {"MASTER","SLAVE",NullS};
|
||||||
TYPELIB rpl_role_typelib = {array_elements(rpl_role_type)-1,"",
|
TYPELIB rpl_role_typelib = {array_elements(rpl_role_type)-1,"",
|
||||||
rpl_role_type};
|
rpl_role_type, NULL};
|
||||||
|
|
||||||
const char* rpl_status_type[]=
|
const char* rpl_status_type[]=
|
||||||
{
|
{
|
||||||
@ -43,7 +43,7 @@ const char* rpl_status_type[]=
|
|||||||
"RECOVERY_CAPTAIN","NULL",NullS
|
"RECOVERY_CAPTAIN","NULL",NullS
|
||||||
};
|
};
|
||||||
TYPELIB rpl_status_typelib= {array_elements(rpl_status_type)-1,"",
|
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,
|
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 };
|
const char *bool_type_names[]= { "OFF", "ON", NullS };
|
||||||
TYPELIB bool_typelib=
|
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 };
|
const char *delay_key_write_type_names[]= { "OFF", "ON", "ALL", NullS };
|
||||||
TYPELIB delay_key_write_typelib=
|
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);
|
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 };
|
const char *query_cache_type_names[]= { "OFF", "ON", "DEMAND",NullS };
|
||||||
TYPELIB query_cache_type_typelib=
|
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};
|
const char *del_exts[]= {".frm", ".BAK", ".TMD",".opt", NullS};
|
||||||
static TYPELIB deletable_extentions=
|
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[]=
|
const char *known_exts[]=
|
||||||
{".ISM",".ISD",".ISM",".MRG",".MYI",".MYD",".db", ".ibd", NullS};
|
{".ISM",".ISD",".ISM",".MRG",".MYI",".MYD",".db", ".ibd", NullS};
|
||||||
static TYPELIB known_extentions=
|
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,
|
static long mysql_rm_known_files(THD *thd, MY_DIR *dirp,
|
||||||
const char *db, const char *path,
|
const char *db, const char *path,
|
||||||
|
@ -4090,6 +4090,7 @@ bool mysql_test_parse_for_slave(THD *thd, char *inBuf, uint length)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
** Store field definition for create
|
** Store field definition for create
|
||||||
** Return 0 if ok
|
** 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->pack_length=8;
|
||||||
new_field->interval=interval;
|
new_field->interval=interval;
|
||||||
new_field->length=0;
|
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;
|
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);
|
length= cs->cset->numchars(cs, *pos, *pos+length);
|
||||||
new_field->length+= 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->interval=interval;
|
||||||
new_field->pack_length=interval->count < 256 ? 1 : 2; // Should be safe
|
new_field->pack_length=interval->count < 256 ? 1 : 2; // Should be safe
|
||||||
new_field->length=(uint) strip_sp((char*) interval->type_names[0]);
|
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;
|
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);
|
length= cs->cset->numchars(cs, *pos, *pos+length);
|
||||||
set_if_bigger(new_field->length,length);
|
set_if_bigger(new_field->length,length);
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ static const char *grant_names[]={
|
|||||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||||
static TYPELIB grant_types = { sizeof(grant_names)/sizeof(char **),
|
static TYPELIB grant_types = { sizeof(grant_names)/sizeof(char **),
|
||||||
"grant_types",
|
"grant_types",
|
||||||
grant_names};
|
grant_names, NULL};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int
|
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
|
Check if the first word in a string is one of the ones in TYPELIB
|
||||||
|
|
||||||
|
31
sql/table.cc
31
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->fieldnames,1,&names);
|
||||||
fix_type_pointers(&int_array,outparam->intervals,interval_count,
|
fix_type_pointers(&int_array,outparam->intervals,interval_count,
|
||||||
&names);
|
&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)
|
if (keynames)
|
||||||
fix_type_pointers(&int_array,&outparam->keynames,1,&keynames);
|
fix_type_pointers(&int_array,&outparam->keynames,1,&keynames);
|
||||||
VOID(my_close(file,MYF(MY_WME)));
|
VOID(my_close(file,MYF(MY_WME)));
|
||||||
@ -1007,14 +1025,19 @@ TYPELIB *typelib(List<String> &strings)
|
|||||||
return 0;
|
return 0;
|
||||||
result->count=strings.elements;
|
result->count=strings.elements;
|
||||||
result->name="";
|
result->name="";
|
||||||
if (!(result->type_names=(const char **) sql_alloc(sizeof(char *)*
|
uint nbytes= (sizeof(char*) + sizeof(uint)) * (result->count + 1);
|
||||||
(result->count+1))))
|
if (!(result->type_names= (const char**) sql_alloc(nbytes)))
|
||||||
return 0;
|
return 0;
|
||||||
|
result->type_lengths= (uint*) (result->type_names + result->count + 1);
|
||||||
List_iterator<String> it(strings);
|
List_iterator<String> it(strings);
|
||||||
String *tmp;
|
String *tmp;
|
||||||
for (uint i=0; (tmp=it++) ; i++)
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user