diff options
author | bar@gw.udmsearch.izhnet.ru <> | 2002-03-29 18:22:21 +0400 |
---|---|---|
committer | bar@gw.udmsearch.izhnet.ru <> | 2002-03-29 18:22:21 +0400 |
commit | ae03ccc40399d01fd78a5bf393b92dbfcdf1951e (patch) | |
tree | f912fbb72c2b725603729c02d6079e5fd0474608 | |
parent | 0300bac68a5ab9c5b00d6fe59a1f9872297a0de3 (diff) | |
download | mariadb-git-ae03ccc40399d01fd78a5bf393b92dbfcdf1951e.tar.gz |
Charset convertion operator CONVERT( string USING charset)
-rw-r--r-- | sql/item_strfunc.cc | 67 | ||||
-rw-r--r-- | sql/item_strfunc.h | 13 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 10 |
3 files changed, 90 insertions, 0 deletions
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index cfbfda97148..90f27148578 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1776,6 +1776,73 @@ String *Item_func_conv::val_str(String *str) } +String *Item_func_conv_charset::val_str(String *str) +{ + my_wc_t wc; + int cnvres; + const uchar *s, *se; + uchar *d, *d0, *de; + uint dmaxlen; + String *arg= args[0]->val_str(str); + CHARSET_INFO *from,*to; + + if (!arg) + { + null_value=1; + return 0; + } + + from=arg->charset(); + to=conv_charset; + + s=(const uchar*)arg->ptr(); + se=s+arg->length(); + + dmaxlen=arg->length()*(conv_charset->mbmaxlen?conv_charset->mbmaxlen:1)+1; + str->alloc(dmaxlen); + d0=d=(unsigned char*)str->ptr(); + de=d+dmaxlen; + + while( s < se && d < de){ + + cnvres=from->mb_wc(from,&wc,s,se); + if (cnvres>0) + { + s+=cnvres; + } + else if (cnvres==MY_CS_ILSEQ) + { + s++; + wc='?'; + } + else + break; + +outp: + cnvres=to->wc_mb(to,wc,d,de); + if (cnvres>0) + { + d+=cnvres; + } + else if (cnvres==MY_CS_ILUNI && wc!='?') + { + wc='?'; + goto outp; + } + else + break; + }; + + str->length((uint) (d-d0)); + str->set_charset(to); + return str; +} + +void Item_func_conv_charset::fix_length_and_dec() +{ + /* BAR TODO: What to do here??? */ +} + String *Item_func_hex::val_str(String *str) { if (args[0]->result_type() != STRING_RESULT) diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index a8768e62f98..5dcf24cfef6 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -476,6 +476,19 @@ public: void fix_length_and_dec() { decimals = 0; max_length=3*8+7; } }; +class Item_func_conv_charset :public Item_str_func +{ + CHARSET_INFO *conv_charset; +public: + Item_func_conv_charset(Item *a, CHARSET_INFO *cs) :Item_str_func(a) + { + conv_charset=cs; + } + String *val_str(String *); + void fix_length_and_dec(); + const char *func_name() const { return "conv_charset"; } +}; + /******************************************************* Spatial functions diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index ee31e726eb1..9ca5b44aa64 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1654,6 +1654,16 @@ simple_expr: | 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); } + | CONVERT_SYM '(' expr USING IDENT ')' + { + CHARSET_INFO *cs=find_compiled_charset_by_name($5.str); + if (!cs) + { + net_printf(¤t_thd->net,ER_UNKNOWN_CHARACTER_SET,$5); + YYABORT; + } + $$= new Item_func_conv_charset($3,cs); + } | FUNC_ARG0 '(' ')' { $$= ((Item*(*)(void))($1.symbol->create_func))();} | FUNC_ARG1 '(' expr ')' |