diff options
Diffstat (limited to 'mysys/charset.c')
-rw-r--r-- | mysys/charset.c | 132 |
1 files changed, 106 insertions, 26 deletions
diff --git a/mysys/charset.c b/mysys/charset.c index e46fd16a5fb..2d9df9f47e4 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -123,13 +123,21 @@ static my_bool init_state_maps(struct charset_info_st *cs) } +static MY_COLLATION_HANDLER *get_simple_collation_handler_by_flags(uint flags) +{ + return flags & MY_CS_BINSORT ? + (flags & MY_CS_NOPAD ? + &my_collation_8bit_nopad_bin_handler : + &my_collation_8bit_bin_handler) : + (flags & MY_CS_NOPAD ? + &my_collation_8bit_simple_nopad_ci_handler : + &my_collation_8bit_simple_ci_handler); +} + + static void simple_cs_init_functions(struct charset_info_st *cs) { - if (cs->state & MY_CS_BINSORT) - cs->coll= &my_collation_8bit_bin_handler; - else - cs->coll= &my_collation_8bit_simple_ci_handler; - + cs->coll= get_simple_collation_handler_by_flags(cs->state); cs->cset= &my_charset_8bit_handler; } @@ -197,13 +205,55 @@ err: } +static my_bool simple_8bit_charset_data_is_full(CHARSET_INFO *cs) +{ + return cs->ctype && cs->to_upper && cs->to_lower && cs->tab_to_uni; +} + + +/** + Inherit missing 8bit charset data from another collation. + Arrays pointed by refcs must be in the permanent memory already, + e.g. static memory, or allocated by my_once_xxx(). +*/ +static void +inherit_charset_data(struct charset_info_st *cs, CHARSET_INFO *refcs) +{ + if (!cs->to_upper) + cs->to_upper= refcs->to_upper; + if (!cs->to_lower) + cs->to_lower= refcs->to_lower; + if (!cs->ctype) + cs->ctype= refcs->ctype; + if (!cs->tab_to_uni) + cs->tab_to_uni= refcs->tab_to_uni; +} + + +static my_bool simple_8bit_collation_data_is_full(CHARSET_INFO *cs) +{ + return cs->sort_order || (cs->state & MY_CS_BINSORT); +} + + +/** + Inherit 8bit simple collation data from another collation. + refcs->sort_order must be in the permanent memory already, + e.g. static memory, or allocated by my_once_xxx(). +*/ +static void +inherit_collation_data(struct charset_info_st *cs, CHARSET_INFO *refcs) +{ + if (!simple_8bit_collation_data_is_full(cs)) + cs->sort_order= refcs->sort_order; +} + static my_bool simple_cs_is_full(CHARSET_INFO *cs) { - return ((cs->csname && cs->tab_to_uni && cs->ctype && cs->to_upper && - cs->to_lower) && - (cs->number && cs->name && - (cs->sort_order || (cs->state & MY_CS_BINSORT) ))); + return cs->number && cs->csname && cs->name && + simple_8bit_charset_data_is_full(cs) && + (simple_8bit_collation_data_is_full(cs) || cs->tailoring); } @@ -297,7 +347,6 @@ static int add_collation(struct charset_info_st *cs) } else { - const uchar *sort_order= newcs->sort_order; simple_cs_init_functions(newcs); newcs->mbminlen= 1; newcs->mbmaxlen= 1; @@ -307,21 +356,6 @@ static int add_collation(struct charset_info_st *cs) newcs->state |= MY_CS_LOADED; } newcs->state|= MY_CS_AVAILABLE; - - /* - Check if case sensitive sort order: A < a < B. - We need MY_CS_FLAG for regex library, and for - case sensitivity flag for 5.0 client protocol, - to support isCaseSensitive() method in JDBC driver - */ - if (sort_order && sort_order['A'] < sort_order['a'] && - sort_order['a'] < sort_order['B']) - newcs->state|= MY_CS_CSSORT; - - if (my_charset_is_8bit_pure_ascii(newcs)) - newcs->state|= MY_CS_PUREASCII; - if (!my_charset_is_ascii_compatible(cs)) - newcs->state|= MY_CS_NONASCII; } } else @@ -352,7 +386,7 @@ static int add_collation(struct charset_info_st *cs) cs->name= NULL; cs->state= 0; cs->sort_order= NULL; - cs->state= 0; + cs->tailoring= NULL; } return MY_XML_OK; } @@ -647,6 +681,39 @@ const char *get_charset_name(uint charset_number) } +static CHARSET_INFO *inheritance_source_by_id(CHARSET_INFO *cs, uint refid) +{ + CHARSET_INFO *refcs; + return refid && refid != cs->number && + (refcs= all_charsets[refid]) && + (refcs->state & MY_CS_AVAILABLE) ? refcs : NULL; +} + + +static CHARSET_INFO *find_collation_data_inheritance_source(CHARSET_INFO *cs) +{ + const char *beg, *end; + if (cs->tailoring && + !strncmp(cs->tailoring, "[import ", 8) && + (end= strchr(cs->tailoring + 8, ']')) && + (beg= cs->tailoring + 8) + MY_CS_NAME_SIZE > end) + { + char name[MY_CS_NAME_SIZE + 1]; + memcpy(name, beg, end - beg); + name[end - beg]= '\0'; + return inheritance_source_by_id(cs, get_collation_number(name)); + } + return NULL; +} + + +static CHARSET_INFO *find_charset_data_inheritance_source(CHARSET_INFO *cs) +{ + uint refid= get_charset_number_internal(cs->csname, MY_CS_PRIMARY); + return inheritance_source_by_id(cs, refid); +} + + static CHARSET_INFO * get_internal_charset(MY_CHARSET_LOADER *loader, uint cs_number, myf flags) { @@ -681,6 +748,19 @@ get_internal_charset(MY_CHARSET_LOADER *loader, uint cs_number, myf flags) { if (!(cs->state & MY_CS_READY)) { + if (!simple_8bit_charset_data_is_full(cs)) + { + CHARSET_INFO *refcs= find_charset_data_inheritance_source(cs); + if (refcs) + inherit_charset_data(cs, refcs); + } + if (!simple_8bit_collation_data_is_full(cs)) + { + CHARSET_INFO *refcl= find_collation_data_inheritance_source(cs); + if (refcl) + inherit_collation_data(cs, refcl); + } + if ((cs->cset->init && cs->cset->init(cs, loader)) || (cs->coll->init && cs->coll->init(cs, loader))) { |