summaryrefslogtreecommitdiff
path: root/mysys/charset.c
diff options
context:
space:
mode:
Diffstat (limited to 'mysys/charset.c')
-rw-r--r--mysys/charset.c132
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)))
{