diff options
Diffstat (limited to 'mysys/charset.c')
-rw-r--r-- | mysys/charset.c | 126 |
1 files changed, 99 insertions, 27 deletions
diff --git a/mysys/charset.c b/mysys/charset.c index 952e045aefd..9f9a96a3089 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -1,5 +1,4 @@ -/* - Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -12,8 +11,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "mysys_priv.h" #include "mysys_err.h" @@ -44,7 +42,7 @@ get_collation_number_internal(const char *name) { CHARSET_INFO **cs; for (cs= all_charsets; - cs < all_charsets+array_elements(all_charsets)-1 ; + cs < all_charsets + array_elements(all_charsets); cs++) { if ( cs[0] && cs[0]->name && @@ -253,12 +251,38 @@ static int add_collation(CHARSET_INFO *cs) { #if defined(HAVE_CHARSET_ucs2) && defined(HAVE_UCA_COLLATIONS) copy_uca_collation(newcs, &my_charset_ucs2_unicode_ci); + newcs->state|= MY_CS_AVAILABLE | MY_CS_LOADED | MY_CS_NONASCII; #endif } - else if (!strcmp(cs->csname, "utf8")) + else if (!strcmp(cs->csname, "utf8") || !strcmp(cs->csname, "utf8mb3")) { #if defined (HAVE_CHARSET_utf8) && defined(HAVE_UCA_COLLATIONS) copy_uca_collation(newcs, &my_charset_utf8_unicode_ci); + newcs->ctype= my_charset_utf8_unicode_ci.ctype; + if (init_state_maps(newcs)) + return MY_XML_ERROR; +#endif + } + else if (!strcmp(cs->csname, "utf8mb4")) + { +#if defined (HAVE_CHARSET_utf8mb4) && defined(HAVE_UCA_COLLATIONS) + copy_uca_collation(newcs, &my_charset_utf8mb4_unicode_ci); + newcs->ctype= my_charset_utf8mb4_unicode_ci.ctype; + newcs->state|= MY_CS_AVAILABLE | MY_CS_LOADED; +#endif + } + else if (!strcmp(cs->csname, "utf16")) + { +#if defined (HAVE_CHARSET_utf16) && defined(HAVE_UCA_COLLATIONS) + copy_uca_collation(newcs, &my_charset_utf16_unicode_ci); + newcs->state|= MY_CS_AVAILABLE | MY_CS_LOADED | MY_CS_NONASCII; +#endif + } + else if (!strcmp(cs->csname, "utf32")) + { +#if defined (HAVE_CHARSET_utf32) && defined(HAVE_UCA_COLLATIONS) + copy_uca_collation(newcs, &my_charset_utf32_unicode_ci); + newcs->state|= MY_CS_AVAILABLE | MY_CS_LOADED | MY_CS_NONASCII; #endif } else @@ -285,6 +309,8 @@ static int add_collation(CHARSET_INFO *cs) if (my_charset_is_8bit_pure_ascii(all_charsets[cs->number])) all_charsets[cs->number]->state|= MY_CS_PUREASCII; + if (!my_charset_is_ascii_compatible(cs)) + all_charsets[cs->number]->state|= MY_CS_NONASCII; } } else @@ -340,10 +366,10 @@ static my_bool my_read_charset_file(const char *filename, myf myflags) !(buf= (uchar*) my_malloc(len,myflags))) return TRUE; - if ((fd=my_open(filename,O_RDONLY,myflags)) < 0) + if ((fd= mysql_file_open(key_file_charset, filename, O_RDONLY, myflags)) < 0) goto error; - tmp_len=my_read(fd, buf, len, myflags); - my_close(fd,myflags); + tmp_len= mysql_file_read(fd, buf, len, myflags); + mysql_file_close(fd, myflags); if (tmp_len != len) goto error; @@ -357,11 +383,11 @@ static my_bool my_read_charset_file(const char *filename, myf myflags) #endif } - my_free(buf, myflags); + my_free(buf); return FALSE; error: - my_free(buf, myflags); + my_free(buf); return TRUE; } @@ -388,11 +414,12 @@ char *get_charsets_dir(char *buf) DBUG_RETURN(res); } -CHARSET_INFO *all_charsets[256]={NULL}; +CHARSET_INFO *all_charsets[MY_ALL_CHARSETS_SIZE]={NULL}; CHARSET_INFO *default_charset_info = &my_charset_latin1; void add_compiled_collation(CHARSET_INFO *cs) { + DBUG_ASSERT(cs->number < array_elements(all_charsets)); all_charsets[cs->number]= cs; cs->state|= MY_CS_AVAILABLE; } @@ -413,7 +440,7 @@ static void init_available_charsets(void) bzero(&all_charsets,sizeof(all_charsets)); init_compiled_charsets(MYF(0)); - + /* Copy compiled charsets */ for (cs=all_charsets; cs < all_charsets+array_elements(all_charsets)-1 ; @@ -426,7 +453,7 @@ static void init_available_charsets(void) *cs= NULL; } } - + strmov(get_charsets_dir(fname), MY_CHARSET_INDEX); my_read_charset_file(fname, MYF(0)); } @@ -437,20 +464,39 @@ void free_charsets(void) charsets_initialized= charsets_template; } + +static const char* +get_collation_name_alias(const char *name, char *buf, size_t bufsize) +{ + if (!strncasecmp(name, "utf8mb3_", 8)) + { + my_snprintf(buf, bufsize, "utf8_%s", name + 8); + return buf; + } + return NULL; +} + + uint get_collation_number(const char *name) { + uint id; + char alias[64]; my_pthread_once(&charsets_initialized, init_available_charsets); - return get_collation_number_internal(name); + if ((id= get_collation_number_internal(name))) + return id; + if ((name= get_collation_name_alias(name, alias, sizeof(alias)))) + return get_collation_number_internal(name); + return 0; } -uint get_charset_number(const char *charset_name, uint cs_flags) +static uint +get_charset_number_internal(const char *charset_name, uint cs_flags) { CHARSET_INFO **cs; - my_pthread_once(&charsets_initialized, init_available_charsets); for (cs= all_charsets; - cs < all_charsets+array_elements(all_charsets)-1 ; + cs < all_charsets + array_elements(all_charsets); cs++) { if ( cs[0] && cs[0]->csname && (cs[0]->state & cs_flags) && @@ -461,16 +507,40 @@ uint get_charset_number(const char *charset_name, uint cs_flags) } +static const char* +get_charset_name_alias(const char *name) +{ + if (!my_strcasecmp(&my_charset_latin1, name, "utf8mb3")) + return "utf8"; + return NULL; +} + + +uint get_charset_number(const char *charset_name, uint cs_flags) +{ + uint id; + my_pthread_once(&charsets_initialized, init_available_charsets); + if ((id= get_charset_number_internal(charset_name, cs_flags))) + return id; + if ((charset_name= get_charset_name_alias(charset_name))) + return get_charset_number_internal(charset_name, cs_flags); + return 0; +} + + const char *get_charset_name(uint charset_number) { - CHARSET_INFO *cs; my_pthread_once(&charsets_initialized, init_available_charsets); - cs=all_charsets[charset_number]; - if (cs && (cs->number == charset_number) && cs->name ) - return (char*) cs->name; + if (charset_number < array_elements(all_charsets)) + { + CHARSET_INFO *cs= all_charsets[charset_number]; + + if (cs && (cs->number == charset_number) && cs->name) + return (char*) cs->name; + } - return (char*) "?"; /* this mimics find_type() */ + return "?"; /* this mimics find_type() */ } @@ -479,6 +549,8 @@ static CHARSET_INFO *get_internal_charset(uint cs_number, myf flags) char buf[FN_REFLEN]; CHARSET_INFO *cs; + DBUG_ASSERT(cs_number < array_elements(all_charsets)); + if ((cs= all_charsets[cs_number])) { if (cs->state & MY_CS_READY) /* if CS is already initialized */ @@ -488,7 +560,7 @@ static CHARSET_INFO *get_internal_charset(uint cs_number, myf flags) To make things thread safe we are not allowing other threads to interfere while we may changing the cs_info_table */ - pthread_mutex_lock(&THR_LOCK_charset); + mysql_mutex_lock(&THR_LOCK_charset); if (!(cs->state & (MY_CS_COMPILED|MY_CS_LOADED))) /* if CS is not in memory */ { @@ -510,7 +582,7 @@ static CHARSET_INFO *get_internal_charset(uint cs_number, myf flags) else cs= NULL; - pthread_mutex_unlock(&THR_LOCK_charset); + mysql_mutex_unlock(&THR_LOCK_charset); } return cs; } @@ -523,8 +595,8 @@ CHARSET_INFO *get_charset(uint cs_number, myf flags) return default_charset_info; my_pthread_once(&charsets_initialized, init_available_charsets); - - if (!cs_number || cs_number >= array_elements(all_charsets)-1) + + if (cs_number >= array_elements(all_charsets)) return NULL; cs=get_internal_charset(cs_number, flags); |