mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
MDEV-10865 COLLATE keyword doesn't work in PREPARE query
Fixing applying the COLLATE clause to a parameter caused an error error: COLLATION '...' is not valid for CHARACTER SET 'binary' Fix: - Changing the collation derivation for a non-prepared Item_param to DERIVATION_IGNORABLE. - Allowing to apply any COLLATE clause to expressions with DERIVATION_IGNORABLE. This includes: 1. A non-prepared Item_param 2. An explicit NULL 3. Expressions derived from #1 and #2 For example: SELECT ? COLLATE utf8mb_unicode_ci; SELECT NULL COLLATE utf8mb_unicode_ci; SELECT CONCAT(?) COLLATE utf8mb_unicode_ci; SELECT CONCAT(NULL) COLLATE utf8mb_unicode_ci - Additional change: preserving the collation of an expression when the expression gets assigned to a PS parameter and evaluates to SQL NULL. Before this change, the collation of the parameter was erroneously set to &my_charset_binary. - Additional change: removing the multiplication to mbmaxlen from the fix_char_length_ulonglong() argument, because the multiplication already happens inside fix_char_length_ulonglong(). This fixes a too large column size created for a COLLATE clause.
This commit is contained in:
@ -33,6 +33,88 @@ const DTCollation &DTCollation_numeric::singleton()
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
DTCollation::merge_charset_and_collation(CHARSET_INFO *cs,
|
||||
const Lex_extended_collation_st &cl,
|
||||
my_repertoire_t repertoire)
|
||||
{
|
||||
Lex_exact_charset_opt_extended_collate cscl(cs, true);
|
||||
if (cscl.merge_collation_override(cl))
|
||||
return true;
|
||||
set(cscl.collation().charset_info(), DERIVATION_EXPLICIT, repertoire);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool DTCollation::merge_collation(const Lex_extended_collation_st &cl,
|
||||
my_repertoire_t repertoire,
|
||||
bool allow_ignorable_with_context_collation)
|
||||
{
|
||||
if (derivation != DERIVATION_IGNORABLE)
|
||||
{
|
||||
// A known character set + an extended collation
|
||||
return merge_charset_and_collation(collation, cl, repertoire);
|
||||
}
|
||||
|
||||
if (cl.type() == Lex_extended_collation::TYPE_EXACT)
|
||||
{
|
||||
/*
|
||||
An unknown character set + an exact collation.
|
||||
Just use this exact collation.
|
||||
Examples:
|
||||
- Expressions derived from an explicit NULL:
|
||||
SELECT NULL COLLATE utf8mb4_general_ci;
|
||||
SELECT CONCAT(NULL) COLLATE utf8mb4_general_ci;
|
||||
Any collation is applicable to an explicit NULL.
|
||||
|
||||
- Expressions with PS parameters (at PREPARE time, not bound yet)
|
||||
SELECT ? COLLATE utf8mb4_general_ci;
|
||||
SELECT CONCAT(?) COLLATE utf8mb4_general_ci;
|
||||
The collation will be checked for applicability to the
|
||||
character set of the actual bound parameter at the EXECUTE time.
|
||||
We're now in PREPARE: let's assume it will be applicable.
|
||||
*/
|
||||
set(cl.charset_info(), DERIVATION_EXPLICIT, repertoire);
|
||||
return false;
|
||||
}
|
||||
|
||||
// An unknown character set + a contextually typed collation
|
||||
if (allow_ignorable_with_context_collation)
|
||||
{
|
||||
/*
|
||||
Expressions with non-bound PS parameters, PREPARE time.
|
||||
SELECT ? COLLATE uca1400_ai_ci;
|
||||
SELECT CONCAT(?) COLLATE uca1400_ai_ci;
|
||||
There is a chance the character set of the actual bound parameter
|
||||
will be known at the EXECUTE time (unless an explicit NULL is bound).
|
||||
|
||||
For now let's use utf8mb4 to resolve collations like uca1400_ai_ci.
|
||||
The real character set of the actual bound parameter expression will be
|
||||
later used to resolve the collation again, during the EXECUTE time.
|
||||
*/
|
||||
return merge_charset_and_collation(&my_charset_utf8mb4_general_ci,
|
||||
cl, repertoire);
|
||||
}
|
||||
|
||||
/*
|
||||
Expressions with an unknown character set:
|
||||
- Either without PS parameters at all:
|
||||
SELECT NULL COLLATE uca1400_ai_ci;
|
||||
SELECT CONCAT(NULL) COLLATE uca1400_ai_ci;
|
||||
- Or with PS parameters bound to NULL at EXECUTE time:
|
||||
EXECUTE IMMEDIATE
|
||||
'SELECT ? COLLATE uca1400_ai_ci' USING NULL;
|
||||
EXECUTE IMMEDIATE
|
||||
'SELECT CONCAT(?) COLLATE uca1400_ai_ci' USING NULL;
|
||||
EXECUTE IMMEDIATE
|
||||
'SELECT ? COLLATE uca1400_ai_ci' USING CONCAT(NULL);
|
||||
*/
|
||||
my_error(ER_NOT_ALLOWED_IN_THIS_CONTEXT, MYF(0), "NULL");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Named_type_handler<Type_handler_row> type_handler_row("row");
|
||||
|
||||
Named_type_handler<Type_handler_null> type_handler_null("null");
|
||||
|
Reference in New Issue
Block a user