diff options
author | Alexander Barkov <alexander.barkov@oracle.com> | 2011-03-03 18:39:26 +0300 |
---|---|---|
committer | Alexander Barkov <alexander.barkov@oracle.com> | 2011-03-03 18:39:26 +0300 |
commit | a1e9be8e8b17e5f14be9edc558e69c4f68d01fab (patch) | |
tree | 38604e17050632461c1318bbac41cb32c3d0029b /sql/item_strfunc.cc | |
parent | 1bc5e76efb18a5c69f711b4c57a4ff275b187141 (diff) | |
download | mariadb-git-a1e9be8e8b17e5f14be9edc558e69c4f68d01fab.tar.gz |
Bug 11766519 - 59648: MY_STRTOLL10_MB2: ASSERTION `(*ENDPTR - S) % 2 == 0' FAILED.
Part 2. Function QUOTE() was not multi-byte safe.
@ mysql-test/r/ctype_ucs.result
@ mysql-test/t/ctype_ucs.test
Adding tests
@ sql/item_strfunc.cc
Fixing Item_func_quote::val_str to be multi-byte safe.
@ sql/item_strfunc.h
Multiple size needed for quote characters to mbmaxlen
Diffstat (limited to 'sql/item_strfunc.cc')
-rw-r--r-- | sql/item_strfunc.cc | 62 |
1 files changed, 59 insertions, 3 deletions
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 319184002bf..affe0f8e17d 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -3214,14 +3214,68 @@ String *Item_func_quote::val_str(String *str) } arg_length= arg->length(); - new_length= arg_length+2; /* for beginning and ending ' signs */ - for (from= (char*) arg->ptr(), end= from + arg_length; from < end; from++) - new_length+= get_esc_bit(escmask, (uchar) *from); + if (collation.collation->mbmaxlen == 1) + { + new_length= arg_length + 2; /* for beginning and ending ' signs */ + for (from= (char*) arg->ptr(), end= from + arg_length; from < end; from++) + new_length+= get_esc_bit(escmask, (uchar) *from); + } + else + { + new_length= (arg_length * 2) + /* For string characters */ + (2 * collation.collation->mbmaxlen); /* For quotes */ + } if (tmp_value.alloc(new_length)) goto null; + if (collation.collation->mbmaxlen > 1) + { + CHARSET_INFO *cs= collation.collation; + int mblen; + uchar *to_end; + to= (char*) tmp_value.ptr(); + to_end= (uchar*) to + new_length; + + /* Put leading quote */ + if ((mblen= cs->cset->wc_mb(cs, '\'', (uchar *) to, to_end)) <= 0) + goto null; + to+= mblen; + + for (start= (char*) arg->ptr(), end= start + arg_length; start < end; ) + { + my_wc_t wc; + bool escape; + if ((mblen= cs->cset->mb_wc(cs, &wc, (uchar*) start, (uchar*) end)) <= 0) + goto null; + start+= mblen; + switch (wc) { + case 0: escape= 1; wc= '0'; break; + case '\032': escape= 1; wc= 'Z'; break; + case '\'': escape= 1; break; + case '\\': escape= 1; break; + default: escape= 0; break; + } + if (escape) + { + if ((mblen= cs->cset->wc_mb(cs, '\\', (uchar*) to, to_end)) <= 0) + goto null; + to+= mblen; + } + if ((mblen= cs->cset->wc_mb(cs, wc, (uchar*) to, to_end)) <= 0) + goto null; + to+= mblen; + } + + /* Put trailing quote */ + if ((mblen= cs->cset->wc_mb(cs, '\'', (uchar *) to, to_end)) <= 0) + goto null; + to+= mblen; + new_length= to - tmp_value.ptr(); + goto ret; + } + /* We replace characters from the end to the beginning */ @@ -3253,6 +3307,8 @@ String *Item_func_quote::val_str(String *str) } } *to= '\''; + +ret: tmp_value.length(new_length); tmp_value.set_charset(collation.collation); null_value= 0; |