summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <bar@mysql.com>2004-10-25 17:51:26 +0500
committerunknown <bar@mysql.com>2004-10-25 17:51:26 +0500
commit712326d6846ae718bf5c7c5961ec3173bbf29b06 (patch)
tree7a9462068baaf8b0e98b30d9e65951269bac98e5
parent7df41480849074ad0b1a907d244b5d3b41403f32 (diff)
downloadmariadb-git-712326d6846ae718bf5c7c5961ec3173bbf29b06.tar.gz
Bug#6202: ENUMs are not case sensitive even if declared BINARY
-rw-r--r--include/typelib.h1
-rw-r--r--mysql-test/r/type_enum.result18
-rw-r--r--mysql-test/t/type_enum.test13
-rw-r--r--sql/field.cc2
-rw-r--r--sql/ha_berkeley.cc2
-rw-r--r--sql/ha_myisam.cc2
-rw-r--r--sql/handler.cc2
-rw-r--r--sql/item_timefunc.cc4
-rw-r--r--sql/mysql_priv.h1
-rw-r--r--sql/mysqld.cc2
-rw-r--r--sql/repl_failsafe.cc4
-rw-r--r--sql/set_var.cc5
-rw-r--r--sql/sql_cache.cc2
-rw-r--r--sql/sql_db.cc4
-rw-r--r--sql/sql_parse.cc18
-rw-r--r--sql/sql_show.cc2
-rw-r--r--sql/strfunc.cc41
-rw-r--r--sql/table.cc31
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;
}