summaryrefslogtreecommitdiff
path: root/mysys
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.org>2016-09-06 12:37:11 +0400
committerAlexander Barkov <bar@mariadb.org>2016-09-06 12:37:11 +0400
commite4f6fd5e1252f8c68f449fe820bae88c18bca8f5 (patch)
tree18830c670cfe3020e72565220096cdf4290d8858 /mysys
parent8ae65920fabddb9157cddb547cf914b4a63539bf (diff)
downloadmariadb-git-e4f6fd5e1252f8c68f449fe820bae88c18bca8f5.tar.gz
MDEV-10743 LDML: a new syntax to reuse sort order from another 8bit simple collation
Diffstat (limited to 'mysys')
-rw-r--r--mysys/charset.c98
1 files changed, 93 insertions, 5 deletions
diff --git a/mysys/charset.c b/mysys/charset.c
index 2a96ec0070d..2efe415af54 100644
--- a/mysys/charset.c
+++ b/mysys/charset.c
@@ -197,13 +197,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);
}
@@ -336,7 +378,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;
}
@@ -631,6 +673,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)
{
@@ -665,6 +740,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)))
{