summaryrefslogtreecommitdiff
path: root/sql/lex_charset.cc
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.com>2022-05-23 11:05:33 +0400
committerAlexander Barkov <bar@mariadb.com>2022-05-23 12:13:40 +0400
commit89adedcb9f0a45483b9917e93310241a4976d4c2 (patch)
tree8747d23a59b2b9d3bdd20458659049afadbff655 /sql/lex_charset.cc
parente7f635e2d29ae283eb4818c47fa6bd2036b5ccfe (diff)
downloadmariadb-git-89adedcb9f0a45483b9917e93310241a4976d4c2.tar.gz
Step#3 MDEV-27896 Wrong result upon `COLLATE latin1_bin CHARACTER SET latin1` on the table or the database level
Splitting Lex_exact_charset_extended_collation_attrs_st into small components. - Adding classes: * Lex_exact_charset * Lex_context_collation * Lex_exact_collation * Lex_extended_collation_st * Lex_extended_collation and moving pieces of the code from methods * merge_charset_clause_and_collate_clause() * merge_collate_clause_and_collate_clause() into smaller methods in the new classes. It's easier to read, handle and reuse the code this way. - Moving static methods find_default_collation() and find_binary_collation() from Lex_exact_charset_extended_collation_attrs_st to non-static methods in Lex_exact_charset_opt_extended_collate, as now it's a better place for them. - Using Lex_extended_collation_st in sql_yacc.yy to handle COLLATE clauses, to handle both context and extended collations (instead of the previous notation with NULL CHARSET_INFO pointer meaning DEFAULT, and not-NULL meaning an exact collation). This change will also help to add more context (UCA1400) collations soon. The old notation with CHARSET_INFO won't be enough. - Adding LEX::set_names() and reusing it in two places in sql_yacc.yy - Removing the opt_collate_or_default rule. It's was used only to handle the CONVERT TO related grammar. Had to add some code duplication, but it will be gone in one of the next commits. This change will also soon help to add Lex_extended_charset_extended_collation_attrs_st - a new class to handle table and database level CHARACTER SET and COLLATE clauses easier.
Diffstat (limited to 'sql/lex_charset.cc')
-rw-r--r--sql/lex_charset.cc575
1 files changed, 385 insertions, 190 deletions
diff --git a/sql/lex_charset.cc b/sql/lex_charset.cc
index 923e20001a3..1373091d222 100644
--- a/sql/lex_charset.cc
+++ b/sql/lex_charset.cc
@@ -21,49 +21,317 @@
#include "mysqld_error.h"
+static void
+raise_ER_CONFLICTING_DECLARATIONS(const char *clause1,
+ const char *name1,
+ const char *clause2,
+ const char *name2,
+ bool reverse_order)
+{
+ if (!reverse_order)
+ my_error(ER_CONFLICTING_DECLARATIONS, MYF(0),
+ clause1, name1, clause2, name2);
+ else
+ my_error(ER_CONFLICTING_DECLARATIONS, MYF(0),
+ clause2, name2, clause1, name1);
+}
+
+
+bool Lex_exact_charset::raise_if_not_equal(const Lex_exact_charset &rhs) const
+{
+ if (m_ci == rhs.m_ci)
+ return false;
+ my_error(ER_CONFLICTING_DECLARATIONS, MYF(0),
+ "CHARACTER SET ", m_ci->cs_name.str,
+ "CHARACTER SET ", rhs.m_ci->cs_name.str);
+ return true;
+}
+
+
+bool Lex_exact_charset::
+ raise_if_not_applicable(const Lex_exact_collation &cl) const
+{
+ return Lex_exact_charset_opt_extended_collate(m_ci, false).
+ raise_if_not_applicable(cl);
+}
+
+
+bool Lex_exact_charset_opt_extended_collate::
+ raise_if_not_applicable(const Lex_exact_collation &cl) const
+{
+ if (!my_charset_same(m_ci, cl.charset_info()))
+ {
+ my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0),
+ cl.charset_info()->coll_name.str, m_ci->cs_name.str);
+ return true;
+ }
+ return false;
+}
+
+
+bool
+Lex_exact_collation::raise_if_not_equal(const Lex_exact_collation &cl) const
+{
+ if (m_ci != cl.m_ci)
+ {
+ my_error(ER_CONFLICTING_DECLARATIONS, MYF(0),
+ "COLLATE ", m_ci->coll_name.str,
+ "COLLATE ", cl.m_ci->coll_name.str);
+ return true;
+ }
+ return false;
+}
+
+
+/*
+ Merge an exact collation and a contexual collation.
+ @param cl - The contextual collation to merge to "this".
+ @param reverse_order - If the contextual collation is on the left side
+
+ Use reverse_order as follows:
+ false: COLLATE latin1_swedish_ci COLLATE DEFAULT
+ true: COLLATE DEFAULT COLLATE latin1_swedish_ci
+*/
+bool
+Lex_exact_collation::
+ raise_if_conflicts_with_context_collation(const Lex_context_collation &cl,
+ bool reverse_order) const
+{
+ if (cl.is_contextually_typed_collate_default() &&
+ !(m_ci->state & MY_CS_PRIMARY))
+ {
+ raise_ER_CONFLICTING_DECLARATIONS("COLLATE ", m_ci->coll_name.str,
+ "COLLATE ", "DEFAULT", reverse_order);
+ return true;
+ }
+
+ if (cl.is_contextually_typed_binary_style() &&
+ !(m_ci->state & MY_CS_BINSORT))
+ {
+ raise_ER_CONFLICTING_DECLARATIONS("COLLATE ", m_ci->coll_name.str,
+ "", "BINARY", reverse_order);
+ return true;
+ }
+ return false;
+}
+
+
+bool
+Lex_context_collation::raise_if_not_equal(const Lex_context_collation &cl) const
+{
+ /*
+ Only equal context collations are possible here so far:
+ - Column grammar only supports BINARY, but does not support COLLATE DEFAULT
+ - DB/Table grammar only support COLLATE DEFAULT
+ But we'll have different collations here - uca140 is coming soon.
+ */
+ DBUG_ASSERT(m_ci == cl.m_ci);
+ return false;
+}
+
+
+/*
+ Resolve a context collation to the character set (when the former gets known):
+ CREATE TABLE t1 (a CHAR(10) BINARY) CHARACTER SET latin1;
+ CREATE DATABASE db1 COLLATE DEFAULT CHARACTER SET latin1;
+*/
+bool Lex_exact_charset_opt_extended_collate::
+ merge_context_collation_override(const Lex_context_collation &cl)
+{
+ DBUG_ASSERT(m_ci);
+
+ // CHAR(10) BINARY
+ if (cl.is_contextually_typed_binary_style())
+ {
+ CHARSET_INFO *ci= find_bin_collation();
+ if (!ci)
+ return true;
+ m_ci= ci;
+ m_with_collate= true;
+ return false;
+ }
+
+ // COLLATE DEFAULT
+ if (cl.is_contextually_typed_collate_default())
+ {
+ CHARSET_INFO *ci= find_default_collation();
+ DBUG_ASSERT(ci);
+ if (!ci)
+ return true;
+ m_ci= ci;
+ m_with_collate= true;
+ return false;
+ }
+
+ /*
+ A non-binary and non-default contextually typed collation.
+ We don't have such yet - the parser cannot produce this.
+ But we have "uca1400_as_ci" coming soon.
+ */
+ DBUG_ASSERT(0);
+ return false;
+}
+
+
+bool Lex_extended_collation_st::merge_exact_charset(const Lex_exact_charset &cs)
+{
+ switch (m_type) {
+ case TYPE_EXACT:
+ {
+ // COLLATE latin1_swedish_ci .. CHARACTER SET latin1
+ return cs.raise_if_not_applicable(Lex_exact_collation(m_ci));
+ }
+ case TYPE_CONTEXTUALLY_TYPED:
+ {
+ // COLLATE DEFAULT .. CHARACTER SET latin1
+ Lex_exact_charset_opt_extended_collate tmp(cs);
+ if (tmp.merge_context_collation(Lex_context_collation(m_ci)))
+ return true;
+ *this= Lex_extended_collation(tmp.collation());
+ return false;
+ }
+ }
+ DBUG_ASSERT(0);
+ return false;
+}
+
+
+bool Lex_extended_collation_st::
+ merge_exact_collation(const Lex_exact_collation &rhs)
+{
+ switch (m_type) {
+
+ case TYPE_EXACT:
+ /*
+ EXACT + EXACT
+ COLLATE latin1_bin .. COLLATE latin1_bin
+ */
+ return Lex_exact_collation(m_ci).raise_if_not_equal(rhs);
+
+ case TYPE_CONTEXTUALLY_TYPED:
+ {
+ /*
+ CONTEXT + EXACT
+ CHAR(10) COLLATE DEFAULT .. COLLATE latin1_swedish_ci
+ CHAR(10) BINARY .. COLLATE latin1_bin
+ CHAR(10) COLLATE uca1400_as_ci .. COLLATE latin1_bin - coming soon
+ */
+ if (rhs.raise_if_conflicts_with_context_collation(
+ Lex_context_collation(m_ci), true))
+ return true;
+ *this= Lex_extended_collation(rhs);
+ return false;
+ }
+ }
+ DBUG_ASSERT(0);
+ return false;
+}
+
+
+bool Lex_extended_collation_st::
+ raise_if_conflicts_with_context_collation(const Lex_context_collation &rhs)
+ const
+{
+ switch (m_type) {
+
+ case TYPE_EXACT:
+ /*
+ EXACT + CONTEXT
+ COLLATE latin1_swedish_ci .. COLLATE DEFAULT
+ */
+ return Lex_exact_collation(m_ci).
+ raise_if_conflicts_with_context_collation(rhs, false);
+
+ case TYPE_CONTEXTUALLY_TYPED:
+ {
+ /*
+ CONTEXT + CONTEXT:
+ CHAR(10) BINARY .. COLLATE DEFAULT - not supported by the parser
+ CREATE DATABASE db1 COLLATE DEFAULT COLLATE DEFAULT;
+ */
+ return Lex_context_collation(m_ci).raise_if_not_equal(rhs);
+ }
+ }
+ DBUG_ASSERT(0);
+ return false;
+}
+
+
+/*
+ Merge two non-empty COLLATE clauses.
+*/
+bool Lex_extended_collation_st::merge(const Lex_extended_collation_st &rhs)
+{
+ switch (rhs.type()) {
+ case TYPE_EXACT:
+ /*
+ EXACT + EXACT
+ COLLATE latin1_swedish_ci .. COLLATE latin1_swedish_ci
+
+ CONTEXT + EXACT
+ COLLATE DEFAULT .. COLLATE latin1_swedish_ci
+ CHAR(10) BINARY .. COLLATE latin1_bin
+ */
+ return merge_exact_collation(Lex_exact_collation(rhs.m_ci));
+ case TYPE_CONTEXTUALLY_TYPED:
+ /*
+ EXACT + CONTEXT
+ COLLATE latin1_swedish_ci .. COLLATE DEFAULT
+
+ CONTEXT + CONTEXT
+ COLLATE DEFAULT .. COLLATE DEFAULT
+ CHAR(10) BINARY .. COLLATE DEFAULT
+ */
+ return raise_if_conflicts_with_context_collation(
+ Lex_context_collation(rhs.m_ci));
+ }
+ DBUG_ASSERT(0);
+ return false;
+}
+
+
/** find a collation with binary comparison rules
*/
-CHARSET_INFO *Lex_exact_charset_extended_collation_attrs_st::
- find_bin_collation(CHARSET_INFO *cs)
+CHARSET_INFO *Lex_exact_charset_opt_extended_collate::find_bin_collation() const
{
/*
We don't need to handle old_mode=UTF8_IS_UTF8MB3 here,
- because "cs" points to a real character set name.
+ because "m_ci" points to a real character set name.
It can be either "utf8mb3" or "utf8mb4". It cannot be "utf8".
No thd->get_utf8_flag() flag passed to get_charset_by_csname().
*/
- DBUG_ASSERT(cs->cs_name.length !=4 || memcmp(cs->cs_name.str, "utf8", 4));
+ DBUG_ASSERT(m_ci->cs_name.length !=4 || memcmp(m_ci->cs_name.str, "utf8", 4));
/*
CREATE TABLE t1 (a CHAR(10) BINARY)
CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
Nothing to do, we have the binary collation already.
*/
- if (cs->state & MY_CS_BINSORT)
- return cs;
+ if (m_ci->state & MY_CS_BINSORT)
+ return m_ci;
// CREATE TABLE t1 (a CHAR(10) BINARY) CHARACTER SET utf8mb4;
- const LEX_CSTRING &cs_name= cs->cs_name;
- if (!(cs= get_charset_by_csname(cs->cs_name.str, MY_CS_BINSORT, MYF(0))))
+ CHARSET_INFO *cs;
+ if (!(cs= get_charset_by_csname(m_ci->cs_name.str, MY_CS_BINSORT, MYF(0))))
{
char tmp[65];
- strxnmov(tmp, sizeof(tmp)-1, cs_name.str, "_bin", NULL);
+ strxnmov(tmp, sizeof(tmp)-1, m_ci->cs_name.str, "_bin", NULL);
my_error(ER_UNKNOWN_COLLATION, MYF(0), tmp);
}
return cs;
}
-CHARSET_INFO *Lex_exact_charset_extended_collation_attrs_st::
- find_default_collation(CHARSET_INFO *cs)
+CHARSET_INFO *
+Lex_exact_charset_opt_extended_collate::find_default_collation() const
{
// See comments in find_bin_collation()
- DBUG_ASSERT(cs->cs_name.length !=4 || memcmp(cs->cs_name.str, "utf8", 4));
+ DBUG_ASSERT(m_ci->cs_name.length !=4 || memcmp(m_ci->cs_name.str, "utf8", 4));
/*
CREATE TABLE t1 (a CHAR(10) COLLATE DEFAULT) CHARACTER SET utf8mb4;
Nothing to do, we have the default collation already.
*/
- if (cs->state & MY_CS_PRIMARY)
- return cs;
+ if (m_ci->state & MY_CS_PRIMARY)
+ return m_ci;
/*
CREATE TABLE t1 (a CHAR(10) COLLATE DEFAULT)
CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
@@ -71,7 +339,8 @@ CHARSET_INFO *Lex_exact_charset_extended_collation_attrs_st::
Don't need to handle old_mode=UTF8_IS_UTF8MB3 here.
See comments in find_bin_collation.
*/
- cs= get_charset_by_csname(cs->cs_name.str, MY_CS_PRIMARY, MYF(MY_WME));
+ CHARSET_INFO *cs= get_charset_by_csname(m_ci->cs_name.str,
+ MY_CS_PRIMARY, MYF(MY_WME));
/*
The above should never fail, as we have default collations for
all character sets.
@@ -81,21 +350,6 @@ CHARSET_INFO *Lex_exact_charset_extended_collation_attrs_st::
}
-bool Lex_exact_charset_extended_collation_attrs_st::
- set_charset_collate_exact(CHARSET_INFO *cs, CHARSET_INFO *cl)
-{
- DBUG_ASSERT(cs != nullptr && cl != nullptr);
- if (!my_charset_same(cl, cs))
- {
- my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0),
- cl->coll_name.str, cs->cs_name.str);
- return true;
- }
- set_collate_exact(cl);
- return false;
-}
-
-
/*
Resolve an empty or a contextually typed collation according to the
upper level default character set (and optionally a collation), e.g.:
@@ -122,103 +376,84 @@ CHARSET_INFO *Lex_exact_charset_extended_collation_attrs_st::
DBUG_ASSERT(m_ci);
return m_ci;
case TYPE_COLLATE_CONTEXTUALLY_TYPED:
- break;
+ {
+ Lex_exact_charset_opt_extended_collate tmp(def, true);
+ if (tmp.merge_context_collation_override(Lex_context_collation(m_ci)))
+ return NULL;
+ return tmp.collation().charset_info();
+ }
}
-
- // Contextually typed
- DBUG_ASSERT(m_ci);
-
- if (is_contextually_typed_binary_style()) // CHAR(10) BINARY
- return find_bin_collation(def);
-
- if (is_contextually_typed_collate_default()) // CHAR(10) COLLATE DEFAULT
- return find_default_collation(def);
-
- /*
- Non-binary and non-default contextually typed collation.
- We don't have such yet - the parser cannot produce this.
- But will have soon, e.g. "uca1400_as_ci".
- */
DBUG_ASSERT(0);
return NULL;
}
-/*
- Merge the CHARACTER SET clause to:
- - an empty COLLATE clause
- - an explicitly typed collation name
- - a contextually typed collation
-
- "this" corresponds to `CHARACTER SET xxx [BINARY]`
- "cl" corresponds to the COLLATE clause
-*/
bool Lex_exact_charset_extended_collation_attrs_st::
- merge_charset_clause_and_collate_clause(
- const Lex_exact_charset_extended_collation_attrs_st &cl)
+ merge_exact_collation(const Lex_exact_collation &cl)
{
- if (cl.is_empty()) // No COLLATE clause
- return false;
-
switch (m_type) {
case TYPE_EMPTY:
/*
No CHARACTER SET clause
CHAR(10) NOT NULL COLLATE latin1_bin
- CHAR(10) NOT NULL COLLATE DEFAULT
*/
- *this= cl;
+ *this= Lex_exact_charset_extended_collation_attrs(cl);
return false;
case TYPE_CHARACTER_SET:
- case TYPE_COLLATE_EXACT:
{
- Lex_exact_charset_opt_extended_collate ecs(m_ci, m_type == TYPE_COLLATE_EXACT);
- if (ecs.merge_collate_or_error(cl))
+ // CHARACTER SET latin1 .. COLLATE latin1_swedish_ci
+ if (Lex_exact_charset(m_ci).raise_if_not_applicable(cl))
return true;
- set_collate_exact(ecs.charset_info());
+ *this= Lex_exact_charset_extended_collation_attrs(cl);
return false;
}
+ case TYPE_COLLATE_EXACT:
+ {
+ // [CHARACTER SET latin1] COLLATE latin1_bin .. COLLATE latin1_bin
+ return Lex_exact_collation(m_ci).raise_if_not_equal(cl);
+ }
case TYPE_COLLATE_CONTEXTUALLY_TYPED:
- break;
- }
-
- if (is_contextually_typed_collation())
- {
- if (cl.is_contextually_typed_collation())
{
- /*
- CONTEXT + CONTEXT:
- CHAR(10) BINARY .. COLLATE DEFAULT - not supported by the parser
- CHAR(10) BINARY .. COLLATE uca1400_as_ci - not supported yet
- */
- DBUG_ASSERT(0); // Not possible yet
+ // COLLATE DEFAULT .. COLLATE latin1_swedish_ci
+ if (cl.raise_if_conflicts_with_context_collation(
+ Lex_context_collation(m_ci), true))
+ return true;
+ *this= Lex_exact_charset_extended_collation_attrs(cl);
return false;
}
+ }
+ DBUG_ASSERT(0);
+ return false;
+}
+
+bool Lex_exact_charset_extended_collation_attrs_st::
+ merge_context_collation(const Lex_context_collation &cl)
+{
+ switch (m_type) {
+ case TYPE_EMPTY:
/*
- CONTEXT + EXPLICIT
- CHAR(10) COLLATE DEFAULT .. COLLATE latin1_swedish_ci
- CHAR(10) BINARY .. COLLATE latin1_bin
- CHAR(10) COLLATE uca1400_as_ci .. COLLATE latin1_bin
+ No CHARACTER SET clause
+ CHAR(10) NOT NULL .. COLLATE DEFAULT
*/
- if (is_contextually_typed_collate_default() &&
- !(cl.charset_info()->state & MY_CS_PRIMARY))
- {
- my_error(ER_CONFLICTING_DECLARATIONS, MYF(0),
- "COLLATE ", "DEFAULT", "COLLATE ",
- cl.charset_info()->coll_name.str);
- return true;
- }
-
- if (is_contextually_typed_binary_style() &&
- !(cl.charset_info()->state & MY_CS_BINSORT))
+ *this= Lex_exact_charset_extended_collation_attrs(cl);
+ return false;
+ case TYPE_CHARACTER_SET:
{
- my_error(ER_CONFLICTING_DECLARATIONS, MYF(0),
- "", "BINARY", "COLLATE ", cl.charset_info()->coll_name.str);
- return true;
+ // CHARACTER SET latin1 .. COLLATE DEFAULT
+ Lex_exact_charset_opt_extended_collate tmp(m_ci, false);
+ if (tmp.merge_context_collation(cl))
+ return true;
+ *this= Lex_exact_charset_extended_collation_attrs(tmp.collation());
+ return false;
}
- *this= cl;
- return false;
+ case TYPE_COLLATE_EXACT:
+ // [CHARACTER SET latin1] COLLATE latin1_swedish_ci .. COLLATE DEFAULT
+ return Lex_exact_collation(m_ci).
+ raise_if_conflicts_with_context_collation(cl, false);
+ case TYPE_COLLATE_CONTEXTUALLY_TYPED:
+ // COLLATE DEFAULT .. COLLATE DEFAULT
+ return Lex_context_collation(m_ci).raise_if_not_equal(cl);
}
DBUG_ASSERT(0);
@@ -227,69 +462,37 @@ bool Lex_exact_charset_extended_collation_attrs_st::
bool Lex_exact_charset_opt_extended_collate::
- merge_collate_or_error(
- const Lex_exact_charset_extended_collation_attrs_st &cl)
+ merge_exact_collation(const Lex_exact_collation &cl)
{
- DBUG_ASSERT(cl.type() !=
- Lex_exact_charset_extended_collation_attrs_st::TYPE_CHARACTER_SET);
+ // CHARACTER SET latin1 [COLLATE latin1_bin] .. COLLATE latin1_bin
+ if (m_with_collate)
+ return Lex_exact_collation(m_ci).raise_if_not_equal(cl);
+ if (raise_if_not_applicable(cl))
+ return true;
+ *this= Lex_exact_charset_opt_extended_collate(cl);
+ return false;
+}
- switch (cl.type()) {
- case Lex_exact_charset_extended_collation_attrs_st::TYPE_EMPTY:
- return false;
- case Lex_exact_charset_extended_collation_attrs_st::TYPE_CHARACTER_SET:
- DBUG_ASSERT(0);
- return false;
- case Lex_exact_charset_extended_collation_attrs_st::TYPE_COLLATE_EXACT:
- /*
- EXPLICIT + EXPLICIT
- CHAR(10) CHARACTER SET latin1 .. COLLATE latin1_bin
- CHAR(10) CHARACTER SET latin1 COLLATE latin1_bin .. COLLATE latin1_bin
- CHAR(10) COLLATE latin1_bin .. COLLATE latin1_bin
- CHAR(10) COLLATE latin1_bin .. COLLATE latin1_bin
- CHAR(10) CHARACTER SET latin1 BINARY .. COLLATE latin1_bin
- */
- if (m_with_collate && m_ci != cl.charset_info())
- {
- my_error(ER_CONFLICTING_DECLARATIONS, MYF(0),
- "COLLATE ", m_ci->coll_name.str,
- "COLLATE ", cl.charset_info()->coll_name.str);
- return true;
- }
- if (!my_charset_same(m_ci, cl.charset_info()))
- {
- my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0),
- cl.charset_info()->coll_name.str, m_ci->cs_name.str);
- return true;
- }
- m_ci= cl.charset_info();
- m_with_collate= true;
- return false;
- case Lex_exact_charset_extended_collation_attrs_st::TYPE_COLLATE_CONTEXTUALLY_TYPED:
- if (cl.is_contextually_typed_collate_default())
- {
- /*
- SET NAMES latin1 COLLATE DEFAULT;
- ALTER TABLE t1 CONVERT TO CHARACTER SET latin1 COLLATE DEFAULT;
- */
- CHARSET_INFO *tmp= Lex_exact_charset_extended_collation_attrs_st::find_default_collation(m_ci);
- if (!tmp)
- return true;
- m_ci= tmp;
- m_with_collate= true;
- return false;
- }
- else
- {
- /*
- EXPLICIT + CONTEXT
- CHAR(10) COLLATE latin1_bin .. COLLATE DEFAULT not possible yet
- CHAR(10) COLLATE latin1_bin .. COLLATE uca1400_as_ci
- */
+bool Lex_exact_charset_opt_extended_collate::
+ merge_context_collation(const Lex_context_collation &cl)
+{
+ // CHARACTER SET latin1 [COLLATE latin1_bin] .. COLLATE DEFAULT
+ if (m_with_collate)
+ return Lex_exact_collation(m_ci).
+ raise_if_conflicts_with_context_collation(cl, false);
+ return merge_context_collation_override(cl);
+}
- DBUG_ASSERT(0); // Not possible yet
- return false;
- }
+
+bool Lex_exact_charset_extended_collation_attrs_st::
+ merge_collation(const Lex_extended_collation_st &cl)
+{
+ switch (cl.type()) {
+ case Lex_extended_collation_st::TYPE_EXACT:
+ return merge_exact_collation(Lex_exact_collation(cl.charset_info()));
+ case Lex_extended_collation_st::TYPE_CONTEXTUALLY_TYPED:
+ return merge_context_collation(Lex_context_collation(cl.charset_info()));
}
DBUG_ASSERT(0);
return false;
@@ -297,48 +500,40 @@ bool Lex_exact_charset_opt_extended_collate::
/*
- This method is used in the "attribute_list" rule to merge two independent
- COLLATE clauses (not belonging to a CHARACTER SET clause).
+ Mix an unordered combination of CHARACTER SET and COLLATE clauses
+ (i.e. COLLATE can come before CHARACTER SET).
+ Merge a CHARACTER SET clause.
+ @param cs - The "CHARACTER SET exact_charset_name".
*/
-bool
-Lex_exact_charset_extended_collation_attrs_st::
- merge_collate_clause_and_collate_clause(
- const Lex_exact_charset_extended_collation_attrs_st &cl)
+bool Lex_exact_charset_extended_collation_attrs_st::
+ merge_exact_charset(const Lex_exact_charset &cs)
{
- /*
- "BINARY" and "COLLATE DEFAULT" are not possible
- in an independent COLLATE clause in a column attribute.
- */
- DBUG_ASSERT(!is_contextually_typed_collation());
- DBUG_ASSERT(!cl.is_contextually_typed_collation());
-
- if (cl.is_empty())
- return false;
+ DBUG_ASSERT(cs.charset_info());
switch (m_type) {
case TYPE_EMPTY:
- *this= cl;
+ // CHARACTER SET cs
+ *this= Lex_exact_charset_extended_collation_attrs(cs);
return false;
+
case TYPE_CHARACTER_SET:
- DBUG_ASSERT(0);
- return false;
+ // CHARACTER SET cs1 .. CHARACTER SET cs2
+ return Lex_exact_charset(m_ci).raise_if_not_equal(cs);
+
case TYPE_COLLATE_EXACT:
- case TYPE_COLLATE_CONTEXTUALLY_TYPED:
- break;
- }
+ // COLLATE latin1_bin .. CHARACTER SET cs
+ return cs.raise_if_not_applicable(Lex_exact_collation(m_ci));
- /*
- Two independent explicit collations:
- CHAR(10) NOT NULL COLLATE latin1_bin DEFAULT 'a' COLLATE latin1_bin
- Note, we should perhaps eventually disallow double COLLATE clauses.
- But for now let's just disallow only conflicting ones.
- */
- if (charset_info() != cl.charset_info())
- {
- my_error(ER_CONFLICTING_DECLARATIONS, MYF(0),
- "COLLATE ", charset_info()->coll_name.str,
- "COLLATE ", cl.charset_info()->coll_name.str);
- return true;
+ case TYPE_COLLATE_CONTEXTUALLY_TYPED:
+ // COLLATE DEFAULT .. CHARACTER SET cs
+ {
+ Lex_exact_charset_opt_extended_collate tmp(cs);
+ if (tmp.merge_context_collation(Lex_context_collation(m_ci)))
+ return true;
+ *this= Lex_exact_charset_extended_collation_attrs(tmp.collation());
+ return false;
+ }
}
+ DBUG_ASSERT(0);
return false;
}