Commit 34e882dd authored by unknown's avatar unknown

CAST(expr AS CHAR(10)) is now working

parent 8359a2c7
......@@ -42,6 +42,60 @@ t1 CREATE TABLE `t1` (
`t` char(4) character set cp1251 NOT NULL default ''
) TYPE=MyISAM CHARSET=latin1
drop table t1;
select
cast(_latin1'ab' AS char) as c1,
cast(_latin1'a ' AS char) as c2,
cast(_latin1'abc' AS char(2)) as c3,
cast(_latin1'a ' AS char(2)) as c4,
cast(_latin1'a' AS char(2)) as c5;
c1 c2 c3 c4 c5
ab a ab a a
create table t1 select
cast(_latin1'ab' AS char) as c1,
cast(_latin1'a ' AS char) as c2,
cast(_latin1'abc' AS char(2)) as c3,
cast(_latin1'a ' AS char(2)) as c4,
cast(_latin1'a' AS char(2)) as c5;
select * from t1;
c1 c2 c3 c4 c5
ab a ab a a
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` char(2) binary NOT NULL default '',
`c2` char(2) binary NOT NULL default '',
`c3` char(2) binary NOT NULL default '',
`c4` char(2) binary NOT NULL default '',
`c5` char(2) binary NOT NULL default ''
) TYPE=MyISAM CHARSET=latin1
drop table t1;
select
cast(_koi8r'' AS nchar) as c1,
cast(_koi8r' ' AS nchar) as c2,
cast(_koi8r'' AS nchar(2)) as c3,
cast(_koi8r' ' AS nchar(2)) as c4,
cast(_koi8r'' AS nchar(2)) as c5;
c1 c2 c3 c4 c5
фг ф фг ф ф
create table t1 select
cast(_koi8r'' AS nchar) as c1,
cast(_koi8r' ' AS nchar) as c2,
cast(_koi8r'' AS nchar(2)) as c3,
cast(_koi8r' ' AS nchar(2)) as c4,
cast(_koi8r'' AS nchar(2)) as c5;
select * from t1;
c1 c2 c3 c4 c5
фг ф фг ф ф
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` char(2) character set utf8 NOT NULL default '',
`c2` char(2) character set utf8 NOT NULL default '',
`c3` char(2) character set utf8 NOT NULL default '',
`c4` char(2) character set utf8 NOT NULL default '',
`c5` char(2) character set utf8 NOT NULL default ''
) TYPE=MyISAM CHARSET=latin1
drop table t1;
select cast("2001-1-1" as date) = "2001-01-01";
cast("2001-1-1" as date) = "2001-01-01"
1
......
......@@ -23,6 +23,47 @@ create table t1 select cast(_koi8r'
show create table t1;
drop table t1;
#
# CAST to CHAR with/without length
#
select
cast(_latin1'ab' AS char) as c1,
cast(_latin1'a ' AS char) as c2,
cast(_latin1'abc' AS char(2)) as c3,
cast(_latin1'a ' AS char(2)) as c4,
cast(_latin1'a' AS char(2)) as c5;
create table t1 select
cast(_latin1'ab' AS char) as c1,
cast(_latin1'a ' AS char) as c2,
cast(_latin1'abc' AS char(2)) as c3,
cast(_latin1'a ' AS char(2)) as c4,
cast(_latin1'a' AS char(2)) as c5;
select * from t1;
show create table t1;
drop table t1;
#
# CAST to NCHAR with/without length
#
select
cast(_koi8r'' AS nchar) as c1,
cast(_koi8r' ' AS nchar) as c2,
cast(_koi8r'' AS nchar(2)) as c3,
cast(_koi8r' ' AS nchar(2)) as c4,
cast(_koi8r'' AS nchar(2)) as c5;
create table t1 select
cast(_koi8r'' AS nchar) as c1,
cast(_koi8r' ' AS nchar) as c2,
cast(_koi8r'' AS nchar(2)) as c3,
cast(_koi8r' ' AS nchar(2)) as c4,
cast(_koi8r'' AS nchar(2)) as c5;
select * from t1;
show create table t1;
drop table t1;
#
# The following should be fixed in 4.1
#
......
......@@ -470,21 +470,21 @@ Item *create_load_file(Item* a)
}
Item *create_func_cast(Item *a, Cast_target cast_type, CHARSET_INFO *cs)
Item *create_func_cast(Item *a, Cast_target cast_type, int len, CHARSET_INFO *cs)
{
Item *res;
LINT_INIT(res);
switch (cast_type) {
case ITEM_CAST_BINARY: res= new Item_func_binary(a); break;
case ITEM_CAST_CHAR:
res= (cs == NULL) ? (Item*) new Item_char_typecast(a) :
(Item*) new Item_func_conv_charset(a,cs);
break;
case ITEM_CAST_SIGNED_INT: res= new Item_func_signed(a); break;
case ITEM_CAST_UNSIGNED_INT: res= new Item_func_unsigned(a); break;
case ITEM_CAST_DATE: res= new Item_date_typecast(a); break;
case ITEM_CAST_TIME: res= new Item_time_typecast(a); break;
case ITEM_CAST_DATETIME: res= new Item_datetime_typecast(a); break;
case ITEM_CAST_CHAR:
res= new Item_char_typecast(a, len, cs ? cs :
current_thd->variables.collation_connection);
break;
}
return res;
}
......
......@@ -28,7 +28,7 @@ Item *create_func_bit_length(Item* a);
Item *create_func_coercibility(Item* a);
Item *create_func_ceiling(Item* a);
Item *create_func_char_length(Item* a);
Item *create_func_cast(Item *a, Cast_target cast_type, CHARSET_INFO *cs);
Item *create_func_cast(Item *a, Cast_target cast_type, int len, CHARSET_INFO *cs);
Item *create_func_connection_id(void);
Item *create_func_conv(Item* a, Item *b, Item *c);
Item *create_func_cos(Item* a);
......
......@@ -1474,6 +1474,59 @@ void Item_typecast::print(String *str)
str->append(')');
}
String *Item_char_typecast::val_str(String *str)
{
String *res, *res1;
uint32 length;
if (!charset_conversion && !(res= args[0]->val_str(str)))
{
null_value= 1;
return 0;
}
else
{
// Convert character set if differ
if (!(res1= args[0]->val_str(&tmp_value)) ||
str->copy(res1->ptr(), res1->length(),res1->charset(), cast_cs))
{
null_value= 1;
return 0;
}
res= str;
}
/*
Cut the tail if cast with length
and the result is longer than cast length, e.g.
CAST('string' AS CHAR(1))
*/
if (cast_length >= 0 &&
(res->length() > (length= (uint32) res->charpos(cast_length))))
{ // Safe even if const arg
if (!res->alloced_length())
{ // Don't change const str
str_value= *res; // Not malloced string
res= &str_value;
}
res->length((uint) length);
}
null_value= 0;
return res;
}
void Item_char_typecast::fix_length_and_dec()
{
uint32 char_length;
charset_conversion= !my_charset_same(args[0]->collation.collation, cast_cs) &&
args[0]->collation.collation != &my_charset_bin &&
cast_cs != &my_charset_bin;
collation.set(cast_cs, DERIVATION_IMPLICIT);
char_length= (cast_length >= 0) ? cast_length :
args[0]->max_length/args[0]->collation.collation->mbmaxlen;
max_length= char_length * cast_cs->mbmaxlen;
}
String *Item_datetime_typecast::val_str(String *str)
{
TIME ltime;
......
......@@ -614,13 +614,15 @@ class Item_typecast :public Item_str_func
class Item_char_typecast :public Item_typecast
{
public:
Item_char_typecast(Item *a) :Item_typecast(a) {}
void fix_length_and_dec()
{
collation.set(default_charset());
max_length=args[0]->max_length;
}
int cast_length;
CHARSET_INFO *cast_cs;
bool charset_conversion;
String tmp_value;
public:
Item_char_typecast(Item *a, int length_arg, CHARSET_INFO *cs_arg)
:Item_typecast(a), cast_length(length_arg), cast_cs(cs_arg) {}
String *val_str(String *a);
void fix_length_and_dec();
};
......
......@@ -642,7 +642,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%type <ha_rkey_mode> handler_rkey_mode
%type <cast_type> cast_type
%type <cast_type> cast_type cast_type_finalize
%type <udf_type> udf_func_type
......@@ -2355,11 +2355,19 @@ simple_expr:
6, &my_charset_latin1));
}
| CAST_SYM '(' expr AS cast_type ')'
{ $$= create_func_cast($3, $5, Lex->charset); }
{
$$= create_func_cast($3, $5,
Lex->length ? atoi(Lex->length) : -1,
Lex->charset);
}
| CASE_SYM opt_expr WHEN_SYM when_list opt_else END
{ $$= new Item_func_case(* $4, $2, $5 ); }
| CONVERT_SYM '(' expr ',' cast_type ')'
{ $$= create_func_cast($3, $5, Lex->charset); }
{
$$= create_func_cast($3, $5,
Lex->length ? atoi(Lex->length) : -1,
Lex->charset);
}
| CONVERT_SYM '(' expr USING charset_name ')'
{ $$= new Item_func_conv_charset($3,$5); }
| CONVERT_SYM '(' expr ',' expr ',' expr ')'
......@@ -2800,16 +2808,25 @@ in_sum_expr:
$$= $3;
};
cast_type_init:
{ Lex->charset= NULL; Lex->length= (char*)0; }
;
cast_type_finalize:
BINARY { $$=ITEM_CAST_BINARY; }
| CHAR_SYM opt_len opt_binary { $$=ITEM_CAST_CHAR; }
| NCHAR_SYM opt_len { $$=ITEM_CAST_CHAR; Lex->charset= national_charset_info; }
| SIGNED_SYM { $$=ITEM_CAST_SIGNED_INT; }
| SIGNED_SYM INT_SYM { $$=ITEM_CAST_SIGNED_INT; }
| UNSIGNED { $$=ITEM_CAST_UNSIGNED_INT; }
| UNSIGNED INT_SYM { $$=ITEM_CAST_UNSIGNED_INT; }
| DATE_SYM { $$=ITEM_CAST_DATE; }
| TIME_SYM { $$=ITEM_CAST_TIME; }
| DATETIME { $$=ITEM_CAST_DATETIME; }
;
cast_type:
BINARY { $$=ITEM_CAST_BINARY; Lex->charset= NULL; }
| CHAR_SYM opt_binary { $$=ITEM_CAST_CHAR; }
| SIGNED_SYM { $$=ITEM_CAST_SIGNED_INT; Lex->charset= NULL; }
| SIGNED_SYM INT_SYM { $$=ITEM_CAST_SIGNED_INT; Lex->charset= NULL; }
| UNSIGNED { $$=ITEM_CAST_UNSIGNED_INT; Lex->charset= NULL; }
| UNSIGNED INT_SYM { $$=ITEM_CAST_UNSIGNED_INT; Lex->charset= NULL; }
| DATE_SYM { $$=ITEM_CAST_DATE; Lex->charset= NULL; }
| TIME_SYM { $$=ITEM_CAST_TIME; Lex->charset= NULL; }
| DATETIME { $$=ITEM_CAST_DATETIME; Lex->charset= NULL; }
cast_type_init cast_type_finalize { $$= $2; }
;
expr_list:
......
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