summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbar@gw.udmsearch.izhnet.ru <>2002-03-29 18:22:21 +0400
committerbar@gw.udmsearch.izhnet.ru <>2002-03-29 18:22:21 +0400
commitae03ccc40399d01fd78a5bf393b92dbfcdf1951e (patch)
treef912fbb72c2b725603729c02d6079e5fd0474608
parent0300bac68a5ab9c5b00d6fe59a1f9872297a0de3 (diff)
downloadmariadb-git-ae03ccc40399d01fd78a5bf393b92dbfcdf1951e.tar.gz
Charset convertion operator CONVERT( string USING charset)
-rw-r--r--sql/item_strfunc.cc67
-rw-r--r--sql/item_strfunc.h13
-rw-r--r--sql/sql_yacc.yy10
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(&current_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 ')'