Bug#37575 UCASE fails on monthname
The MONTHNAME/DAYNAME functions returns binary string, so the LOWER/UPPER functions are not effective on the result of MONTHNAME/DAYNAME call. Character set of the MONTHNAME/DAYNAME function result has been changed to connection character set.
This commit is contained in:
parent
6147201a17
commit
26e804d0a7
@ -445,6 +445,7 @@ my_bool my_propagate_complex(CHARSET_INFO *cs, const uchar *str, uint len);
|
|||||||
uint my_string_repertoire(CHARSET_INFO *cs, const char *str, ulong len);
|
uint my_string_repertoire(CHARSET_INFO *cs, const char *str, ulong len);
|
||||||
my_bool my_charset_is_ascii_based(CHARSET_INFO *cs);
|
my_bool my_charset_is_ascii_based(CHARSET_INFO *cs);
|
||||||
my_bool my_charset_is_8bit_pure_ascii(CHARSET_INFO *cs);
|
my_bool my_charset_is_8bit_pure_ascii(CHARSET_INFO *cs);
|
||||||
|
uint my_charset_repertoire(CHARSET_INFO *cs);
|
||||||
|
|
||||||
|
|
||||||
#define _MY_U 01 /* Upper case */
|
#define _MY_U 01 /* Upper case */
|
||||||
|
@ -1111,4 +1111,57 @@ set names latin1;
|
|||||||
select hex(char(0x41 using ucs2));
|
select hex(char(0x41 using ucs2));
|
||||||
hex(char(0x41 using ucs2))
|
hex(char(0x41 using ucs2))
|
||||||
0041
|
0041
|
||||||
|
SET character_set_connection=ucs2;
|
||||||
|
SELECT CHARSET(DAYNAME(19700101));
|
||||||
|
CHARSET(DAYNAME(19700101))
|
||||||
|
ucs2
|
||||||
|
SELECT CHARSET(MONTHNAME(19700101));
|
||||||
|
CHARSET(MONTHNAME(19700101))
|
||||||
|
ucs2
|
||||||
|
SELECT LOWER(DAYNAME(19700101));
|
||||||
|
LOWER(DAYNAME(19700101))
|
||||||
|
thursday
|
||||||
|
SELECT LOWER(MONTHNAME(19700101));
|
||||||
|
LOWER(MONTHNAME(19700101))
|
||||||
|
january
|
||||||
|
SELECT UPPER(DAYNAME(19700101));
|
||||||
|
UPPER(DAYNAME(19700101))
|
||||||
|
THURSDAY
|
||||||
|
SELECT UPPER(MONTHNAME(19700101));
|
||||||
|
UPPER(MONTHNAME(19700101))
|
||||||
|
JANUARY
|
||||||
|
SELECT HEX(MONTHNAME(19700101));
|
||||||
|
HEX(MONTHNAME(19700101))
|
||||||
|
004A0061006E0075006100720079
|
||||||
|
SELECT HEX(DAYNAME(19700101));
|
||||||
|
HEX(DAYNAME(19700101))
|
||||||
|
00540068007500720073006400610079
|
||||||
|
SET LC_TIME_NAMES=ru_RU;
|
||||||
|
SET NAMES utf8;
|
||||||
|
SET character_set_connection=ucs2;
|
||||||
|
SELECT CHARSET(DAYNAME(19700101));
|
||||||
|
CHARSET(DAYNAME(19700101))
|
||||||
|
ucs2
|
||||||
|
SELECT CHARSET(MONTHNAME(19700101));
|
||||||
|
CHARSET(MONTHNAME(19700101))
|
||||||
|
ucs2
|
||||||
|
SELECT LOWER(DAYNAME(19700101));
|
||||||
|
LOWER(DAYNAME(19700101))
|
||||||
|
четверг
|
||||||
|
SELECT LOWER(MONTHNAME(19700101));
|
||||||
|
LOWER(MONTHNAME(19700101))
|
||||||
|
января
|
||||||
|
SELECT UPPER(DAYNAME(19700101));
|
||||||
|
UPPER(DAYNAME(19700101))
|
||||||
|
ЧЕТВЕРГ
|
||||||
|
SELECT UPPER(MONTHNAME(19700101));
|
||||||
|
UPPER(MONTHNAME(19700101))
|
||||||
|
ЯНВАРЯ
|
||||||
|
SELECT HEX(MONTHNAME(19700101));
|
||||||
|
HEX(MONTHNAME(19700101))
|
||||||
|
042F043D043204300440044F
|
||||||
|
SELECT HEX(DAYNAME(19700101));
|
||||||
|
HEX(DAYNAME(19700101))
|
||||||
|
0427043504420432043504400433
|
||||||
|
SET character_set_connection=latin1;
|
||||||
End of 5.0 tests
|
End of 5.0 tests
|
||||||
|
@ -592,6 +592,21 @@ unix_timestamp('1970-01-01 03:00:01')
|
|||||||
select unix_timestamp('2038-01-19 07:14:07');
|
select unix_timestamp('2038-01-19 07:14:07');
|
||||||
unix_timestamp('2038-01-19 07:14:07')
|
unix_timestamp('2038-01-19 07:14:07')
|
||||||
0
|
0
|
||||||
|
SELECT CHARSET(DAYNAME(19700101));
|
||||||
|
CHARSET(DAYNAME(19700101))
|
||||||
|
latin1
|
||||||
|
SELECT CHARSET(MONTHNAME(19700101));
|
||||||
|
CHARSET(MONTHNAME(19700101))
|
||||||
|
latin1
|
||||||
|
SELECT LOWER(DAYNAME(19700101));
|
||||||
|
LOWER(DAYNAME(19700101))
|
||||||
|
thursday
|
||||||
|
SELECT LOWER(MONTHNAME(19700101));
|
||||||
|
LOWER(MONTHNAME(19700101))
|
||||||
|
january
|
||||||
|
SELECT COERCIBILITY(MONTHNAME('1970-01-01')),COERCIBILITY(DAYNAME('1970-01-01'));
|
||||||
|
COERCIBILITY(MONTHNAME('1970-01-01')) COERCIBILITY(DAYNAME('1970-01-01'))
|
||||||
|
4 4
|
||||||
CREATE TABLE t1 (datetime datetime, timestamp timestamp, date date, time time);
|
CREATE TABLE t1 (datetime datetime, timestamp timestamp, date date, time time);
|
||||||
INSERT INTO t1 values ("2001-01-02 03:04:05", "2002-01-02 03:04:05", "2003-01-02", "06:07:08");
|
INSERT INTO t1 values ("2001-01-02 03:04:05", "2002-01-02 03:04:05", "2003-01-02", "06:07:08");
|
||||||
SELECT * from t1;
|
SELECT * from t1;
|
||||||
|
@ -685,4 +685,29 @@ set names latin1;
|
|||||||
#
|
#
|
||||||
select hex(char(0x41 using ucs2));
|
select hex(char(0x41 using ucs2));
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug#37575: UCASE fails on monthname
|
||||||
|
#
|
||||||
|
SET character_set_connection=ucs2;
|
||||||
|
SELECT CHARSET(DAYNAME(19700101));
|
||||||
|
SELECT CHARSET(MONTHNAME(19700101));
|
||||||
|
SELECT LOWER(DAYNAME(19700101));
|
||||||
|
SELECT LOWER(MONTHNAME(19700101));
|
||||||
|
SELECT UPPER(DAYNAME(19700101));
|
||||||
|
SELECT UPPER(MONTHNAME(19700101));
|
||||||
|
SELECT HEX(MONTHNAME(19700101));
|
||||||
|
SELECT HEX(DAYNAME(19700101));
|
||||||
|
SET LC_TIME_NAMES=ru_RU;
|
||||||
|
SET NAMES utf8;
|
||||||
|
SET character_set_connection=ucs2;
|
||||||
|
SELECT CHARSET(DAYNAME(19700101));
|
||||||
|
SELECT CHARSET(MONTHNAME(19700101));
|
||||||
|
SELECT LOWER(DAYNAME(19700101));
|
||||||
|
SELECT LOWER(MONTHNAME(19700101));
|
||||||
|
SELECT UPPER(DAYNAME(19700101));
|
||||||
|
SELECT UPPER(MONTHNAME(19700101));
|
||||||
|
SELECT HEX(MONTHNAME(19700101));
|
||||||
|
SELECT HEX(DAYNAME(19700101));
|
||||||
|
SET character_set_connection=latin1;
|
||||||
|
|
||||||
--echo End of 5.0 tests
|
--echo End of 5.0 tests
|
||||||
|
@ -304,6 +304,15 @@ select unix_timestamp('1970-01-01 03:00:01');
|
|||||||
# check bad date, close to the boundary (we cut them off in the very end)
|
# check bad date, close to the boundary (we cut them off in the very end)
|
||||||
select unix_timestamp('2038-01-19 07:14:07');
|
select unix_timestamp('2038-01-19 07:14:07');
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug #28759: DAYNAME() and MONTHNAME() return binary string
|
||||||
|
#
|
||||||
|
|
||||||
|
SELECT CHARSET(DAYNAME(19700101));
|
||||||
|
SELECT CHARSET(MONTHNAME(19700101));
|
||||||
|
SELECT LOWER(DAYNAME(19700101));
|
||||||
|
SELECT LOWER(MONTHNAME(19700101));
|
||||||
|
SELECT COERCIBILITY(MONTHNAME('1970-01-01')),COERCIBILITY(DAYNAME('1970-01-01'));
|
||||||
|
|
||||||
#
|
#
|
||||||
# Test types from + INTERVAL
|
# Test types from + INTERVAL
|
||||||
|
@ -1036,12 +1036,25 @@ longlong Item_func_month::val_int()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Item_func_monthname::fix_length_and_dec()
|
||||||
|
{
|
||||||
|
THD* thd= current_thd;
|
||||||
|
CHARSET_INFO *cs= thd->variables.collation_connection;
|
||||||
|
uint32 repertoire= my_charset_repertoire(cs);
|
||||||
|
locale= thd->variables.lc_time_names;
|
||||||
|
collation.set(cs, DERIVATION_COERCIBLE, repertoire);
|
||||||
|
decimals=0;
|
||||||
|
max_length= locale->max_month_name_length * collation.collation->mbmaxlen;
|
||||||
|
maybe_null=1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
String* Item_func_monthname::val_str(String* str)
|
String* Item_func_monthname::val_str(String* str)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
const char *month_name;
|
const char *month_name;
|
||||||
uint month= (uint) val_int();
|
uint month= (uint) val_int();
|
||||||
THD *thd= current_thd;
|
uint err;
|
||||||
|
|
||||||
if (null_value || !month)
|
if (null_value || !month)
|
||||||
{
|
{
|
||||||
@ -1049,8 +1062,9 @@ String* Item_func_monthname::val_str(String* str)
|
|||||||
return (String*) 0;
|
return (String*) 0;
|
||||||
}
|
}
|
||||||
null_value=0;
|
null_value=0;
|
||||||
month_name= thd->variables.lc_time_names->month_names->type_names[month-1];
|
month_name= locale->month_names->type_names[month-1];
|
||||||
str->set(month_name, strlen(month_name), system_charset_info);
|
str->copy(month_name, strlen(month_name), &my_charset_utf8_bin,
|
||||||
|
collation.collation, &err);
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1169,19 +1183,32 @@ longlong Item_func_weekday::val_int()
|
|||||||
odbc_type) + test(odbc_type);
|
odbc_type) + test(odbc_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Item_func_dayname::fix_length_and_dec()
|
||||||
|
{
|
||||||
|
THD* thd= current_thd;
|
||||||
|
CHARSET_INFO *cs= thd->variables.collation_connection;
|
||||||
|
uint32 repertoire= my_charset_repertoire(cs);
|
||||||
|
locale= thd->variables.lc_time_names;
|
||||||
|
collation.set(cs, DERIVATION_COERCIBLE, repertoire);
|
||||||
|
decimals=0;
|
||||||
|
max_length= locale->max_day_name_length * collation.collation->mbmaxlen;
|
||||||
|
maybe_null=1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
String* Item_func_dayname::val_str(String* str)
|
String* Item_func_dayname::val_str(String* str)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
uint weekday=(uint) val_int(); // Always Item_func_daynr()
|
uint weekday=(uint) val_int(); // Always Item_func_daynr()
|
||||||
const char *day_name;
|
const char *day_name;
|
||||||
THD *thd= current_thd;
|
uint err;
|
||||||
|
|
||||||
if (null_value)
|
if (null_value)
|
||||||
return (String*) 0;
|
return (String*) 0;
|
||||||
|
|
||||||
day_name= thd->variables.lc_time_names->day_names->type_names[weekday];
|
day_name= locale->day_names->type_names[weekday];
|
||||||
str->set(day_name, strlen(day_name), system_charset_info);
|
str->copy(day_name, strlen(day_name), &my_charset_utf8_bin,
|
||||||
|
collation.collation, &err);
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,18 +108,13 @@ public:
|
|||||||
|
|
||||||
class Item_func_monthname :public Item_func_month
|
class Item_func_monthname :public Item_func_month
|
||||||
{
|
{
|
||||||
|
MY_LOCALE *locale;
|
||||||
public:
|
public:
|
||||||
Item_func_monthname(Item *a) :Item_func_month(a) {}
|
Item_func_monthname(Item *a) :Item_func_month(a) {}
|
||||||
const char *func_name() const { return "monthname"; }
|
const char *func_name() const { return "monthname"; }
|
||||||
String *val_str(String *str);
|
String *val_str(String *str);
|
||||||
enum Item_result result_type () const { return STRING_RESULT; }
|
enum Item_result result_type () const { return STRING_RESULT; }
|
||||||
void fix_length_and_dec()
|
void fix_length_and_dec();
|
||||||
{
|
|
||||||
collation.set(&my_charset_bin);
|
|
||||||
decimals=0;
|
|
||||||
max_length=10*my_charset_bin.mbmaxlen;
|
|
||||||
maybe_null=1;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -272,18 +267,13 @@ public:
|
|||||||
|
|
||||||
class Item_func_dayname :public Item_func_weekday
|
class Item_func_dayname :public Item_func_weekday
|
||||||
{
|
{
|
||||||
|
MY_LOCALE *locale;
|
||||||
public:
|
public:
|
||||||
Item_func_dayname(Item *a) :Item_func_weekday(a,0) {}
|
Item_func_dayname(Item *a) :Item_func_weekday(a,0) {}
|
||||||
const char *func_name() const { return "dayname"; }
|
const char *func_name() const { return "dayname"; }
|
||||||
String *val_str(String *str);
|
String *val_str(String *str);
|
||||||
enum Item_result result_type () const { return STRING_RESULT; }
|
enum Item_result result_type () const { return STRING_RESULT; }
|
||||||
void fix_length_and_dec()
|
void fix_length_and_dec();
|
||||||
{
|
|
||||||
collation.set(&my_charset_bin);
|
|
||||||
decimals=0;
|
|
||||||
max_length=9*MY_CHARSET_BIN_MB_MAXLEN;
|
|
||||||
maybe_null=1;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -132,15 +132,20 @@ typedef struct my_locale_st
|
|||||||
TYPELIB *ab_month_names;
|
TYPELIB *ab_month_names;
|
||||||
TYPELIB *day_names;
|
TYPELIB *day_names;
|
||||||
TYPELIB *ab_day_names;
|
TYPELIB *ab_day_names;
|
||||||
|
uint max_month_name_length;
|
||||||
|
uint max_day_name_length;
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
my_locale_st(uint number_par,
|
my_locale_st(uint number_par,
|
||||||
const char *name_par, const char *descr_par, bool is_ascii_par,
|
const char *name_par, const char *descr_par, bool is_ascii_par,
|
||||||
TYPELIB *month_names_par, TYPELIB *ab_month_names_par,
|
TYPELIB *month_names_par, TYPELIB *ab_month_names_par,
|
||||||
TYPELIB *day_names_par, TYPELIB *ab_day_names_par) :
|
TYPELIB *day_names_par, TYPELIB *ab_day_names_par,
|
||||||
|
uint max_month_name_length_par, uint max_day_name_length_par) :
|
||||||
number(number_par),
|
number(number_par),
|
||||||
name(name_par), description(descr_par), is_ascii(is_ascii_par),
|
name(name_par), description(descr_par), is_ascii(is_ascii_par),
|
||||||
month_names(month_names_par), ab_month_names(ab_month_names_par),
|
month_names(month_names_par), ab_month_names(ab_month_names_par),
|
||||||
day_names(day_names_par), ab_day_names(ab_day_names_par)
|
day_names(day_names_par), ab_day_names(ab_day_names_par),
|
||||||
|
max_month_name_length(max_month_name_length_par),
|
||||||
|
max_day_name_length(max_day_name_length_par)
|
||||||
{}
|
{}
|
||||||
#endif
|
#endif
|
||||||
} MY_LOCALE;
|
} MY_LOCALE;
|
||||||
|
@ -3616,6 +3616,44 @@ void decrement_handler_count()
|
|||||||
#endif /* defined(__NT__) || defined(HAVE_SMEM) */
|
#endif /* defined(__NT__) || defined(HAVE_SMEM) */
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef DBUG_OFF
|
||||||
|
/*
|
||||||
|
Debugging helper function to keep the locale database
|
||||||
|
(see sql_locale.cc) and max_month_name_length and
|
||||||
|
max_day_name_length variable values in consistent state.
|
||||||
|
*/
|
||||||
|
static void test_lc_time_sz()
|
||||||
|
{
|
||||||
|
DBUG_ENTER("test_lc_time_sz");
|
||||||
|
for (MY_LOCALE **loc= my_locales; *loc; loc++)
|
||||||
|
{
|
||||||
|
uint max_month_len= 0;
|
||||||
|
uint max_day_len = 0;
|
||||||
|
for (const char **month= (*loc)->month_names->type_names; *month; month++)
|
||||||
|
{
|
||||||
|
set_if_bigger(max_month_len,
|
||||||
|
my_numchars_mb(&my_charset_utf8_general_ci,
|
||||||
|
*month, *month + strlen(*month)));
|
||||||
|
}
|
||||||
|
for (const char **day= (*loc)->day_names->type_names; *day; day++)
|
||||||
|
{
|
||||||
|
set_if_bigger(max_day_len,
|
||||||
|
my_numchars_mb(&my_charset_utf8_general_ci,
|
||||||
|
*day, *day + strlen(*day)));
|
||||||
|
}
|
||||||
|
if ((*loc)->max_month_name_length != max_month_len ||
|
||||||
|
(*loc)->max_day_name_length != max_day_len)
|
||||||
|
{
|
||||||
|
DBUG_PRINT("Wrong max day name(or month name) length for locale:",
|
||||||
|
("%s", (*loc)->name));
|
||||||
|
DBUG_ASSERT(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
}
|
||||||
|
#endif//DBUG_OFF
|
||||||
|
|
||||||
|
|
||||||
#ifndef EMBEDDED_LIBRARY
|
#ifndef EMBEDDED_LIBRARY
|
||||||
#ifdef __WIN__
|
#ifdef __WIN__
|
||||||
int win_main(int argc, char **argv)
|
int win_main(int argc, char **argv)
|
||||||
@ -3712,6 +3750,10 @@ int main(int argc, char **argv)
|
|||||||
openlog(libwrapName, LOG_PID, LOG_AUTH);
|
openlog(libwrapName, LOG_PID, LOG_AUTH);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef DBUG_OFF
|
||||||
|
test_lc_time_sz();
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We have enough space for fiddling with the argv, continue
|
We have enough space for fiddling with the argv, continue
|
||||||
*/
|
*/
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -337,6 +337,16 @@ my_string_repertoire(CHARSET_INFO *cs, const char *str, ulong length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Returns repertoire for charset
|
||||||
|
*/
|
||||||
|
uint my_charset_repertoire(CHARSET_INFO *cs)
|
||||||
|
{
|
||||||
|
return cs->state & MY_CS_PUREASCII ?
|
||||||
|
MY_REPERTOIRE_ASCII : MY_REPERTOIRE_UNICODE30;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Detect whether a character set is ASCII compatible.
|
Detect whether a character set is ASCII compatible.
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user