1
0
mirror of https://github.com/MariaDB/server.git synced 2026-10-23 18:49:29 +03:00

Merge branch 'knielsen_log_event_read_validation_base_12.3' into 13.1

This merges the	patch series that fixes	a lot of missing validation
checks for read_log_event(). The merge includes a few added fixes that
are needed in new code introduced in 13.1.

Signed-off-by: Kristian Nielsen <knielsen@knielsen-hq.org>
This commit is contained in:
Kristian Nielsen
2026-10-22 16:01:38 +02:00
780 changed files with 69995 additions and 4649 deletions

View File

@@ -88,6 +88,9 @@ enforces the coding style — flag style violations as well as bugs.
## PR hygiene
- Subject line starts with `MDEV-NNNNN`; body wrapped at 72 cols.
- AI attribution must use the `Assisted-by: NAME:MODEL` line in the commit
comment, for example, `Assisted-by: Claude:claude-5.5-opus`. Flag if it's
`Co-Authored-By`, flag if an AI-assisted commit has no attribution.
- Bug fix targets the oldest maintained branch that reproduces (≤3y since GA);
new feature targets the main branch.
- Bug fix commit is minimal; cleanups (unrelated and related - prerequisite

View File

@@ -1,4 +1,4 @@
# Community Contributions Process #
# Community Contributions Process
MariaDB Server is an Open Source project that thrives thanks to its community.
MariaDB Foundation handles all community contributions in a timely manner.
@@ -25,7 +25,7 @@ But it's important to always have both prior to review.
There are constant efforts (including background processes) to make sure
the states of the Jira and the corresponding pull request(s) are kept in sync.
### What should go into the jira ###
### What should go into the jira
The [Jira](https://jira.mariadb.org) is used to describe the design of the
feature: why is it a good idea, what should work, what might not work etc.
@@ -45,9 +45,9 @@ See [here](https://mariadb.org/contribute/#contribute-to-testing)
> [!CAUTION]
> If the jira already exists and is assigned to somebody please reach out
> to them **before** starting to working on it to avoid effort duplication.
> to them **before** starting to working on it to avoid effort duplication.
### What should go into the pull request ###
### What should go into the pull request
The pull request is used to describe the implementation.
E.g. how the bug is fixed. Or how the feature is implemented in detail.
@@ -64,7 +64,7 @@ And that commit should have a commit message that's compliant with
> If there's no Jira or no reference to it in your pull request
> there might be delays in processing it
## States of a Community Contribution ##
## States of a Community Contribution
```mermaid
stateDiagram-v2
@@ -87,7 +87,7 @@ stateDiagram-v2
Closed --> [*]
```
### Draft ###
### Draft
* Pull request
* State: Draft
@@ -114,7 +114,7 @@ the GitHub pull request viewer UI.
> and "External Contribution" pull request labels and there's
> been no activity for 3 months.
### Open ##
### Open
* Pull request
* State: Open
@@ -169,7 +169,7 @@ Questions and Answers
> label to pull requests in this state, if absent.
> This marks the contribution entering the preliminary review queue.
### Preliminary Review ###
### Preliminary Review
* Pull request
* State: Open
@@ -199,7 +199,7 @@ The preliminary reviewer does the following:
Or that an internal developer has taken over the contribution to
re-do it and push it directly.
### Final review ###
### Final review
* Pull request
* State: Open
@@ -245,7 +245,7 @@ detailed information:
> There's a requirement that certain contributions need to undergo
> a separate test step. This is usually done for the new features or
> for more complex and risky bug fixes. If that's the desired state,
> a test engineer will be assigned as a final reviewer. See
> a test engineer will be assigned as a final reviewer. See
> https://mariadb.com/docs/server/reference/product-development/mariadb-quality-development-rules
> for more details.
@@ -256,7 +256,7 @@ detailed information:
> in the middle of the new feature development cycle or vice versa
> it might take up to a couple of months for a developer to do a review.
### Approved ###
### Approved
* Pull request
* State: Open
@@ -280,7 +280,7 @@ The person that does the merge might need some assistance by the contributor.
When the pull request is successfully merged the Jira should be moved to
"Closed" state and its target version should be specified.
### Merged ###
### Merged
* Pull request
* State: Merged
@@ -295,7 +295,7 @@ This is the "success" final state for a contribution.
Ideally all contributions will end up in this state.
No further actions are necessary.
### Closed ###
### Closed
* Pull request
* State: Closed

View File

@@ -4533,6 +4533,8 @@ print_tab_data(MYSQL_RES *result)
}
while ((cur = fetch_row(result)))
{
if (interrupted_query)
break;
lengths=mysql_fetch_lengths(result);
field= mysql_fetch_fields(result);
if (opt_binhex && is_binary_field(&field[0]))

View File

@@ -748,17 +748,13 @@ static bool print_partial_row_event(PRINT_EVENT_INFO *print_event_info, Log_even
header info here for filtering.
*/
const uchar *rows_data_begin= prle->ev_buffer_base + prle->start_offset;
Log_event_type event_type= (Log_event_type)(uchar)rows_data_begin[EVENT_TYPE_OFFSET];
uint8 const post_header_len= glob_description_event->post_header_len[event_type-1];
uint8 const post_header_len= PARTIAL_ROWS_HEADER_LEN;
const uchar *table_id_ptr= rows_data_begin +
print_event_info->common_header_len +
RW_MAPID_OFFSET;
ulonglong table_id;
if (post_header_len == 6)
table_id= uint4korr(table_id_ptr);
else
table_id= (ulonglong) uint6korr(table_id_ptr);
table_id= (ulonglong) uint6korr(table_id_ptr);
/*
Cache the flags of the Rows_log_event to use it for the last
@@ -1425,7 +1421,7 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
size_t len_to= 0;
const char* db_to= binlog_filter->get_rewrite_db(map->get_db_name(), &len_to);
if (len_to && map->rewrite_db(db_to, len_to, glob_description_event))
if (len_to && map->rewrite_db(db_to, len_to))
{
error("Could not rewrite database name");
goto err;
@@ -2526,6 +2522,53 @@ static Exit_status safe_connect()
}
/**
Copied from sql-common/pack.c, since it is needed for reading Log_event
objects in sql/log_event.cc, but this function is not available in
libmariadbclient.
The function is simple and the format of the variable length field is
fixed, so we can probably live with copying the code for now.
*/
my_ulonglong safe_net_field_length_ll(uchar **packet, size_t packet_len)
{
uchar *pos= *packet;
if (packet_len < 1)
goto err;
if (*pos < 251)
{
(*packet)++;
return (my_ulonglong) *pos;
}
if (*pos == 251)
{
(*packet)++;
return (my_ulonglong) NULL_LENGTH;
}
if (*pos == 252)
{
if (packet_len < 3)
goto err;
(*packet)+=3;
return (my_ulonglong) uint2korr(pos+1);
}
if (*pos == 253)
{
if (packet_len < 4)
goto err;
(*packet)+=4;
return (my_ulonglong) uint3korr(pos+1);
}
if (packet_len < 9 || *pos != 254)
goto err;
(*packet)+=9;
return (my_ulonglong) uint8korr(pos+1);
err:
*packet = NULL;
return 0;
}
/**
High-level function for dumping a named binlog.

View File

@@ -811,6 +811,16 @@ struct Expression_value
void set_int(long long value)
{
type= EXPR_INT;
is_numeric= true;
is_unsigned= false;
int_val= (unsigned long long) value;
}
/* Preserve the bit pattern after a defined unsigned operation. */
void set_int_from_uint(unsigned long long value)
{
type= EXPR_INT;
is_numeric= true;
@@ -1003,6 +1013,17 @@ struct Expression_value
};
static void check_mixed_unsigned_arithmetic(const Expression_value &left,
const Expression_value &right,
const char *op)
{
if ((left.is_unsigned || right.is_unsigned) &&
((!left.is_unsigned && left.to_int() < 0) ||
(!right.is_unsigned && right.to_int() < 0)))
die("Evaluation error: Signed integer overflow in operator '%s'", op);
}
/* Core expression parsing functions */
static void expr(Expression_value *result, const char **s);
static void logical_or(Expression_value *result, const char **s);
@@ -5438,7 +5459,7 @@ void do_sync_with_master(struct st_command *command)
long offset= 0;
char *p= command->first_argument;
const char *offset_start= p;
char *start, *buff= 0;
char *start, *buff= 0, *str;
start= const_cast<char*>("");
if (*offset_start)
@@ -5456,15 +5477,15 @@ void do_sync_with_master(struct st_command *command)
p++;
while (*p && my_isspace(charset_info, *p))
p++;
start= buff= (char*)my_malloc(PSI_NOT_INSTRUMENTED, strlen(p)+1,
MYF(MY_WME|MY_FAE));
get_string(&buff, &p, command);
str= buff= (char*)my_malloc(PSI_NOT_INSTRUMENTED, strlen(p)+1,
MYF(MY_WME|MY_FAE));
start= get_string(&str, &p, command);
}
command->last_argument= p;
}
do_sync_with_master2(command, offset, start);
if (buff)
my_free(start);
my_free(buff);
return;
}
@@ -5755,7 +5776,15 @@ static void unary(Expression_value *result, const char **s)
unary(result, s);
if (!result->is_numeric)
die("Type error: unary minus requires an integer operand");
result->set_int(-result->to_int());
if (result->is_unsigned)
result->set_int_from_uint(0ULL - result->to_uint());
else
{
long long value= result->to_int();
if (value == LLONG_MIN)
die("Evaluation error: Signed integer overflow in unary '-'");
result->set_int(-value);
}
return;
}
if (match(s, "~"))
@@ -5804,10 +5833,26 @@ static void factor(Expression_value *result, const char **s)
bitwise_xor(&rhs, s);
if (!result->is_numeric || !rhs.is_numeric)
die("Type error: operator '*' requires integer operands");
check_mixed_unsigned_arithmetic(*result, rhs, "*");
if (result->is_unsigned || rhs.is_unsigned)
result->set_uint(result->to_uint() * rhs.to_uint());
{
unsigned long long left= result->to_uint();
unsigned long long right= rhs.to_uint();
if (right != 0 && left > ULLONG_MAX / right)
die("Evaluation error: Unsigned integer overflow in operator '*'");
result->set_uint(left * right);
}
else
result->set_int(result->to_int() * rhs.to_int());
{
long long left= result->to_int();
long long right= rhs.to_int();
if ((left > 0 && right > 0 && left > LLONG_MAX / right) ||
(left > 0 && right < 0 && right < LLONG_MIN / left) ||
(left < 0 && right > 0 && left < LLONG_MIN / right) ||
(left < 0 && right < 0 && left < LLONG_MAX / right))
die("Evaluation error: Signed integer overflow in operator '*'");
result->set_int(left * right);
}
}
else if (match(s, "/"))
{
@@ -5817,17 +5862,17 @@ static void factor(Expression_value *result, const char **s)
die("Type error: operator '/' requires integer operands");
if (rhs.to_int() == 0)
die("Evaluation error: Division by zero");
check_mixed_unsigned_arithmetic(*result, rhs, "/");
if (result->is_unsigned || rhs.is_unsigned)
result->set_uint(result->to_uint() / rhs.to_uint());
else
{
long long nominator= result->to_int();
long long denominator= rhs.to_int();
// Prevent fatal integer overflow from LLONG_MIN / -1, which causes a crash
// Prevent signed overflow from LLONG_MIN / -1.
if (nominator == LLONG_MIN && denominator == -1)
result->set_int(nominator);
else
result->set_int(nominator / denominator);
die("Evaluation error: Signed integer overflow in operator '/'");
result->set_int(nominator / denominator);
}
}
else if (match(s, "%"))
@@ -5838,13 +5883,14 @@ static void factor(Expression_value *result, const char **s)
die("Type error: operator '%%' requires integer operands");
if (rhs.to_int() == 0)
die("Evaluation error: Modulo by zero");
check_mixed_unsigned_arithmetic(*result, rhs, "%");
if (result->is_unsigned || rhs.is_unsigned)
result->set_uint(result->to_uint() % rhs.to_uint());
else
{
long long nominator= result->to_int();
long long denominator= rhs.to_int();
// Prevent fatal integer overflow from LLONG_MIN % -1, which causes a crash
// LLONG_MIN % -1 is zero, but the CPU division can still trap.
if (nominator == LLONG_MIN && denominator == -1)
result->set_int(0);
else
@@ -5870,10 +5916,24 @@ static void term(Expression_value *result, const char **s)
factor(&rhs, s);
if (!result->is_numeric || !rhs.is_numeric)
die("Type error: operator '+' requires integer operands");
check_mixed_unsigned_arithmetic(*result, rhs, "+");
if (result->is_unsigned || rhs.is_unsigned)
result->set_uint(result->to_uint() + rhs.to_uint());
{
unsigned long long left= result->to_uint();
unsigned long long right= rhs.to_uint();
if (left > ULLONG_MAX - right)
die("Evaluation error: Unsigned integer overflow in operator '+'");
result->set_uint(left + right);
}
else
result->set_int(result->to_int() + rhs.to_int());
{
long long left= result->to_int();
long long right= rhs.to_int();
if ((right > 0 && left > LLONG_MAX - right) ||
(right < 0 && left < LLONG_MIN - right))
die("Evaluation error: Signed integer overflow in operator '+'");
result->set_int(left + right);
}
}
else if (match(s, "-"))
{
@@ -5881,10 +5941,27 @@ static void term(Expression_value *result, const char **s)
factor(&rhs, s);
if (!result->is_numeric || !rhs.is_numeric)
die("Type error: operator '-' requires integer operands");
check_mixed_unsigned_arithmetic(*result, rhs, "-");
if (result->is_unsigned || rhs.is_unsigned)
result->set_uint(result->to_uint() - rhs.to_uint());
{
unsigned long long left= result->to_uint();
unsigned long long right= rhs.to_uint();
if (left >= right)
result->set_uint(left - right);
else if (right - left <= (unsigned long long) LLONG_MAX + 1)
result->set_int_from_uint(left - right); /* negative result */
else
die("Evaluation error: Integer overflow in operator '-'");
}
else
result->set_int(result->to_int() - rhs.to_int());
{
long long left= result->to_int();
long long right= rhs.to_int();
if ((right > 0 && left < LLONG_MIN + right) ||
(right < 0 && left > LLONG_MAX + right))
die("Evaluation error: Signed integer overflow in operator '-'");
result->set_int(left - right);
}
}
else
break;
@@ -6350,7 +6427,19 @@ void func_abs(Expression_value args[], int count, Expression_value *result)
if (!args[0].is_numeric)
die("abs() requires numeric argument");
result->set_int(llabs(args[0].to_int()));
if (args[0].is_unsigned)
{
if (args[0].to_uint() > (unsigned long long) LLONG_MAX)
die("Evaluation error: Signed integer overflow in abs()");
result->set_int((long long) args[0].to_uint());
}
else
{
long long value= args[0].to_int();
if (value == LLONG_MIN)
die("Evaluation error: Signed integer overflow in abs()");
result->set_int(value < 0 ? -value : value);
}
}
@@ -8508,7 +8597,7 @@ void do_get_errcodes(struct st_command *command)
/*
Get a string; Return ptr to end of string
Get a string; Return ptr to start of string
Strings may be surrounded by " or '
If string is a '$variable', return the value of the variable.
@@ -12848,7 +12937,7 @@ void init_re(void)
*/
const char *ps2_re_str =
"^("
"[[:space:]]*SELECT[[:space:]])";
"[[:space:]]*(\\([[:space:]]*)*SELECT[[:space:]])";
/*
Filter for queries that can be run as views

View File

@@ -28,6 +28,10 @@ IF(RPM)
STRING(REGEX REPLACE "^Have library " "" L ${H})
SET(V ${L}_LIBRARY)
FIND_LIBRARY(${V} ${L})
ELSEIF(H MATCHES "^Have includes? [^/]" AND ${V})
STRING(REGEX REPLACE "^Have includes? (.*;)?" "" I ${H})
SET(V ${I}_INCLUDE)
FIND_FILE(${V} ${I})
ENDIF()
GET_PROPERTY(T CACHE ${V} PROPERTY TYPE)
IF ((T STREQUAL FILEPATH OR V MATCHES "^CMAKE_COMMAND$") AND ${V} MATCHES "^/")

View File

@@ -59,6 +59,11 @@ MACRO(CHECK_DTRACE)
SET(DTRACE_FLAGS -64 CACHE INTERNAL "DTrace architecture flags")
ENDIF()
ENDIF()
include(CheckIncludeFile)
CHECK_INCLUDE_FILE("sys/sdt.h" HAVE_SYS_SDT_H)
IF(NOT HAVE_SYS_SDT_H)
SET(ENABLE_DTRACE OFF CACHE BOOL "Disable dtrace")
ENDIF()
ENDMACRO()
CHECK_DTRACE()

View File

@@ -1,5 +1,5 @@
# Used to check if running in Bash
bash-term-in-posix-shell '${BASH_VERSION' [usr/share/mysql/wsrep_notify:86]
bash-term-in-posix-shell '${BASH_VERSION' [usr/share/mysql/wsrep_notify:94]
bash-term-in-posix-shell '[ "$url" ==' [usr/bin/mariadbd-safe:216]
# In comment so false-positive
bash-term-in-posix-shell 'let' [usr/bin/mariadbd-safe:41]

View File

@@ -5,9 +5,6 @@ incorrect-path-for-interpreter /usr/bin/env perl != /usr/bin/perl [usr/share/mar
incorrect-path-for-interpreter /usr/bin/env perl != /usr/bin/perl [usr/share/mariadb/mariadb-test/suite/funcs_1/lib/DataGen_modify.pl]
incorrect-path-for-interpreter /usr/bin/env perl != /usr/bin/perl [usr/share/mariadb/mariadb-test/suite/funcs_2/lib/gen_charset_utf8.pl]
incorrect-path-for-interpreter /usr/bin/env perl != /usr/bin/perl [usr/share/mariadb/mariadb-test/suite/rpl/extension/checksum.pl]
# This is used to check if we are running under Bash
bash-term-in-posix-shell '${BASH_VERSION' [usr/share/mysql/mariadb-test/std_data/wsrep_notify.sh:87]
bash-term-in-posix-shell '${BASH_VERSION' [usr/share/mysql/mariadb-test/std_data/wsrep_notify_ssl.sh:87]
# These files are result files and they are supposed to be
# National encoded (ISO/IEC 8859-1) not UTF-8
national-encoding [usr/share/mysql/mariadb-test/include/ctype_E05C.inc]

View File

@@ -23,6 +23,8 @@ usr/lib/mysql/plugin/ha_example.so
usr/lib/mysql/plugin/ha_test_sql_discovery.so
usr/lib/mysql/plugin/libdaemon_example.so
usr/lib/mysql/plugin/mypluglib.so
usr/lib/mysql/plugin/plugin_name_ascii.so
usr/lib/mysql/plugin/plugin_name_non_ascii.so
usr/lib/mysql/plugin/qa_auth_interface.so
usr/lib/mysql/plugin/qa_auth_server.so
usr/lib/mysql/plugin/test_sql_service.so

View File

@@ -5681,13 +5681,14 @@ static bool xtrabackup_backup_func()
msg("cd to %s", mysql_real_data_home);
encryption_plugin_backup_init(mysql_connection);
if (innodb_log_checkpoint_now) {
msg("Initiating checkpoint");
if (mysql_send_query(mysql_connection,
C_STRING_WITH_LEN("SET GLOBAL "
"innodb_log_checkpoint_now=ON;"))) {
msg("initiating checkpoint failed");
return(false);
}
/* This had better finish before recv_sys.find_checkpoint()
starts executing below. The command may not be recognised
by an old server; we can ignore a failure to execute this
performance tweak. */
xb_mysql_query(
mysql_connection,
"SET GLOBAL innodb_log_checkpoint_now=ON;",
false, false);
}
msg("open files limit requested %lu, set to %lu",
@@ -5801,13 +5802,6 @@ fail:
goto fail;
}
/* try to wait for a log checkpoint, but do not fail if the
server does not support this */
if (innodb_log_checkpoint_now != false) {
mysql_read_query_result(mysql_connection);
msg("Finished waiting for checkpoint");
}
if (!select_history()) {
goto fail;
}

View File

@@ -99,6 +99,12 @@ struct casefold_info_st
my_wc_t maxchar;
const MY_CASEFOLD_CHARACTER * const *page;
const uint16 * const *simple_weight; /* For general_ci-alike collations */
/*
TRUE if an ASCII character can be converted to a non-ASCII character
by LOWER() or UPPER(), e.g. in Turkish: LOWER('I') -> U+0131,
UPPER('i') -> U+0130.
*/
my_bool can_convert_to_non_ascii_on_casefolding;
};
@@ -299,18 +305,116 @@ extern MY_UNI_CTYPE my_uni_ctype[256];
to weights, e.g. contractions, expansions,
ignorable characters */
#define MY_CS_UPPER_EQUAL_AS_EQUAL 0x80000 /* (UPPER(x)=UPPER(y)) <=> (x=y)*/
/*
MY_CS_ASCII_CASEUP_CI means that the collation maps lower case ASCII
letters a-z to their upper case counter parts A-Z, and sorts the ASCII
range according to the code point otherwise. Therefore the underscore
(0x5F) sorts after the letters. A collation which converts upper case
letters to lower case would sort the underscore before the letters.
Sorting on the non-ASCII range can be any, not necessarily
according to the code point.
*/
#define MY_CS_ASCII_CASEUP_CI 0x100000 /* ASCII CASEUP CI sorting */
/*
MY_CS_IDENT_CASEUP_CI means that the collation maps lower case ASCII
letters a-z to their upper case counter parts A-Z, and sorts "identifier"
ranges (0-9,A-Z,_) according to the code point. As a-z are folded
to A-Z, the order is: digits < letters (case insensitive) < underscore,
i.e. the underscore (0x5F) sorts after all letters.
Sorting on the other ASCII characters is not important, sorting on
non-ASCII characters is not important.
*/
#define MY_CS_IDENT_CASEUP_CI 0x200000 /* CASEUP CI sorting, IDENT range */
/*
MY_CS_ASCII_STD_UCA means that the collation sorts all characters in the
range U+0000..U+007F like the default (not-tailored) UCA collations do:
utf8mb3_unicode_ci, utf8mb3_uca1400_ai_ci.
*/
#define MY_CS_ASCII_STD_UCA 0x400000 /* Standard UCA sorting on ASCII */
/*
MY_CS_DIGITS_STD means that the collation sorts the ASCII digits 0..9
in the code point order, and does not tailor them (no contractions,
expansions or ignorable digits). For a PAD collation it also means that
the space sorts before the digits, as a shorter string is padded with
spaces for comparison. Therefore strings consisting of ASCII digits
are compared in the same way in all collations having this flag
(with the same MY_CS_NOPAD), regardless of case sensitivity
and the order of letters.
*/
#define MY_CS_DIGITS_STD 0x800000 /* Standard sorting of 0..9 */
/*
MY_CS_ASCII_MINUS_DOT_DIGITS means MY_CS_DIGITS_STD, and additionally,
the ASCII minus (-) sorts before the ASCII dot (.), which sorts before
the digits, and, for PAD collations, the space sorts before the minus.
Therefore strings consisting of minuses, dots and digits
(e.g. decimal numbers like '-10.5') are compared in the same way
in all collations having this flag (with the same MY_CS_NOPAD).
*/
#define MY_CS_ASCII_MINUS_DOT_DIGITS 0x1000000 /* Standard order of -.0..9 */
#define MY_CHARSET_UNDEFINED 0
/* Character repertoire flags */
typedef enum enum_repertoire_t
{
MY_REPERTOIRE_NONE= 0,
MY_REPERTOIRE_ASCII= 1, /* Pure ASCII U+0000..U+007F */
MY_REPERTOIRE_EXTENDED= 2, /* Extended characters: U+0080..U+FFFF */
MY_REPERTOIRE_UNICODE30= 3 /* ASCII | EXTENDED: U+0000..U+FFFF */
MY_REPERTOIRE_NONE= 0,
/* ASCII digits 0..9 */
MY_REPERTOIRE_ASCII_DIGITS= 1,
/* ASCII letters A..Z */
MY_REPERTOIRE_ASCII_LETTERS_UPPER= 2,
/* ASCII letters a..z */
MY_REPERTOIRE_ASCII_LETTERS_LOWER= 4,
/* ASCII letters A..Z, a..z */
MY_REPERTOIRE_ASCII_LETTERS= MY_REPERTOIRE_ASCII_LETTERS_UPPER |
MY_REPERTOIRE_ASCII_LETTERS_LOWER,
/* ASCII letters and digits */
MY_REPERTOIRE_ASCII_ALNUM= MY_REPERTOIRE_ASCII_DIGITS |
MY_REPERTOIRE_ASCII_LETTERS,
/* ASCII underscore character */
MY_REPERTOIRE_ASCII_UNDERSCORE= 8,
/* A combination of alnum and underscore */
MY_REPERTOIRE_ASCII_IDENT= MY_REPERTOIRE_ASCII_ALNUM |
MY_REPERTOIRE_ASCII_UNDERSCORE,
/*
Other ASCII characters, not covered by MY_REPERTOIRE_ASCII_IDENT,
MY_REPERTOIRE_ASCII_DOT and MY_REPERTOIRE_ASCII_MINUS:
*/
MY_REPERTOIRE_ASCII_NOT_IDENT= 16,
/* Extended characters: U+0080..U+10FFFF */
MY_REPERTOIRE_EXTENDED= 32,
/* ASCII dot (full stop) character: . */
MY_REPERTOIRE_ASCII_DOT= 64,
/* ASCII minus (hyphen-minus) character: - */
MY_REPERTOIRE_ASCII_MINUS= 128,
/* Decimal numbers, e.g. '-10.5': digits, dot and minus */
MY_REPERTOIRE_ASCII_MINUS_DOT_DIGITS= MY_REPERTOIRE_ASCII_DIGITS |
MY_REPERTOIRE_ASCII_DOT |
MY_REPERTOIRE_ASCII_MINUS,
/* Entire pure ASCII: U+0000..U+007F */
MY_REPERTOIRE_ASCII= MY_REPERTOIRE_ASCII_IDENT |
MY_REPERTOIRE_ASCII_NOT_IDENT |
MY_REPERTOIRE_ASCII_DOT |
MY_REPERTOIRE_ASCII_MINUS,
/* All characters: U+0000..U+10FFFF */
MY_REPERTOIRE_UNICODE30= MY_REPERTOIRE_ASCII |
MY_REPERTOIRE_EXTENDED
} my_repertoire_t;
/*
Check if all characters of "repertoire" belong to "of",
e.g. my_repertoire_is_subset_of(rep, MY_REPERTOIRE_ASCII) means
"rep contains only ASCII".
Note, do not use "repertoire == MY_REPERTOIRE_ASCII" for this purpose,
as repertoire values are sets of bits.
*/
static inline
my_bool my_repertoire_is_subset_of(my_repertoire_t repertoire,
my_repertoire_t of)
{
return (repertoire & ~of) == 0;
}
/* ID compatibility */
typedef enum enum_collation_id_type
{
@@ -665,6 +769,54 @@ struct my_collation_handler_st
@return 1 Identical
*/
my_bool (*eq_collation)(CHARSET_INFO *self, CHARSET_INFO *other);
/*
Get collation rules on the given repertoire.
This virtual function is used for tailoring-based optimization.
If two different collations have equal rules (tailoring) on the
given repertoire, then they can be mutually substituted in a comparison
operator instead of raising an "Illegal mix of collations" error,
if the additional conditions listed below are met.
For example:
SET NAMES latin1 COLLATE latin1_swedish_ci;
CREATE VIEW v1 AS SELECT IF(cond,'Y','N') AS c1 FROM t1;
SET NAMES big5 COLLATE big5_chinese_ci;
SELECT * FROM v1 WHERE c1='Y';
Although latin1_swedish_ci and big5_chinese_ci are different collations,
their rules on the given range (i.e. MY_REPERTOIRE_ASCII_ALNUM) are
exactly the same, so it does not matter which collation to use for
comparison purposes - the result will be the same. There is no need
to raise the "Illegal mix of collations".
If "tailoring()" returns a null LEX_CSTRING {0,0}, it means this
collation can not use tailoring-based optimization in the passed
repertoire.
The tailoring() results must not be compared directly by the callers.
Use my_collations_equal_on_repertoire(), which knows how tailorings
are compared and which additional properties of the collations
(PAD/NOPAD, UCA version) must be checked.
Currently two tailorings are considered equal when the str pointers
of the returned LEX_CSTRING values are equal (not when their texts
are equal). So an implementation must return shared constant strings,
and never its own literals, even if the text of such a literal is the
same. The shared constants (my_tailoring_str_*) are defined in
strings/ctype.c and declared in strings/strings_def.h, which is not
a public header. So only the implementations inside strings/ can
return them. An implementation defined elsewhere should return {0,0}
on all repertoires, which disables the optimization for its collations.
Equal tailorings are necessary, but not sufficient for the collations
to be interchangeable. The returned string does not describe the PAD/
NOPAD attribute and the UCA version of the collation, which are
additionally checked by my_collations_equal_on_repertoire().
For MY_REPERTOIRE_NONE (the empty repertoire) the implementations
inside strings/ return the shared constant my_tailoring_str_empty:
any two collations are trivially compatible on the empty repertoire
(the additional checks above still apply).
*/
LEX_CSTRING (*tailoring)(CHARSET_INFO *self, my_repertoire_t repertoire);
};
@@ -1282,6 +1434,21 @@ struct charset_info_st
return this == rhs || (coll->eq_collation)(this, rhs);
}
/*
Check if the character set can store all ASCII characters
U+0000..U+007F. An expression with the ASCII repertoire can be safely
converted to such a character set.
- All supported multibyte character sets can store U+0000..U+007F
- All supported 7bit character sets can store U+0000..U+007F
except those marked with MY_CS_NONASCII (e.g. swe7).
Note, this is not the same as the byte level ASCII compatibility,
see my_charset_is_ascii_based().
*/
bool is_ascii_superset() const
{
return mbmaxlen > 1 || !(state & MY_CS_NONASCII);
}
#endif /* __cplusplus */
};
@@ -1864,6 +2031,8 @@ void my_string_metadata_get(MY_STRING_METADATA *metadata,
my_repertoire_t my_string_repertoire(CHARSET_INFO *cs,
const char *str, size_t len);
my_bool my_charset_is_ascii_based(CHARSET_INFO *cs);
my_bool my_collations_equal_on_repertoire(CHARSET_INFO *cs1, CHARSET_INFO *cs2,
my_repertoire_t repertoire);
my_repertoire_t my_charset_repertoire(CHARSET_INFO *cs);
uint my_strxfrm_flag_normalize(CHARSET_INFO *cs, uint flags);

View File

@@ -578,7 +578,8 @@ enum ha_base_keytype {
#define HA_NAMELEN 64 /* Max length of saved filename */
#define NO_SUCH_KEY (~(uint)0) /* used as a key no. */
typedef ulong key_part_map;
typedef uint32 key_part_map;
#define MAX_REF_PARTS sizeof(key_part_map)*8 /* Max parts used as ref */
#define HA_WHOLE_KEY (~(key_part_map)0)
/* Intern constants in databases */

View File

@@ -96,8 +96,9 @@ C_MODE_START
#define MY_ROOT_USE_VMEM 0x20000U /* init_alloc_root: use my_virtual_mem_commit */
/* Tree that should delete things automatically */
#define MY_TREE_WITH_DELETE 0x40000U
#define MY_TRACK 0x80000U /* Track tmp usage */
#define MY_TRACK_WITH_LIMIT 0x100000U /* Give error if over tmp_file_usage */
#define MY_TRY_LARGE_PAGES 0x80000U /* try to allocate large pages */
#define MY_TRACK 0x100000U /* Track tmp usage */
#define MY_TRACK_WITH_LIMIT 0x200000U /* Give error if over tmp_file_usage */
#define MY_CHECK_ERROR 1U /* Params to my_end; Check open-close */
#define MY_GIVE_INFO 2U /* Give time info about process*/
@@ -180,14 +181,19 @@ extern void my_free(void *ptr);
extern void *my_memdup(PSI_memory_key key, const void *from,size_t length,myf MyFlags);
extern char *my_strdup(PSI_memory_key key, const char *from,myf MyFlags);
extern char *my_strndup(PSI_memory_key key, const char *from, size_t length, myf MyFlags);
extern my_bool my_use_large_pages;
/**
0, or MY_TRY_LARGE_PAGES to request large pages from my_large_malloc(),
my_large_virtual_alloc(), or the my_virtual_mem_*() functions. Set once
by my_init_large_pages(), does not change thereafter.
*/
extern myf my_large_pages_flag;
int my_init_large_pages(void);
uchar *my_large_malloc(size_t *size, myf my_flags);
#ifdef _WIN32
/* On Windows, use my_virtual_mem_reserve() and my_virtual_mem_commit(). */
#else
char *my_large_virtual_alloc(size_t *size);
char *my_large_virtual_alloc(size_t *size, myf my_flags);
#endif
void my_large_free(void *ptr, size_t size);
void my_large_page_truncate(size_t *size);
@@ -945,6 +951,7 @@ extern void init_alloc_root(PSI_memory_key key, MEM_ROOT *mem_root,
extern void *alloc_root(MEM_ROOT *mem_root, size_t Size);
extern void *multi_alloc_root(MEM_ROOT *mem_root, ...);
extern void free_root(MEM_ROOT *root, myf MyFLAGS);
/* There is also dbug_get_mem_root_alloc_size() in sql/sql_test.cc */
extern void move_root(MEM_ROOT *to, MEM_ROOT *from);
extern void set_prealloc_root(MEM_ROOT *root, char *ptr);
extern void reset_root_defaults(MEM_ROOT *mem_root, size_t block_size,

View File

@@ -19,6 +19,7 @@
(reserve, commit, decommit, release)
*/
#include <stddef.h> /*size_t*/
#include <my_global.h> /*myf*/
#ifdef __cplusplus
extern "C" {
@@ -26,9 +27,9 @@ extern "C" {
enum my_vmem_prot { MY_VMEM_READONLY= 0, MY_VMEM_READWRITE };
char *my_virtual_mem_reserve(size_t *size);
char *my_virtual_mem_commit(char *ptr, size_t size);
void my_virtual_mem_decommit(char *ptr, size_t size);
char *my_virtual_mem_reserve(size_t *size, myf my_flags);
char *my_virtual_mem_commit(char *ptr, size_t size, myf my_flags);
void my_virtual_mem_decommit(char *ptr, size_t size, myf my_flags);
void my_virtual_mem_release(char *ptr, size_t size);
void my_virtual_mem_protect(void *ptr, size_t size, enum my_vmem_prot prot);

View File

@@ -471,10 +471,19 @@ typedef struct st_net {
my_bool thread_specific_malloc;
unsigned char compress;
my_bool pkt_nr_can_be_reset;
/* Bits: NET_PROXY_PROTOCOL, NET_PROXY_PROTOCOL_CONNECT_ERRORS */
my_bool using_proxy_protocol;
/* Bits: NET_PROXY_PROTOCOL, NET_PROXY_PROTOCOL_CONNECT_ERRORS,
NET_PROXY_PROTOCOL_HOST_NOT_PRIVILEGED, NET_PROXY_PROTOCOL_HOST_BLOCKED */
unsigned char using_proxy_protocol;
#define NET_PROXY_PROTOCOL 1
#define NET_PROXY_PROTOCOL_CONNECT_ERRORS 2
/*
A PROXY-header-derived peer address failed the "host privileged"/"host
blocked" check; rejection is deferred until the client's handshake
response is parsed, after SSL if requested, instead of being sent in
clear text right away.
*/
#define NET_PROXY_PROTOCOL_HOST_NOT_PRIVILEGED 4
#define NET_PROXY_PROTOCOL_HOST_BLOCKED 8
/*
Pointer to query object in query cache, do not equal NULL (0) for
queries in cache that have not stored its results yet

View File

@@ -0,0 +1,341 @@
CREATE TABLE cmp_result (
cl1 VARCHAR(64), cl2 VARCHAR(64), is_error INT, is_error_expected INT, expected_reason TEXT
) ENGINE=MyISAM;
CREATE TABLE cmp_result_all AS SELECT *, SPACE(32) AS repertoire FROM cmp_result LIMIT 0;
# Unicode collations that reorder ASCII letters
DELIMITER $$;
CREATE FUNCTION unicode_reorders_ascii_letters(cl VARCHAR(64)) RETURNS BOOL
BEGIN
/* Old collations */
CASE
WHEN cl RLIKE '^(utf8mb3|ucs2|utf8mb4|utf16|utf32)'
'_(czech|croatian|croatian_mysql561|danish|estonian|latvian|lithuanian|roman|slovak|spanish2|turkish)'
'_ci$'
THEN RETURN 1;
/* MySQL 0900 compatibility collations */
WHEN cl RLIKE '^utf8mb4'
'_(es_trad|cs|et|la|lt|lv|sk|tr)'
'_0900_ai_(ci|cs)$'
THEN RETURN 1;
/* uca1400 collations*/
WHEN cl RLIKE '^(utf8mb3|ucs2|utf8mb4|utf16|utf32)'
'_uca1400'
'_(czech|croatian|danish|estonian|latvian|lithuanian|roman|slovak|spanish2|turkish)'
'_(|nopad_)'
'(ai_cs|ai_ci|as_cs|as_ci)$'
THEN RETURN 1;
ELSE
RETURN 0;
END CASE;
RETURN 0;
END;
$$
DELIMITER ;$$
DELIMITER $$;
CREATE PROCEDURE update_expected_reasons(repertoire VARCHAR(32))
BEGIN
UPDATE cmp_result SET is_error_expected=0, expected_reason='000 cl1 = cl2' WHERE is_error_expected IS NULL AND cl1=cl2;
UPDATE cmp_result SET is_error_expected=0, expected_reason='001 LEFT binary' WHERE is_error_expected IS NULL AND cl1='binary' AND cl2<>'binary';
UPDATE cmp_result SET is_error_expected=0, expected_reason='001 RIGHT binary' WHERE is_error_expected IS NULL AND cl1<>'binary' AND cl2='binary';
UPDATE cmp_result SET is_error_expected=0, expected_reason='002 RIGHT sameCS_bin' WHERE is_error_expected IS NULL AND cl1 NOT LIKE '%_bin' AND concat(substring_index(cl1,'_',1),'_bin')=cl2;
UPDATE cmp_result SET is_error_expected=0, expected_reason='002 RIGHT sameCS_bin' WHERE is_error_expected IS NULL AND cl1 NOT LIKE '%_bin' AND concat(substring_index(cl1,'_',1),'_nopad_bin')=cl2;
UPDATE cmp_result SET is_error_expected=0, expected_reason='002 RIGHT sameCS_bin' WHERE is_error_expected IS NULL AND cl1 NOT LIKE '%_bin' AND concat(substring_index(cl1,'_',1),'_0900_bin')=cl2;
UPDATE cmp_result SET is_error_expected=0, expected_reason='002 LEFT sameCS_bin' WHERE is_error_expected IS NULL AND cl2 NOT LIKE '%_bin' AND cl1=concat(substring_index(cl2,'_',1),'_bin');
UPDATE cmp_result SET is_error_expected=0, expected_reason='002 LEFT sameCS_bin' WHERE is_error_expected IS NULL AND cl2 NOT LIKE '%_bin' AND cl1=concat(substring_index(cl2,'_',1),'_nopad_bin');
UPDATE cmp_result SET is_error_expected=0, expected_reason='002 LEFT sameCS_bin' WHERE is_error_expected IS NULL AND cl2 NOT LIKE '%_bin' AND cl1=concat(substring_index(cl2,'_',1),'_0900_bin');
UPDATE cmp_result SET is_error_expected=0, expected_reason='003 LEFT superset' WHERE is_error_expected IS NULL AND cl1 RLIKE '^(utf8mb4).*' AND cl2 NOT RLIKE '^(ucs2|utf8mb4|utf32|utf16).*';
UPDATE cmp_result SET is_error_expected=0, expected_reason='003 RIGHT superset' WHERE is_error_expected IS NULL AND cl1 NOT RLIKE '^(ucs2|utf8mb4|utf32|utf16).*' AND cl2 RLIKE '^(utf8mb4).*';
UPDATE cmp_result SET is_error_expected=0, expected_reason='003 LEFT superset' WHERE is_error_expected IS NULL AND cl1 RLIKE '^(utf16|utf32).*' AND cl2 NOT RLIKE '^(ucs2|utf8mb3|utf8mb4|utf32|utf16).*';
UPDATE cmp_result SET is_error_expected=0, expected_reason='003 RIGHT superset' WHERE is_error_expected IS NULL AND cl1 NOT RLIKE '^(ucs2|utf8mb3|utf8mb4|utf32|utf16).*' AND cl2 RLIKE '^(utf16|utf32).*';
UPDATE cmp_result SET is_error_expected=0, expected_reason='004 LEFT superset' WHERE is_error_expected IS NULL AND cl1 RLIKE '^(ucs2|utf8mb3).*' AND cl2 NOT RLIKE '^(utf8mb4|utf32|utf16|ucs2|utf8mb3).*';
UPDATE cmp_result SET is_error_expected=0, expected_reason='004 RIGHT superset' WHERE is_error_expected IS NULL AND cl1 NOT RLIKE '^(utf8mb4|utf32|utf16|utf8mb3|ucs2).*' AND cl2 RLIKE '^(ucs2|utf8mb3).*';
IF repertoire ='ascii' THEN
UPDATE cmp_result SET is_error_expected=1, expected_reason='010 sjis_bin reorders ASCII punctuation' WHERE is_error_expected IS NULL AND (cl1='sjis_bin' OR cl2='sjis_bin');
UPDATE cmp_result SET is_error_expected=1, expected_reason='010 sjis_nopad_bin reorders ASCII punctuation' WHERE is_error_expected IS NULL AND (cl1='sjis_nopad_bin' OR cl2='sjis_nopad_bin');
END IF;
IF repertoire ='ascii' THEN
/* These collations have no tailoring on the entire ASCII repertoire */
UPDATE cmp_result SET is_error_expected=1, expected_reason='010 no tailoring on the entire ASCII repertoire'
WHERE is_error_expected IS NULL
AND (cl1 RLIKE '^(big5_chinese|gb2312_chinese|gbk_chinese|sjis_japanese)' OR
cl2 RLIKE '^(big5_chinese|gb2312_chinese|gbk_chinese|sjis_japanese)');
UPDATE cmp_result SET is_error_expected=1, expected_reason='010 hp8_english_ci has anomalies on ASCII punctuation'
WHERE is_error_expected IS NULL AND (cl1='hp8_english_ci' OR cl2='hp8_english_ci');
UPDATE cmp_result SET is_error_expected=1, expected_reason='010 swe7_swedish_nopad_ci reorders ASCII punctuation'
WHERE is_error_expected IS NULL AND (cl1='swe7_swedish_nopad_ci' OR cl2='swe7_swedish_nopad_ci');
END IF;
/*
The ASCII digits are sorted in the code point order in all collations,
regardless of the order of the letters and the case sensitivity.
So on the digits repertoire only PAD vs NOPAD collations are incompatible.
*/
IF repertoire NOT IN ('digits', 'minus_dot_digits') THEN
UPDATE cmp_result SET is_error_expected=1, expected_reason='010 cp1257_lithuanian_ci reorders ASCII letters: I<Y<J' WHERE is_error_expected IS NULL AND (cl1='cp1257_lithuanian_ci' OR cl2='cp1257_lithuanian_ci');
UPDATE cmp_result SET is_error_expected=1, expected_reason='010 latin5_turkish_ci reorders ASCII letters: I<i<J' WHERE is_error_expected IS NULL AND (cl1 RLIKE '^latin5_turkish' OR cl2 RLIKE '^latin5_turkish');
UPDATE cmp_result SET is_error_expected=1, expected_reason='010 cp866_general_ci reorders ASCII letters: J<j (bug)' WHERE is_error_expected IS NULL AND (cl1='cp866_general_ci' OR cl2='cp866_general_ci');
UPDATE cmp_result SET is_error_expected=1, expected_reason='010 macce_general_ci reorders ASCII letters: M=m=N=n' WHERE is_error_expected IS NULL AND (cl1='macce_general_ci' OR cl2='macce_general_ci');
UPDATE cmp_result SET is_error_expected=1, expected_reason='010 latin7_general_ci reorders ASCII letters: t<T (bug)' WHERE is_error_expected IS NULL AND (cl1='latin7_general_ci' OR cl2='latin7_general_ci');
UPDATE cmp_result SET is_error_expected=1, expected_reason='020 reorders ASCII letters' WHERE is_error_expected IS NULL AND unicode_reorders_ascii_letters(cl1)=TRUE;
UPDATE cmp_result SET is_error_expected=1, expected_reason='020 reorders ASCII letters' WHERE is_error_expected IS NULL AND unicode_reorders_ascii_letters(cl2)=TRUE;
UPDATE cmp_result SET is_error_expected=1, expected_reason='030 diffCS cs vs bin' WHERE is_error_expected IS NULL AND cl1 RLIKE '_cs$' AND cl2 RLIKE '_bin$';
UPDATE cmp_result SET is_error_expected=1, expected_reason='030 diffCS cs vs ci' WHERE is_error_expected IS NULL AND cl1 RLIKE '_cs$' AND cl2 RLIKE '_ci$';
UPDATE cmp_result SET is_error_expected=1, expected_reason='030 diffCS ci vs cs' WHERE is_error_expected IS NULL AND cl1 RLIKE '_ci$' AND cl2 RLIKE '_cs$';
UPDATE cmp_result SET is_error_expected=1, expected_reason='030 diffCS bin vs cs' WHERE is_error_expected IS NULL AND cl1 RLIKE '_bin$' AND cl2 RLIKE '_cs$';
UPDATE cmp_result SET is_error_expected=1, expected_reason='030 diffCS ci vs bin' WHERE is_error_expected IS NULL AND cl1 RLIKE '_ci$' AND cl2 RLIKE '_bin$';
UPDATE cmp_result SET is_error_expected=1, expected_reason='030 diffCS bin vs ci' WHERE is_error_expected IS NULL AND cl1 RLIKE '_bin$' AND cl2 RLIKE '_ci$';
END IF;
UPDATE cmp_result SET is_error_expected=1, expected_reason='030 nopad vs pad' WHERE is_error_expected IS NULL AND cl1 RLIKE '_(nopad|0900)_' AND cl2 NOT RLIKE '_(nopad|0900)_';
UPDATE cmp_result SET is_error_expected=1, expected_reason='030 pad vs nopad' WHERE is_error_expected IS NULL AND cl1 NOT RLIKE '_(nopad|0900)_' AND cl2 RLIKE '_(nopad|0900)_';
/*
tis620_thai_ci and tis620_thai_nopad_ci fold letters to lower case,
so they sort the underscore before the letters.
They are compatible with other collations only on the ALNUM repertoire.
*/
IF repertoire IN ('ident','ascii') THEN
UPDATE cmp_result SET is_error_expected=1, expected_reason='040 tis620_thai_ci sorts underscore before letters'
WHERE is_error_expected IS NULL
AND ((cl1 RLIKE '^tis620_thai' AND cl2 NOT RLIKE '^tis620_thai')
OR (cl2 RLIKE '^tis620_thai' AND cl1 NOT RLIKE '^tis620_thai'));
END IF;
/*
Unicode _general_ vs UCA collations
have different position of the underscore
*/
IF repertoire IN ('ident','ascii') THEN
UPDATE cmp_result SET is_error_expected=1, expected_reason='040 different underscore position'
WHERE is_error_expected IS NULL
AND cl1 RLIKE '^(utf8mb4|utf32|utf16|utf8mb3|ucs2)_general.*'
AND cl2 RLIKE '^(utf8mb4|utf32|utf16|utf8mb3|ucs2)_(unicode|swedish|czech|uca).*';
UPDATE cmp_result SET is_error_expected=1, expected_reason='040 different underscore position'
WHERE is_error_expected IS NULL
AND cl1 RLIKE '^(utf8mb4|utf32|utf16|utf8mb3|ucs2)_(unicode|swedish|czech|uca).*'
AND cl2 RLIKE '^(utf8mb4|utf32|utf16|utf8mb3|ucs2)_(general).*';
END IF;
/*
Old UCA vs uca1400 collations have different punctuation order.
The minus and the dot are punctuation characters, so the UCA versions
must be equal on the repertoire with them.
*/
IF repertoire IN ('minus_dot_digits','ascii') THEN
UPDATE cmp_result SET is_error_expected=1, expected_reason='050 different punctuation order'
WHERE is_error_expected IS NULL
AND cl1 RLIKE '^(utf8mb4|utf32|utf16|utf8mb3|ucs2)_(unicode|swedish|czech).*'
AND cl2 RLIKE '^(utf8mb4|utf32|utf16|utf8mb3|ucs2)_(uca1400|0900).*';
UPDATE cmp_result SET is_error_expected=1, expected_reason='050 different punctuation order'
WHERE is_error_expected IS NULL
AND cl1 RLIKE '^(utf8mb4|utf32|utf16|utf8mb3|ucs2)_(uca1400|0900).*'
AND cl2 RLIKE '^(utf8mb4|utf32|utf16|utf8mb3|ucs2)_(unicode|swedish|czech).*';
END IF;
/*
All other pairs are expected to be compatible: the collations
have equal tailorings on the repertoire.
Without this update is_error_expected would stay NULL for these pairs,
and the check "is_error<>is_error_expected" would skip them.
*/
UPDATE cmp_result SET is_error_expected=0, expected_reason='100 equal tailoring' WHERE is_error_expected IS NULL;
END;
$$
DELIMITER ;$$
DELIMITER $$;
CREATE PROCEDURE check_compatibility(repertoire VARCHAR(32), param VARCHAR(32))
BEGIN
DECLARE mask VARCHAR(32) DEFAULT COALESCE(@mask,'');
DECLARE errmsg TEXT;
DECLARE c1 CURSOR FOR SELECT full_collation_name
FROM collations
ORDER BY full_collation_name;
DECLARE c2 CURSOR FOR SELECT full_collation_name
FROM collations
ORDER BY full_collation_name;
DECLARE CONTINUE HANDLER FOR 1267 /*Illegal mix of collations*/
BEGIN
GET DIAGNOSTICS CONDITION 1 errmsg = MESSAGE_TEXT;
END;
TRUNCATE TABLE cmp_result;
FOR rec1 IN c1 DO
SET @@collation_connection=rec1.full_collation_name;
EXECUTE IMMEDIATE REPLACE('CREATE VIEW v1 AS '
'SELECT ''PARAM'' AS alnum', 'PARAM', param);
SET NAMES DEFAULT;
FOR rec2 IN c2 DO
SET errmsg= NULL;
SET @@collation_connection=rec2.full_collation_name;
/* This query raises an error on incompatible collations */
IF (rec1.full_collation_name RLIKE mask OR
rec2.full_collation_name RLIKE mask)
THEN
SET @a= NULL;
EXECUTE IMMEDIATE
REPLACE('SET @a=(SELECT COUNT(*) FROM v1 WHERE v1.alnum=''PARAM'')',
'PARAM', param);
/*
is_error is set to 1 if the query raised an error, and to 2 if it
did not raise an error but did not return the expected single row.
So a wrong result is reported by "is_error<>is_error_expected",
as is_error_expected can be only 0 or 1.
*/
INSERT INTO cmp_result (cl1, cl2, is_error)
VALUES (rec1.full_collation_name,
rec2.full_collation_name,
IF(errmsg IS NOT NULL, 1, IF(@a=1, 0, 2)));
END IF;
END FOR;
DROP VIEW v1;
END FOR;
SET NAMES DEFAULT;
CALL update_expected_reasons(repertoire);
END;
$$
DELIMITER ;$$
CREATE TABLE collations (full_collation_name VARCHAR(64) NOT NULL PRIMARY KEY);
INSERT INTO collations VALUES
('latin1_general_cs'), ('latin5_turkish_ci'),
('latin1_swedish_nopad_ci'), ('swe7_swedish_nopad_ci'),
('utf8mb3_uca1400_nopad_ai_cs'),('utf8mb4_0900_as_cs'),
('latin1_nopad_bin'), ('swe7_nopad_bin'),
('latin1_german1_ci'),('latin1_swedish_ci'),
('utf8mb3_uca1400_ai_cs'),('utf32_uca1400_as_cs'),
('latin1_bin'),('latin5_bin'),
('hp8_english_ci');
INSERT INTO collations VALUES
('utf8mb3_general_ci'),('utf8mb3_general_nopad_ci'),
('utf8mb3_unicode_ci'),('utf8mb3_unicode_nopad_ci'),
('utf8mb3_bin'),('utf8mb3_nopad_bin'),
('utf8mb4_general_ci'),('utf8mb4_general_nopad_ci'),
('utf8mb4_uca1400_ai_ci'),('utf8mb4_uca1400_nopad_ai_ci'),
('utf8mb4_unicode_ci'),('utf8mb4_unicode_nopad_ci'),
('utf8mb4_bin'),('utf8mb4_nopad_bin');
DELIMITER $$;
BEGIN NOT ATOMIC
IF @extra_collations_query IS NOT NULL
THEN
EXECUTE IMMEDIATE @extra_collations_query;
END IF;
END;
$$
DELIMITER ;$$
--echo #
--echo # ASCII digits repertoire
--echo #
CALL check_compatibility('digits', '12');
SELECT * FROM cmp_result WHERE is_error<>is_error_expected;
SELECT
RPAD(cl1, 32) AS cl1, RPAD(cl2, 32) AS cl2,
is_error, is_error_expected, expected_reason
FROM cmp_result ORDER BY expected_reason,cl1, cl2;
INSERT INTO cmp_result_all SELECT *, '0_digits' FROM cmp_result;
--echo #
--echo # ASCII minus, dot and digits repertoire
--echo #
CALL check_compatibility('minus_dot_digits', '-1.5');
SELECT * FROM cmp_result WHERE is_error<>is_error_expected;
SELECT
RPAD(cl1, 32) AS cl1, RPAD(cl2, 32) AS cl2,
is_error, is_error_expected, expected_reason
FROM cmp_result ORDER BY expected_reason,cl1, cl2;
INSERT INTO cmp_result_all SELECT *, '1_minus_dot_digits' FROM cmp_result;
--echo #
--echo # ALNUM repertoire
--echo #
CALL check_compatibility('alnum', 'a1');
SELECT * FROM cmp_result WHERE is_error<>is_error_expected;
SELECT
RPAD(cl1, 32) AS cl1, RPAD(cl2, 32) AS cl2,
is_error, is_error_expected, expected_reason
FROM cmp_result ORDER BY expected_reason,cl1, cl2;
INSERT INTO cmp_result_all SELECT *, 'A_alnum' FROM cmp_result;
--echo #
--echo # IDENT repertoire
--echo #
CALL check_compatibility('ident', 'a_');
SELECT * FROM cmp_result WHERE is_error<>is_error_expected;
SELECT
RPAD(cl1, 32) AS cl1, RPAD(cl2, 32) AS cl2,
is_error, is_error_expected, expected_reason
FROM cmp_result ORDER BY expected_reason,cl1, cl2;
INSERT INTO cmp_result_all SELECT *, 'B_ident' FROM cmp_result;
--echo #
--echo # Entire ASCII-7 repertoire
--echo #
CALL check_compatibility('ascii', 'a#');
SELECT * FROM cmp_result WHERE is_error<>is_error_expected;
SELECT
RPAD(cl1, 32) AS cl1, RPAD(cl2, 32) AS cl2,
is_error, is_error_expected, expected_reason
FROM cmp_result ORDER BY expected_reason,cl1, cl2;
INSERT INTO cmp_result_all SELECT *, 'C_ascii' FROM cmp_result;
--echo #
--echo # Collation pairs having different results on different repertoires
--echo #
SELECT
RPAD(cl1,32) AS cl1, RPAD(cl2,32) AS cl2,
GROUP_CONCAT(repertoire, is_error ORDER BY repertoire) AS is_error_all
FROM cmp_result_all
GROUP BY cmp_result_all.cl1, cmp_result_all.cl2
HAVING is_error_all NOT IN
('0_digits0,1_minus_dot_digits0,A_alnum0,B_ident0,C_ascii0',
'0_digits1,1_minus_dot_digits1,A_alnum1,B_ident1,C_ascii1')
ORDER BY is_error_all;
DROP TABLE cmp_result_all;
DROP TABLE cmp_result;
DROP TABLE collations;
DROP PROCEDURE check_compatibility;
DROP PROCEDURE update_expected_reasons;
DROP FUNCTION unicode_reorders_ascii_letters;
SET @extra_collations_query=NULL;
SET @mask=NULL;

View File

@@ -0,0 +1,28 @@
# The ASCII digits repertoire. It is compatible even with collations having
# anomalies on letters, but not with a collation with a different PAD/NOPAD.
# The result is printed instead of raising the error, to show both outcomes.
--echo # ASCII digits
--disable_query_log
DELIMITER $$;
BEGIN NOT ATOMIC
DECLARE CONTINUE HANDLER FOR 1267 /*Illegal mix of collations*/
SELECT 'ER_CANT_AGGREGATE_2COLLATIONS' AS d;
SELECT d FROM v_tailoring WHERE d='1';
END;
$$
DELIMITER ;$$
--enable_query_log
--echo # ASCII minus, dot and digits
--disable_query_log
DELIMITER $$;
BEGIN NOT ATOMIC
DECLARE CONTINUE HANDLER FOR 1267 /*Illegal mix of collations*/
SELECT 'ER_CANT_AGGREGATE_2COLLATIONS' AS e;
SELECT e FROM v_tailoring WHERE e='-1.5';
END;
$$
DELIMITER ;$$
--enable_query_log
SELECT c FROM v_tailoring WHERE c='Y';
SELECT c FROM v_tailoring WHERE c<>'Y_';
SELECT c FROM v_tailoring WHERE c<>'Y+';

View File

@@ -0,0 +1,31 @@
# The ASCII digits repertoire. It is compatible even with collations having
# anomalies on letters, but not with a collation with a different PAD/NOPAD.
# The result is printed instead of raising the error, to show both outcomes.
--echo # ASCII digits
--disable_query_log
DELIMITER $$;
BEGIN NOT ATOMIC
DECLARE CONTINUE HANDLER FOR 1267 /*Illegal mix of collations*/
SELECT 'ER_CANT_AGGREGATE_2COLLATIONS' AS d;
SELECT d FROM v_tailoring WHERE d='1';
END;
$$
DELIMITER ;$$
--enable_query_log
--echo # ASCII minus, dot and digits
--disable_query_log
DELIMITER $$;
BEGIN NOT ATOMIC
DECLARE CONTINUE HANDLER FOR 1267 /*Illegal mix of collations*/
SELECT 'ER_CANT_AGGREGATE_2COLLATIONS' AS e;
SELECT e FROM v_tailoring WHERE e='-1.5';
END;
$$
DELIMITER ;$$
--enable_query_log
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT c FROM v_tailoring WHERE c='Y';
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT c FROM v_tailoring WHERE c<>'Y_';
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT c FROM v_tailoring WHERE c<>'Y+';

View File

@@ -0,0 +1,4 @@
SELECT Insert_priv FROM mysql.user WHERE Insert_priv='Y' LIMIT 0;
SELECT Insert_priv FROM mysql.user WHERE Insert_priv='Y_' LIMIT 0;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT Insert_priv FROM mysql.user WHERE Insert_priv='Y+' LIMIT 0;

View File

@@ -0,0 +1,29 @@
# The ASCII digits repertoire. It is compatible even with collations having
# anomalies on letters, but not with a collation with a different PAD/NOPAD.
# The result is printed instead of raising the error, to show both outcomes.
--echo # ASCII digits
--disable_query_log
DELIMITER $$;
BEGIN NOT ATOMIC
DECLARE CONTINUE HANDLER FOR 1267 /*Illegal mix of collations*/
SELECT 'ER_CANT_AGGREGATE_2COLLATIONS' AS d;
SELECT d FROM v_tailoring WHERE d='1';
END;
$$
DELIMITER ;$$
--enable_query_log
--echo # ASCII minus, dot and digits
--disable_query_log
DELIMITER $$;
BEGIN NOT ATOMIC
DECLARE CONTINUE HANDLER FOR 1267 /*Illegal mix of collations*/
SELECT 'ER_CANT_AGGREGATE_2COLLATIONS' AS e;
SELECT e FROM v_tailoring WHERE e='-1.5';
END;
$$
DELIMITER ;$$
--enable_query_log
SELECT c FROM v_tailoring WHERE c='Y';
SELECT c FROM v_tailoring WHERE c<>'Y_';
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT c FROM v_tailoring WHERE c<>'Y+';

View File

@@ -0,0 +1,24 @@
# Create a test view similar to mysql.user, which caused MDEV-41246:
# a latin1_swedish_ci column with the narrow repertoire ASCII_ALNUM,
# calculated by IF() from two literals. It always has exactly one row.
# The column c has the value 'Y', the column d (ASCII digits repertoire)
# has the value '1', and the column e (ASCII minus, dot and digits repertoire)
# has the value '-1.5'.
# The current client/connection character sets are preserved.
# The view is dropped by ctype_tailoring_view_drop.inc.
--disable_query_log
SET @ctype_tailoring_save_client= @@character_set_client;
SET @ctype_tailoring_save_results= @@character_set_results;
SET @ctype_tailoring_save_collation= @@collation_connection;
SET NAMES latin1 COLLATE latin1_swedish_ci;
CREATE TABLE t_tailoring (a INT);
INSERT INTO t_tailoring VALUES (1);
CREATE VIEW v_tailoring AS
SELECT IF(a=1,'Y','N') AS c, IF(a=1,'1','2') AS d,
IF(a=1,'-1.5','2.5') AS e
FROM t_tailoring;
SET @@character_set_client= @ctype_tailoring_save_client;
SET @@character_set_results= @ctype_tailoring_save_results;
SET @@collation_connection= @ctype_tailoring_save_collation;
--enable_query_log

View File

@@ -0,0 +1,7 @@
--disable_query_log
DROP VIEW v_tailoring;
DROP TABLE t_tailoring;
SET @ctype_tailoring_save_client= NULL;
SET @ctype_tailoring_save_results= NULL;
SET @ctype_tailoring_save_collation= NULL;
--enable_query_log

View File

@@ -2,11 +2,26 @@
#
# Waits for galera node to transition to READY state.
#
# Parameters
# ----------
# $galera_wait_ready_timeout (optional)
# Seconds to wait before giving up, 60 by default. Raise it around a
# restart which has to wait for a full SST, as that takes considerably
# longer than a plain restart and on a loaded machine can exceed the
# default. The value is reset here, so it only applies to the next
# sourcing of this file.
#
--enable_reconnect
--disable_query_log
--disable_result_log
let $wait_counter = 600;
if ($galera_wait_ready_timeout)
{
let $wait_counter = $($galera_wait_ready_timeout * 10);
}
while ($wait_counter)
{
--disable_abort_on_error
@@ -25,7 +40,7 @@ while ($wait_counter)
if (!$success)
{
die "Server did not transition to READY state";
die "Server did not transition to READY state in $_galera_wait_ready_timeout seconds";
}
--disable_reconnect
--enable_query_log

View File

@@ -1,5 +1,34 @@
# Kill the server the current connection is on, and wait until its process
# is really gone.
#
# USAGE
#
# [--let $kill_signal = TERM] # defaults to KILL
# --source include/kill_galera.inc
#
# $kill_signal applies to this call only and is reset afterwards. Give the
# signal by name and never by number: signal numbers are not portable, and
# "kill -9" fails as an unknown signal on FreeBSD.
#
# On return the process no longer exists, so its pid file, ports and data
# directory are free: the node can be restarted, or its grastate.dat read,
# straight away. Waiting only for the connection to drop is not enough for
# that. The connection dies as soon as the server stops serving it, which for
# a signal that lets mysqld shut down gracefully is long before the process
# actually exits, and tests used to paper over the difference with a --sleep.
#
# What this does NOT wait for is the rest of the cluster noticing. A test that
# needs the surviving nodes to have processed the loss of this one has to wait
# for that itself, on a surviving node, e.g. for wsrep_cluster_size to drop or
# for wsrep_cluster_status to become non-Primary.
--echo Killing server ...
if (!$kill_signal)
{
--let $kill_signal = KILL
}
# Write file to make mysql-test-run.pl expect the crash, but don't start it
--let $_expect_file_name= `select regexp_replace(@@tmpdir, '^.*/','')`
--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/$_expect_file_name.expect
@@ -7,14 +36,31 @@
# Kill the connected server
--disable_reconnect
--let KILL_SIGNAL_VALUE = $kill_signal
--let KILL_NODE_PIDFILE = `SELECT @@pid_file`
--perl
my $kill_sig = $ENV{'KILL_SIGNAL_VALUE'};
my $pid_filename = $ENV{'KILL_NODE_PIDFILE'};
my $mysqld_pid = `cat $pid_filename`;
chomp($mysqld_pid);
system("kill -9 $mysqld_pid");
die "No pid found in $pid_filename\n"
unless $mysqld_pid =~ /^\d+$/;
system("kill -s $kill_sig $mysqld_pid");
# Wait for the process to be gone, and not merely for it to stop
# serving connections. my_safe_process is its parent and is sitting
# in waitpid() on it, so it is reaped as soon as it exits and kill(0)
# stops finding it.
my $waited = 0;
while (kill(0, $mysqld_pid)) {
die "Server pid $mysqld_pid did not exit\n" if $waited >= 60;
select(undef, undef, undef, 0.1);
$waited += 0.1;
}
exit(0);
EOF
--let $kill_signal =
--source include/wait_until_disconnected.inc

View File

@@ -1,34 +0,0 @@
#############################################
# checks if mysqlbinlog is debug compiled
# this "cannot" be done simply by using
# have_debug.inc
#############################################
--disable_query_log
--let $temp_out_help_file=$MYSQL_TMP_DIR/mysqlbinlog_help.tmp
--exec $MYSQL_BINLOG --help>$temp_out_help_file
let log_tmp=$temp_out_help_file;
--let $temp_inc=$MYSQL_TMP_DIR/temp.inc
let inc_tmp=$temp_inc;
--perl
use strict;
my $tmp_file= $ENV{'log_tmp'} or die "log_tmp not set";
open(FILE, "$tmp_file") or die("Unable to open $tmp_file: $!\n");
my $count = () = grep(/Output debug log/g,<FILE>);
close FILE;
my $temp_inc= $ENV{'inc_tmp'} or die "temp_inc not set";
open(FILE_INC,">", "$temp_inc") or die("can't open file \"$temp_inc\": $!");
print FILE_INC '--let $is_debug= '.$count;
close FILE_INC;
EOF
--source $temp_inc
if (!$is_debug)
{
--skip mysqlbinlog needs to be debug compiled
}
--remove_file $temp_out_help_file
--remove_file $temp_inc
--enable_query_log

View File

@@ -0,0 +1,6 @@
# Truncate the ddl log by cycling BACKUP STAGE END/START on con1, so a
# subsequent print_ddl_log.inc only shows entries logged after this point.
connection con1;
BACKUP STAGE END;
BACKUP STAGE START;
connection default;

View File

@@ -52,6 +52,13 @@ openssl req -newkey rsa:4096 -keyout client-key.pem -out demoCA/client-req.pem -
openssl rsa -in client-key.pem -out client-key.pem
openssl ca -keyfile cakey.pem -days 7300 -batch -cert cacert.pem -policy policy_anything -out client-cert.pem -in demoCA/client-req.pem
# client cert with a single RDN whose value is the literal string "a/b+c"
# ('/' and '+' are separator characters some SSL libraries escape and
# some don't -- see https://github.com/wolfSSL/wolfssl/issues/11392)
openssl req -newkey rsa:4096 -keyout client-slash-cn-key.pem -out demoCA/client-slash-cn-req.pem -days 7300 -nodes -subj '/CN=a\/b\+c'
openssl rsa -in client-slash-cn-key.pem -out client-slash-cn-key.pem
openssl ca -keyfile cakey.pem -days 7300 -batch -cert cacert.pem -policy policy_anything -out client-slash-cn-cert.pem -in demoCA/client-slash-cn-req.pem
# generate combined client cert and key file
cat client-cert.pem client-key.pem > client-certkey.pem
@@ -78,10 +85,12 @@ openssl genrsa -out gcadir/root.key 4096
openssl req -new -x509 '-sha256' -key gcadir/root.key -out galera-chain-ca.pem -days 7300 -subj "/O=MariaDB/OU=MariaDB/CN=Galera Chain Root CA" -addext "basicConstraints=critical,CA:TRUE" -addext "keyUsage=critical,keyCertSign,cRLSign"
openssl genrsa -out gcadir/int.key 4096
openssl req -new '-sha256' -key gcadir/int.key -out gcadir/int.csr -subj "/O=MariaDB/OU=MariaDB/CN=Galera Chain Intermediate CA"
openssl x509 -req -in gcadir/int.csr -CA galera-chain-ca.pem -CAkey gcadir/root.key -CAcreateserial -days 7200 -sha256 -extfile <(printf "basicConstraints=critical,CA:TRUE,pathlen:0\nkeyUsage=critical,keyCertSign,cRLSign") -out gcadir/int.crt
printf "basicConstraints=critical,CA:TRUE,pathlen:0\nkeyUsage=critical,keyCertSign,cRLSign\n" > gcadir/int.ext
openssl x509 -req -in gcadir/int.csr -CA galera-chain-ca.pem -CAkey gcadir/root.key -CAcreateserial -days 7200 -sha256 -extfile gcadir/int.ext -out gcadir/int.crt
openssl genrsa -out galera-chain-key.pem 4096
openssl req -new '-sha256' -key galera-chain-key.pem -out gcadir/leaf.csr -subj "/CN=localhost"
openssl x509 -req -in gcadir/leaf.csr -CA gcadir/int.crt -CAkey gcadir/int.key -CAcreateserial -days 7100 -sha256 -extfile <(printf "basicConstraints=CA:FALSE\nkeyUsage=critical,digitalSignature,keyEncipherment\nextendedKeyUsage=serverAuth,clientAuth\nsubjectAltName=DNS:localhost,IP:127.0.0.1") -out gcadir/leaf.crt
printf "basicConstraints=CA:FALSE\nkeyUsage=critical,digitalSignature,keyEncipherment\nextendedKeyUsage=serverAuth,clientAuth\nsubjectAltName=DNS:localhost,IP:127.0.0.1\n" > gcadir/leaf.ext
openssl x509 -req -in gcadir/leaf.csr -CA gcadir/int.crt -CAkey gcadir/int.key -CAcreateserial -days 7100 -sha256 -extfile gcadir/leaf.ext -out gcadir/leaf.crt
cat gcadir/leaf.crt gcadir/int.crt > galera-chain-cert.pem
rm -rf gcadir

View File

@@ -23,7 +23,7 @@
# Tool used for executing a suite of .test file
#
# See the "MySQL Test framework manual" for more information
# https://mariadb.com/kb/en/library/mysqltest/
# https://mariadb.com/docs/server/clients-and-utilities/testing-tools/mariadb-test
#
# Please keep the test framework tools identical in all versions!
#

View File

@@ -233,9 +233,27 @@ ALTER,DATABASE,0,mysqltest,,,,0,,,
DROP,MyISAM,0,mysqltest,t90,id: 27,,0,,,
DROP,InnoDB,0,mysqltest,t91,id: 28,,0,,,
DROP,DATABASE,0,mysqltest,,,,0,,,
connection con1;
BACKUP STAGE END;
BACKUP STAGE START;
connection default;
#
# MDEV-41175 ASAN stack-buffer-overflow in add_str_to_buffer/add_name_to_buffer
#
CREATE TABLE t1 (id INT) ENGINE=MyISAM;
RENAME TABLE `#mysql50#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!`.`#mysql50#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%` TO `#mysql50#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!`.t2;
DROP DATABASE `#mysql50#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!`;
#
# Reading backup ddl log file
#
CREATE,MyISAM,0,test,t1,id: 1,,0,,,
RENAME,MyISAM,0,@0023mysql50@0023@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021,#sql1,id: 1,MyISAM,0,@0023mysql50@0023@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021,t2,id: 1
DROP,MyISAM,0,@0023mysql50@0023@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021,t2,id: 1,,0,,,
DROP,DATABASE,0,@0023mysql50@0023@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021,,,,0,,,
#
# Cleanup
#
DROP TABLE t_exists;
DROP TABLE t_exists_template;
disconnect con1;
# End of 10.11 tests

View File

@@ -31,9 +31,31 @@ CREATE TABLE IF NOT EXISTS t_exists LIKE t_exists_template;
--source include/print_ddl_log.inc
--source include/truncate_ddl_log.inc
--echo #
--echo # MDEV-41175 ASAN stack-buffer-overflow in add_str_to_buffer/add_name_to_buffer
--echo #
# A #mysql50# name is stored on disk as is, but is filename-encoded
# (up to 5 bytes per character) in the ddl log, so the record gets long
# without hitting MAX_PATH on Windows. Such names can't be created with
# SQL, so create the 5.0-style files directly.
let $MYSQLD_DATADIR= `select @@datadir`;
--mkdir $MYSQLD_DATADIR/!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
CREATE TABLE t1 (id INT) ENGINE=MyISAM;
--move_file $MYSQLD_DATADIR/test/t1.frm $MYSQLD_DATADIR/!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!/%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%.frm
--move_file $MYSQLD_DATADIR/test/t1.MYI $MYSQLD_DATADIR/!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!/%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%.MYI
--move_file $MYSQLD_DATADIR/test/t1.MYD $MYSQLD_DATADIR/!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!/%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%.MYD
RENAME TABLE `#mysql50#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!`.`#mysql50#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%` TO `#mysql50#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!`.t2;
DROP DATABASE `#mysql50#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!`;
--source include/print_ddl_log.inc
--echo #
--echo # Cleanup
--echo #
DROP TABLE t_exists;
DROP TABLE t_exists_template;
disconnect con1;
--echo # End of 10.11 tests

View File

@@ -0,0 +1,24 @@
connect con1,localhost,root,,;
BACKUP STAGE START;
connection default;
#
# MDEV-41175 ASAN stack-buffer-overflow in add_str_to_buffer/add_name_to_buffer
#
CREATE DATABASE `!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!`;
CREATE TABLE `!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!`.`@@@@@@@@@@@@@@@@@@@@` (id INT) ENGINE=MyISAM;
RENAME TABLE `!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!`.`@@@@@@@@@@@@@@@@@@@@` TO `!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!`.`%%%%%%%%%%%%%%%%%%%%`;
DROP TABLE `!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!`.`%%%%%%%%%%%%%%%%%%%%`;
DROP DATABASE `!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!`;
#
# Reading backup ddl log file
#
CREATE,DATABASE,0,@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021,,,,0,,,
CREATE,MyISAM,0,@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021,@0040@0040@0040@0040@0040@0040@0040@0040@0040@0040@0040@0040@0040@0040@0040@0040@0040@0040@0040@0040,id: 1,,0,,,
RENAME,MyISAM,0,@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021,@0040@0040@0040@0040@0040@0040@0040@0040@0040@0040@0040@0040@0040@0040@0040@0040@0040@0040@0040@0040,id: 1,MyISAM,0,@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021,@0025@0025@0025@0025@0025@0025@0025@0025@0025@0025@0025@0025@0025@0025@0025@0025@0025@0025@0025@0025,id: 1
DROP,MyISAM,0,@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021,@0025@0025@0025@0025@0025@0025@0025@0025@0025@0025@0025@0025@0025@0025@0025@0025@0025@0025@0025@0025,id: 1,,0,,,
DROP,DATABASE,0,@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021@0021,,,,0,,,
connection con1;
BACKUP STAGE END;
disconnect con1;
connection default;
# End of 10.11 tests

View File

@@ -0,0 +1,27 @@
# Logging of ddl's with long special-character identifiers under backup
# stages. Not on Windows: the file paths of these identifiers exceed MAX_PATH.
--source include/not_embedded.inc
--source include/not_windows.inc
connect (con1,localhost,root,,);
BACKUP STAGE START;
connection default;
--echo #
--echo # MDEV-41175 ASAN stack-buffer-overflow in add_str_to_buffer/add_name_to_buffer
--echo #
CREATE DATABASE `!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!`;
CREATE TABLE `!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!`.`@@@@@@@@@@@@@@@@@@@@` (id INT) ENGINE=MyISAM;
RENAME TABLE `!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!`.`@@@@@@@@@@@@@@@@@@@@` TO `!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!`.`%%%%%%%%%%%%%%%%%%%%`;
DROP TABLE `!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!`.`%%%%%%%%%%%%%%%%%%%%`;
DROP DATABASE `!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!`;
--source include/print_ddl_log.inc
connection con1;
BACKUP STAGE END;
disconnect con1;
connection default;
--echo # End of 10.11 tests

View File

@@ -1,3 +1,4 @@
call mtr.add_suppression("Host 'localhost' is not allowed to connect to this MariaDB server");
#
# MDEV-4462 mysqld gets SIGFPE when mysql.user table is empty
#

View File

@@ -1,5 +1,7 @@
source include/not_embedded.inc;
call mtr.add_suppression("Host 'localhost' is not allowed to connect to this MariaDB server");
--echo #
--echo # MDEV-4462 mysqld gets SIGFPE when mysql.user table is empty
--echo #

View File

@@ -4569,3 +4569,293 @@ a
drop view v1;
drop table t1,t2;
# End of 10.4 tests
#
# MDEV-41225: window functions and subqueries in the ORDER BY of a
# parenthesized query expression that must be wrapped into a derived table
#
CREATE TABLE t1 (c1 INT);
(SELECT 1 FROM t1 LIMIT 1)
ORDER BY PERCENTILE_DISC(1) WITHIN GROUP(ORDER BY TIME'0') OVER();
1
INSERT INTO t1 VALUES (1),(2),(3);
CREATE TABLE t2 (a INT);
INSERT INTO t2 VALUES (1),(2),(3);
# window functions must be computed over the rows left after LIMIT 2
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY c1 = MAX(c1) OVER () DESC, c1 LIMIT 1;
c1
2
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY c1 = COUNT(*) OVER () DESC, c1 LIMIT 1;
c1
2
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY LEAD(c1) OVER (ORDER BY c1) IS NULL DESC, c1 LIMIT 1;
c1
2
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY NTILE(2) OVER (ORDER BY c1) DESC, c1;
c1
2
1
((SELECT c1 FROM t1 ORDER BY c1 LIMIT 2) UNION (SELECT 3) ORDER BY c1 LIMIT 2)
ORDER BY c1 = COUNT(*) OVER () DESC, c1 LIMIT 1;
c1
2
SELECT * FROM ((SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY c1 = COUNT(*) OVER () DESC, c1 LIMIT 1) dt;
c1
2
SELECT ((SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY c1 = COUNT(*) OVER () DESC, c1 LIMIT 1) AS c;
c
2
# inner ORDER BY without LIMIT also forces the wrapping
(SELECT c1 FROM t1 ORDER BY c1)
ORDER BY c1 = MAX(c1) OVER () DESC, c1 LIMIT 1;
c1
3
# no wrapping: the tail belongs to the parenthesized select itself
(SELECT c1 FROM t1)
ORDER BY c1 = MAX(c1) OVER () DESC, c1 LIMIT 1;
c1
3
(SELECT c1 FROM t1 ORDER BY c1 DESC) LIMIT 1;
c1
3
# subqueries must be attached to the wrapping select
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY c1 = (SELECT MAX(a) - 1 FROM t2) DESC, c1 LIMIT 1;
c1
2
(SELECT c1 FROM t1 ORDER BY c1)
ORDER BY c1 = (SELECT MAX(a) - 1 FROM t2) DESC, c1 LIMIT 1;
c1
2
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY (SELECT COUNT(*) FROM t2 WHERE a > c1) LIMIT 1;
c1
2
EXPLAIN EXTENDED (SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY (SELECT COUNT(*) FROM t2 WHERE a > c1) LIMIT 1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2 100.00 Using filesort
3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00 Using where
2 DERIVED t1 ALL NULL NULL NULL NULL 3 100.00 Using filesort
Warnings:
Note 1276 Field or reference '__2.c1' of SELECT #3 was resolved in SELECT #1
Note 1003 /* select#1 */ select `__2`.`c1` AS `c1` from ((/* select#2 */ select `test`.`t1`.`c1` AS `c1` from `test`.`t1` order by `test`.`t1`.`c1` limit 2)) `__2` order by <expr_cache><`__2`.`c1`>((/* select#3 */ select count(0) from `test`.`t2` where `test`.`t2`.`a` > `__2`.`c1`)) limit 1
# t1.c1 is not visible outside of the derived table
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY (SELECT COUNT(*) FROM t2 WHERE a > t1.c1) LIMIT 1;
ERROR 42S22: Unknown column 't1.c1' in 'WHERE'
CREATE VIEW v1 AS (SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY c1 = COUNT(*) OVER () DESC, (SELECT MAX(a) FROM t2 WHERE a > c1), c1
LIMIT 1;
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `__3`.`c1` AS `c1` from (select `t1`.`c1` AS `c1` from `t1` order by `t1`.`c1` limit 2) `__3` order by `__3`.`c1` = count(0) over () desc,(select max(`t2`.`a`) from `t2` where `t2`.`a` > `__3`.`c1`),`__3`.`c1` limit 1 latin1 latin1_swedish_ci
SELECT * FROM v1;
c1
2
DROP VIEW v1;
PREPARE stmt FROM "(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY c1 = COUNT(*) OVER () DESC,
(SELECT COUNT(*) FROM t2 WHERE a > c1), c1 LIMIT 1";
EXECUTE stmt;
c1
2
EXECUTE stmt;
c1
2
DEALLOCATE PREPARE stmt;
# original query on a non-empty table
(SELECT 1 FROM t1 LIMIT 1)
ORDER BY PERCENTILE_DISC(1) WITHIN GROUP(ORDER BY TIME'0') OVER();
1
1
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY PERCENTILE_DISC(1) WITHIN GROUP(ORDER BY c1) OVER () = c1 DESC, c1
LIMIT 1;
c1
2
# locking clauses after a tail with ORDER BY
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY c1 = COUNT(*) OVER () DESC, c1 LIMIT 1 FOR UPDATE;
c1
2
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY c1 = COUNT(*) OVER () DESC, c1 LIMIT 1 LOCK IN SHARE MODE;
c1
2
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY c1 = (SELECT MAX(a) - 1 FROM t2) DESC, c1 FOR UPDATE WAIT 1;
c1
2
1
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY c1 = COUNT(*) OVER () DESC, c1 FOR UPDATE NOWAIT;
c1
2
1
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY c1 = COUNT(*) OVER () DESC, c1 LIMIT 1 FOR UPDATE SKIP LOCKED;
c1
2
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY c1 = COUNT(*) OVER () DESC, c1 LOCK IN SHARE MODE WAIT 1;
c1
2
1
(SELECT c1 FROM t1)
ORDER BY c1 = MAX(c1) OVER () DESC, c1 LIMIT 1 FOR UPDATE;
c1
3
(SELECT c1 FROM t1)
ORDER BY c1 = MAX(c1) OVER () DESC, c1 LIMIT 1 LOCK IN SHARE MODE;
c1
3
# locking clauses after a tail without ORDER BY
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2) LIMIT 1 FOR UPDATE;
c1
1
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2) LIMIT 1 LOCK IN SHARE MODE;
c1
1
(SELECT c1 FROM t1 ORDER BY c1 DESC) LIMIT 1 FOR UPDATE NOWAIT;
c1
3
(SELECT c1 FROM t1 ORDER BY c1 DESC) LIMIT 1 LOCK IN SHARE MODE;
c1
3
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2) FOR UPDATE;
c1
1
2
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2) LOCK IN SHARE MODE;
c1
1
2
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2) FOR UPDATE SKIP LOCKED;
c1
1
2
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2) LOCK IN SHARE MODE NOWAIT;
c1
1
2
# tail referring to a table of the enclosing query
SELECT a, ((SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY ABS(c1 - t2.a), c1 LIMIT 1) AS nearest
FROM t2 ORDER BY a;
a nearest
1 1
2 2
3 2
SELECT a, ((SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY (SELECT COUNT(*) FROM t2 AS x WHERE x.a >= t2.a) = c1 DESC,
c1 LIMIT 1) AS c
FROM t2 ORDER BY a;
a c
1 1
2 2
3 1
SELECT a, ((SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY c1 = COUNT(*) OVER () + t2.a - 1 DESC, c1 LIMIT 1) AS c
FROM t2 ORDER BY a;
a c
1 2
2 1
3 1
SELECT a FROM t2
WHERE a = ((SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY c1 = t2.a DESC, c1 DESC LIMIT 1)
ORDER BY a;
a
1
2
# aggregate function in the tail belongs to the wrapping select
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2) ORDER BY MAX(c1);
c1
1
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2) ORDER BY COUNT(*), c1;
c1
1
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY (SELECT MAX(a) FROM t2 WHERE a >= MAX(c1));
c1
1
(SELECT c1 FROM t1) ORDER BY MAX(c1);
c1
1
# named window of the wrapped select is not visible in the tail
(SELECT c1 FROM t1 WINDOW w AS (ORDER BY c1) ORDER BY c1 LIMIT 2)
ORDER BY ROW_NUMBER() OVER w;
ERROR HY000: Window specification with name 'w' is not defined
(SELECT c1 FROM t1 WINDOW w AS (ORDER BY c1))
ORDER BY ROW_NUMBER() OVER w DESC LIMIT 1;
c1
3
# MATCH in the tail
CREATE TABLE t3 (b VARCHAR(20), FULLTEXT (b)) ENGINE=MyISAM;
INSERT INTO t3 VALUES ('apple'),('banana'),('cherry'),('apple pie');
(SELECT b FROM t3 ORDER BY b LIMIT 3) ORDER BY MATCH(b) AGAINST ('apple');
ERROR HY000: The storage engine MEMORY doesn't support FULLTEXT indexes
(SELECT b FROM t3 ORDER BY b LIMIT 3)
ORDER BY MATCH(b) AGAINST ('cherry' IN BOOLEAN MODE) DESC, b;
ERROR HY000: The storage engine MEMORY doesn't support FULLTEXT indexes
SELECT b FROM (SELECT b FROM t3 ORDER BY b LIMIT 3) dt
ORDER BY MATCH(b) AGAINST ('cherry' IN BOOLEAN MODE) DESC, b;
ERROR HY000: The storage engine MEMORY doesn't support FULLTEXT indexes
(SELECT b FROM t3) ORDER BY MATCH(b) AGAINST ('cherry') DESC, b LIMIT 1;
b
cherry
DROP TABLE t3;
# wrapped query inside a wrapped query
((SELECT c1 FROM t1 ORDER BY c1 LIMIT 3)
ORDER BY NTILE(2) OVER (ORDER BY c1) DESC, c1 LIMIT 2)
ORDER BY c1 = COUNT(*) OVER () DESC, (SELECT MAX(a) FROM t2 WHERE a < c1), c1
LIMIT 1;
c1
1
EXPLAIN EXTENDED ((SELECT c1 FROM t1 ORDER BY c1 LIMIT 3)
ORDER BY NTILE(2) OVER (ORDER BY c1) DESC, c1 LIMIT 2)
ORDER BY c1 = COUNT(*) OVER () DESC, (SELECT MAX(a) FROM t2 WHERE a < c1), c1
LIMIT 1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived3> ALL NULL NULL NULL NULL 2 100.00 Using temporary; Using filesort
4 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00 Using where
3 DERIVED <derived2> ALL NULL NULL NULL NULL 3 100.00 Using temporary; Using filesort
2 DERIVED t1 ALL NULL NULL NULL NULL 3 100.00 Using filesort
Warnings:
Note 1276 Field or reference '__3.c1' of SELECT #4 was resolved in SELECT #1
Note 1003 /* select#1 */ select `__3`.`c1` AS `c1` from ((/* select#3 */ select `__2`.`c1` AS `c1` from ((/* select#2 */ select `test`.`t1`.`c1` AS `c1` from `test`.`t1` order by `test`.`t1`.`c1` limit 3)) `__2` order by ntile(2) over ( order by `__2`.`c1`) desc,`__2`.`c1` limit 2)) `__3` order by `__3`.`c1` = count(0) over () desc,<expr_cache><`__3`.`c1`>((/* select#4 */ select max(`test`.`t2`.`a`) from `test`.`t2` where `test`.`t2`.`a` < `__3`.`c1`)),`__3`.`c1` limit 1
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY ((SELECT a FROM t2 ORDER BY a LIMIT 2)
ORDER BY a = COUNT(*) OVER () DESC, a LIMIT 1) = c1 DESC, c1
LIMIT 1;
c1
2
# stored procedure
CREATE PROCEDURE p1()
BEGIN
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY c1 = COUNT(*) OVER () DESC,
(SELECT COUNT(*) FROM t2 WHERE a > c1), c1 LIMIT 1;
((SELECT c1 FROM t1 ORDER BY c1 LIMIT 3)
ORDER BY NTILE(2) OVER (ORDER BY c1) DESC, c1 LIMIT 2)
ORDER BY c1 = MAX(c1) OVER () DESC, c1 LIMIT 1 FOR UPDATE;
END|
CALL p1();
c1
2
c1
3
CALL p1();
c1
2
c1
3
DROP PROCEDURE p1;
DROP TABLE t1, t2;
# End of 10.11 tests

View File

@@ -2504,3 +2504,178 @@ drop table t1,t2;
--echo # End of 10.4 tests
--echo #
--echo # MDEV-41225: window functions and subqueries in the ORDER BY of a
--echo # parenthesized query expression that must be wrapped into a derived table
--echo #
CREATE TABLE t1 (c1 INT);
(SELECT 1 FROM t1 LIMIT 1)
ORDER BY PERCENTILE_DISC(1) WITHIN GROUP(ORDER BY TIME'0') OVER();
INSERT INTO t1 VALUES (1),(2),(3);
CREATE TABLE t2 (a INT);
INSERT INTO t2 VALUES (1),(2),(3);
--echo # window functions must be computed over the rows left after LIMIT 2
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY c1 = MAX(c1) OVER () DESC, c1 LIMIT 1;
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY c1 = COUNT(*) OVER () DESC, c1 LIMIT 1;
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY LEAD(c1) OVER (ORDER BY c1) IS NULL DESC, c1 LIMIT 1;
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY NTILE(2) OVER (ORDER BY c1) DESC, c1;
((SELECT c1 FROM t1 ORDER BY c1 LIMIT 2) UNION (SELECT 3) ORDER BY c1 LIMIT 2)
ORDER BY c1 = COUNT(*) OVER () DESC, c1 LIMIT 1;
SELECT * FROM ((SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY c1 = COUNT(*) OVER () DESC, c1 LIMIT 1) dt;
SELECT ((SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY c1 = COUNT(*) OVER () DESC, c1 LIMIT 1) AS c;
--echo # inner ORDER BY without LIMIT also forces the wrapping
(SELECT c1 FROM t1 ORDER BY c1)
ORDER BY c1 = MAX(c1) OVER () DESC, c1 LIMIT 1;
--echo # no wrapping: the tail belongs to the parenthesized select itself
(SELECT c1 FROM t1)
ORDER BY c1 = MAX(c1) OVER () DESC, c1 LIMIT 1;
(SELECT c1 FROM t1 ORDER BY c1 DESC) LIMIT 1;
--echo # subqueries must be attached to the wrapping select
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY c1 = (SELECT MAX(a) - 1 FROM t2) DESC, c1 LIMIT 1;
(SELECT c1 FROM t1 ORDER BY c1)
ORDER BY c1 = (SELECT MAX(a) - 1 FROM t2) DESC, c1 LIMIT 1;
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY (SELECT COUNT(*) FROM t2 WHERE a > c1) LIMIT 1;
EXPLAIN EXTENDED (SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY (SELECT COUNT(*) FROM t2 WHERE a > c1) LIMIT 1;
--echo # t1.c1 is not visible outside of the derived table
--error ER_BAD_FIELD_ERROR
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY (SELECT COUNT(*) FROM t2 WHERE a > t1.c1) LIMIT 1;
CREATE VIEW v1 AS (SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY c1 = COUNT(*) OVER () DESC, (SELECT MAX(a) FROM t2 WHERE a > c1), c1
LIMIT 1;
SHOW CREATE VIEW v1;
SELECT * FROM v1;
DROP VIEW v1;
PREPARE stmt FROM "(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY c1 = COUNT(*) OVER () DESC,
(SELECT COUNT(*) FROM t2 WHERE a > c1), c1 LIMIT 1";
EXECUTE stmt;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
--echo # original query on a non-empty table
(SELECT 1 FROM t1 LIMIT 1)
ORDER BY PERCENTILE_DISC(1) WITHIN GROUP(ORDER BY TIME'0') OVER();
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY PERCENTILE_DISC(1) WITHIN GROUP(ORDER BY c1) OVER () = c1 DESC, c1
LIMIT 1;
--echo # locking clauses after a tail with ORDER BY
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY c1 = COUNT(*) OVER () DESC, c1 LIMIT 1 FOR UPDATE;
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY c1 = COUNT(*) OVER () DESC, c1 LIMIT 1 LOCK IN SHARE MODE;
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY c1 = (SELECT MAX(a) - 1 FROM t2) DESC, c1 FOR UPDATE WAIT 1;
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY c1 = COUNT(*) OVER () DESC, c1 FOR UPDATE NOWAIT;
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY c1 = COUNT(*) OVER () DESC, c1 LIMIT 1 FOR UPDATE SKIP LOCKED;
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY c1 = COUNT(*) OVER () DESC, c1 LOCK IN SHARE MODE WAIT 1;
(SELECT c1 FROM t1)
ORDER BY c1 = MAX(c1) OVER () DESC, c1 LIMIT 1 FOR UPDATE;
(SELECT c1 FROM t1)
ORDER BY c1 = MAX(c1) OVER () DESC, c1 LIMIT 1 LOCK IN SHARE MODE;
--echo # locking clauses after a tail without ORDER BY
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2) LIMIT 1 FOR UPDATE;
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2) LIMIT 1 LOCK IN SHARE MODE;
(SELECT c1 FROM t1 ORDER BY c1 DESC) LIMIT 1 FOR UPDATE NOWAIT;
(SELECT c1 FROM t1 ORDER BY c1 DESC) LIMIT 1 LOCK IN SHARE MODE;
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2) FOR UPDATE;
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2) LOCK IN SHARE MODE;
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2) FOR UPDATE SKIP LOCKED;
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2) LOCK IN SHARE MODE NOWAIT;
--echo # tail referring to a table of the enclosing query
SELECT a, ((SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY ABS(c1 - t2.a), c1 LIMIT 1) AS nearest
FROM t2 ORDER BY a;
SELECT a, ((SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY (SELECT COUNT(*) FROM t2 AS x WHERE x.a >= t2.a) = c1 DESC,
c1 LIMIT 1) AS c
FROM t2 ORDER BY a;
SELECT a, ((SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY c1 = COUNT(*) OVER () + t2.a - 1 DESC, c1 LIMIT 1) AS c
FROM t2 ORDER BY a;
SELECT a FROM t2
WHERE a = ((SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY c1 = t2.a DESC, c1 DESC LIMIT 1)
ORDER BY a;
--echo # aggregate function in the tail belongs to the wrapping select
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2) ORDER BY MAX(c1);
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2) ORDER BY COUNT(*), c1;
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY (SELECT MAX(a) FROM t2 WHERE a >= MAX(c1));
(SELECT c1 FROM t1) ORDER BY MAX(c1);
--echo # named window of the wrapped select is not visible in the tail
--error ER_WRONG_WINDOW_SPEC_NAME
(SELECT c1 FROM t1 WINDOW w AS (ORDER BY c1) ORDER BY c1 LIMIT 2)
ORDER BY ROW_NUMBER() OVER w;
(SELECT c1 FROM t1 WINDOW w AS (ORDER BY c1))
ORDER BY ROW_NUMBER() OVER w DESC LIMIT 1;
--echo # MATCH in the tail
CREATE TABLE t3 (b VARCHAR(20), FULLTEXT (b)) ENGINE=MyISAM;
INSERT INTO t3 VALUES ('apple'),('banana'),('cherry'),('apple pie');
--error ER_TABLE_CANT_HANDLE_FT
(SELECT b FROM t3 ORDER BY b LIMIT 3) ORDER BY MATCH(b) AGAINST ('apple');
--error ER_TABLE_CANT_HANDLE_FT
(SELECT b FROM t3 ORDER BY b LIMIT 3)
ORDER BY MATCH(b) AGAINST ('cherry' IN BOOLEAN MODE) DESC, b;
--error ER_TABLE_CANT_HANDLE_FT
SELECT b FROM (SELECT b FROM t3 ORDER BY b LIMIT 3) dt
ORDER BY MATCH(b) AGAINST ('cherry' IN BOOLEAN MODE) DESC, b;
(SELECT b FROM t3) ORDER BY MATCH(b) AGAINST ('cherry') DESC, b LIMIT 1;
DROP TABLE t3;
--echo # wrapped query inside a wrapped query
((SELECT c1 FROM t1 ORDER BY c1 LIMIT 3)
ORDER BY NTILE(2) OVER (ORDER BY c1) DESC, c1 LIMIT 2)
ORDER BY c1 = COUNT(*) OVER () DESC, (SELECT MAX(a) FROM t2 WHERE a < c1), c1
LIMIT 1;
EXPLAIN EXTENDED ((SELECT c1 FROM t1 ORDER BY c1 LIMIT 3)
ORDER BY NTILE(2) OVER (ORDER BY c1) DESC, c1 LIMIT 2)
ORDER BY c1 = COUNT(*) OVER () DESC, (SELECT MAX(a) FROM t2 WHERE a < c1), c1
LIMIT 1;
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY ((SELECT a FROM t2 ORDER BY a LIMIT 2)
ORDER BY a = COUNT(*) OVER () DESC, a LIMIT 1) = c1 DESC, c1
LIMIT 1;
--echo # stored procedure
DELIMITER |;
CREATE PROCEDURE p1()
BEGIN
(SELECT c1 FROM t1 ORDER BY c1 LIMIT 2)
ORDER BY c1 = COUNT(*) OVER () DESC,
(SELECT COUNT(*) FROM t2 WHERE a > c1), c1 LIMIT 1;
((SELECT c1 FROM t1 ORDER BY c1 LIMIT 3)
ORDER BY NTILE(2) OVER (ORDER BY c1) DESC, c1 LIMIT 2)
ORDER BY c1 = MAX(c1) OVER () DESC, c1 LIMIT 1 FOR UPDATE;
END|
DELIMITER ;|
CALL p1();
CALL p1();
DROP PROCEDURE p1;
DROP TABLE t1, t2;
--echo # End of 10.11 tests

View File

@@ -1538,7 +1538,7 @@ LENGTH(a)
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` blob /*M!100301 COMPRESSED*/ NOT NULL DEFAULT ''
`a` blob /*M!100301 COMPRESSED*/ NOT NULL
) ENGINE=CSV DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
DROP TABLE t1;
@@ -3091,3 +3091,55 @@ REPLACE INTO t VALUES ('abcdefghijklm');
UPDATE t SET c=MID(c,2,4);
DROP TABLE t;
# End of 10.6 tests
#
# MDEV-40417 A column with compression enabled automatically adds DEFAULT ''
#
CREATE TABLE t (
c1 LONGTEXT COMPRESSED NOT NULL,
nc1 LONGTEXT NOT NULL,
c2 LONGTEXT COMPRESSED NOT NULL DEFAULT '',
nc2 LONGTEXT NOT NULL DEFAULT '',
c3 VARCHAR(100) COMPRESSED NOT NULL,
nc3 VARCHAR(100) NOT NULL
) ENGINE=InnoDB;
SHOW CREATE TABLE t;
Table Create Table
t CREATE TABLE `t` (
`c1` longtext /*M!100301 COMPRESSED*/ NOT NULL,
`nc1` longtext NOT NULL,
`c2` longtext /*M!100301 COMPRESSED*/ NOT NULL DEFAULT '',
`nc2` longtext NOT NULL DEFAULT '',
`c3` varchar(100) /*M!100301 COMPRESSED*/ NOT NULL,
`nc3` varchar(100) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci
SELECT COLUMN_NAME, COLUMN_DEFAULT FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t' ORDER BY ORDINAL_POSITION;
COLUMN_NAME COLUMN_DEFAULT
c1 NULL
nc1 NULL
c2 ''
nc2 ''
c3 NULL
nc3 NULL
# A compressed column must be as mandatory as an uncompressed one
INSERT INTO t (nc1) VALUES ('x');
ERROR HY000: Field 'c1' doesn't have a default value
INSERT INTO t (c1, nc1, nc3) VALUES ('x', 'x', 'x');
ERROR HY000: Field 'c3' doesn't have a default value
INSERT INTO t (c1, nc1, c3, nc3) VALUES ('x', 'x', 'x', 'x');
SELECT * FROM t;
c1 nc1 c2 nc2 c3 nc3
x x x x
DROP TABLE t;
# ALTER TABLE must not add an implicit default either
CREATE TABLE t (c LONGTEXT COMPRESSED NOT NULL DEFAULT 'x') ENGINE=InnoDB;
ALTER TABLE t MODIFY c LONGTEXT COMPRESSED NOT NULL;
ALTER TABLE t ADD c2 VARCHAR(100) COMPRESSED NOT NULL;
SHOW CREATE TABLE t;
Table Create Table
t CREATE TABLE `t` (
`c` longtext /*M!100301 COMPRESSED*/ NOT NULL,
`c2` varchar(100) /*M!100301 COMPRESSED*/ NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci
DROP TABLE t;
# End of 10.11 tests

View File

@@ -599,3 +599,37 @@ UPDATE t SET c=MID(c,2,4);
DROP TABLE t;
--echo # End of 10.6 tests
--echo #
--echo # MDEV-40417 A column with compression enabled automatically adds DEFAULT ''
--echo #
CREATE TABLE t (
c1 LONGTEXT COMPRESSED NOT NULL,
nc1 LONGTEXT NOT NULL,
c2 LONGTEXT COMPRESSED NOT NULL DEFAULT '',
nc2 LONGTEXT NOT NULL DEFAULT '',
c3 VARCHAR(100) COMPRESSED NOT NULL,
nc3 VARCHAR(100) NOT NULL
) ENGINE=InnoDB;
SHOW CREATE TABLE t;
SELECT COLUMN_NAME, COLUMN_DEFAULT FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t' ORDER BY ORDINAL_POSITION;
--echo # A compressed column must be as mandatory as an uncompressed one
--error ER_NO_DEFAULT_FOR_FIELD
INSERT INTO t (nc1) VALUES ('x');
--error ER_NO_DEFAULT_FOR_FIELD
INSERT INTO t (c1, nc1, nc3) VALUES ('x', 'x', 'x');
INSERT INTO t (c1, nc1, c3, nc3) VALUES ('x', 'x', 'x', 'x');
SELECT * FROM t;
DROP TABLE t;
--echo # ALTER TABLE must not add an implicit default either
CREATE TABLE t (c LONGTEXT COMPRESSED NOT NULL DEFAULT 'x') ENGINE=InnoDB;
ALTER TABLE t MODIFY c LONGTEXT COMPRESSED NOT NULL;
ALTER TABLE t ADD c2 VARCHAR(100) COMPRESSED NOT NULL;
SHOW CREATE TABLE t;
DROP TABLE t;
--echo # End of 10.11 tests

View File

@@ -89,3 +89,65 @@ db1 CREATE DATABASE `db1` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_uca1400_
Warnings:
Note 1105 Database 'db1' does not have a db.opt file. You can create one with ALTER DATABASE if needed
DROP DATABASE db1;
#
# MDEV-41157 CREATE DATABASE COMMENT overflows db.opt comment buffer
#
set session sql_mode='';
create database db comment '$long_comment';
Warnings:
Warning 4160 Comment for database 'db' is too long (max = 1024)
# Bug 1: put_dbopt() must not overflow when storing a truncated comment
show create database db;
Database Create Database
db CREATE DATABASE `db` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_uca1400_ai_ci COMMENT '<A x1024>'
flush tables;
# Bug 2: write_db_opt() must persist a properly terminated truncated comment
show create database db;
Database Create Database
db CREATE DATABASE `db` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_uca1400_ai_ci COMMENT '<A x1024>'
# Bug 3: load_db_opt() must clamp an overlong comment loaded from a legacy db.opt file
flush tables;
show create database db;
Database Create Database
db CREATE DATABASE `db` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_uca1400_ai_ci COMMENT '<A x1024>'
Warnings:
Warning 4160 Comment in database options file './db/db.opt' is too long (max = 1024), truncated
# Bug 3: ALTER DATABASE without COMMENT must clamp a legacy overlong comment too
flush tables;
alter database db character set 'latin1';
Warnings:
Warning 4160 Comment in database options file './db/db.opt' is too long (max = 1024), truncated
show create database db;
Database Create Database
db CREATE DATABASE `db` DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci COMMENT '<A x1024>'
drop database db;
# Bug 4: multi-byte comment must be truncated at a character boundary
set names utf8mb3;
create database dbmb comment '$mb_comment';
Warnings:
Warning 4160 Comment for database 'dbmb' is too long (max = 1024)
select char_length(schema_comment), octet_length(schema_comment)
from information_schema.schemata where schema_name='dbmb';
char_length(schema_comment) octet_length(schema_comment)
341 1023
flush tables;
select char_length(schema_comment), octet_length(schema_comment)
from information_schema.schemata where schema_name='dbmb';
char_length(schema_comment) octet_length(schema_comment)
341 1023
drop database dbmb;
# Bug 4: strict sql_mode must reject an overlong multi-byte comment
set session sql_mode='TRADITIONAL';
create database dbmb comment '$mb_comment';
ERROR HY000: Comment for database 'dbmb' is too long (max = 1024)
set session sql_mode='';
# a 1024-character multi-byte table comment must not be byte-clamped
create table test.t1 (a int) comment '$mb_table_comment';
select char_length(table_comment), octet_length(table_comment)
from information_schema.tables where table_name='t1';
char_length(table_comment) octet_length(table_comment)
1024 3072
drop table test.t1;
set names default;
set session sql_mode=default;
# End of 10.11 tests

View File

@@ -71,3 +71,70 @@ CREATE DATABASE db1;
SHOW CREATE DATABASE db1;
SHOW CREATE DATABASE db1;
DROP DATABASE db1;
--echo #
--echo # MDEV-41157 CREATE DATABASE COMMENT overflows db.opt comment buffer
--echo #
set session sql_mode='';
--let $long_comment= `select repeat('A', 4000)`
evalp create database db comment '$long_comment';
--echo # Bug 1: put_dbopt() must not overflow when storing a truncated comment
--replace_regex /A{1024}/<A x1024>/ # /\*!40100[^*]*\*/##
show create database db;
flush tables;
--echo # Bug 2: write_db_opt() must persist a properly terminated truncated comment
--replace_regex /A{1024}/<A x1024>/ # /\*!40100[^*]*\*/##
show create database db;
--echo # Bug 3: load_db_opt() must clamp an overlong comment loaded from a legacy db.opt file
--let $def_charset= `select @@character_set_server`
--let $def_collation= `select @@collation_server`
--remove_file $MARIADB_DATADIR/db/db.opt
--write_file $MARIADB_DATADIR/db/db.opt EOF eval
default-character-set=$def_charset
default-collation=$def_collation
comment=$long_comment
EOF
flush tables;
--replace_regex /A{1024}/<A x1024>/ /[\\]/\// # /\*!40100[^*]*\*/##
show create database db;
--echo # Bug 3: ALTER DATABASE without COMMENT must clamp a legacy overlong comment too
flush tables;
--replace_regex /[\\]/\//
alter database db character set 'latin1';
--replace_regex /A{1024}/<A x1024>/ # /\*!40100[^*]*\*/##
show create database db;
drop database db;
--echo # Bug 4: multi-byte comment must be truncated at a character boundary
set names utf8mb3;
--let $mb_comment= `select repeat(convert(0xE4B8AD using utf8mb3), 4000)`
evalp create database dbmb comment '$mb_comment';
select char_length(schema_comment), octet_length(schema_comment)
from information_schema.schemata where schema_name='dbmb';
flush tables;
select char_length(schema_comment), octet_length(schema_comment)
from information_schema.schemata where schema_name='dbmb';
drop database dbmb;
--echo # Bug 4: strict sql_mode must reject an overlong multi-byte comment
set session sql_mode='TRADITIONAL';
--error ER_TOO_LONG_DATABASE_COMMENT
evalp create database dbmb comment '$mb_comment';
set session sql_mode='';
--echo # a 1024-character multi-byte table comment must not be byte-clamped
--let $mb_table_comment= `select repeat(convert(0xE4B8AD using utf8mb3), 1024)`
evalp create table test.t1 (a int) comment '$mb_table_comment';
select char_length(table_comment), octet_length(table_comment)
from information_schema.tables where table_name='t1';
drop table test.t1;
set names default;
set session sql_mode=default;
--echo # End of 10.11 tests

View File

@@ -1,2 +1,8 @@
create table `...................................................`(i int);
ERROR HY000: Can't create table `test`.`...................................................` (errno: 38 "Filename too long")
#
# MDEV-28746 continued: a *relative* path can overflow MAX_PATH too
#
CREATE TABLE `NAME` (id INT);
ERROR HY000: Can't create table `test`.`NAME` (errno: 38 "Filename too long")
# End of 10.11 tests

View File

@@ -8,3 +8,17 @@
let $t = `SELECT(REPEAT('.',51))`;
--error ER_CANT_CREATE_TABLE
eval create table `$t`(i int);
--echo #
--echo # MDEV-28746 continued: a *relative* path can overflow MAX_PATH too
--echo #
# mariadbd opens table files via relative (to datadir) paths, so a short
# identifier can still overflow MAX_PATH (260) once resolved against a long
# enough datadir. '!' encodes to 5 bytes; pick the fewest of them that push
# datadir + "test\<name>.frm" (9 fixed bytes) to 260.
--let $t2= `SELECT REPEAT('!', GREATEST(1, CEIL((260 - LENGTH(@@datadir) - 9) / 5)))`
--replace_regex /!+/NAME/
--error ER_CANT_CREATE_TABLE
eval CREATE TABLE `$t2` (id INT);
--echo # End of 10.11 tests

View File

@@ -0,0 +1,24 @@
#
# MDEV-41246 "Illegal mix of collations" on the mysql.user view
#
SET NAMES armscii8 COLLATE armscii8_general_ci;
# ASCII digits
d
1
# ASCII minus, dot and digits
e
-1.5
SELECT c FROM v_tailoring WHERE c='Y';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y_';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y+';
c
Y
SET NAMES armscii8 COLLATE armscii8_bin;
SELECT c FROM v_tailoring WHERE c='Y';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (armscii8_bin,COERCIBLE) for operation '='
SET NAMES DEFAULT;
# End of 11.8 tests

View File

@@ -0,0 +1,17 @@
--echo #
--echo # MDEV-41246 "Illegal mix of collations" on the mysql.user view
--echo #
SET NAMES armscii8 COLLATE armscii8_general_ci;
--disable_service_connection
--source include/ctype_tailoring_view_create.inc
--source include/ctype_tailoring_01_probe.inc
SET NAMES armscii8 COLLATE armscii8_bin;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT c FROM v_tailoring WHERE c='Y';
--source include/ctype_tailoring_view_drop.inc
--enable_service_connection
SET NAMES DEFAULT;
--echo # End of 11.8 tests

View File

@@ -175,3 +175,27 @@ z z
~ ~
drop table t1;
End of 5.0 tests.
#
# MDEV-41246 "Illegal mix of collations" on the mysql.user view
#
SET NAMES ascii COLLATE ascii_general_ci;
# ASCII digits
d
1
# ASCII minus, dot and digits
e
-1.5
SELECT c FROM v_tailoring WHERE c='Y';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y_';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y+';
c
Y
SET NAMES ascii COLLATE ascii_bin;
SELECT c FROM v_tailoring WHERE c='Y';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (ascii_bin,COERCIBLE) for operation '='
SET NAMES DEFAULT;
# End of 11.8 tests

View File

@@ -11,3 +11,21 @@ drop table t1;
#
--echo End of 5.0 tests.
--echo #
--echo # MDEV-41246 "Illegal mix of collations" on the mysql.user view
--echo #
SET NAMES ascii COLLATE ascii_general_ci;
--disable_service_connection
--source include/ctype_tailoring_view_create.inc
--source include/ctype_tailoring_01_probe.inc
SET NAMES ascii COLLATE ascii_bin;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT c FROM v_tailoring WHERE c='Y';
--source include/ctype_tailoring_view_drop.inc
--enable_service_connection
SET NAMES DEFAULT;
--echo # End of 11.8 tests

View File

@@ -5644,3 +5644,406 @@ c1
#
# End of 10.5 tests
#
#
# MDEV-41246 "Illegal mix of collations" on the mysql.user view
#
# Two different explicit COLLATE clauses are still not accepted,
# whether the character sets are different or the same
SELECT _latin1'a' COLLATE latin1_swedish_ci = _big5'a' COLLATE big5_chinese_ci;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,EXPLICIT) and (big5_chinese_ci,EXPLICIT) for operation '='
SELECT _latin1'a' COLLATE latin1_german1_ci = _latin1'a' COLLATE latin1_swedish_ci;
ERROR HY000: Illegal mix of collations (latin1_german1_ci,EXPLICIT) and (latin1_swedish_ci,EXPLICIT) for operation '='
SET NAMES big5 COLLATE big5_chinese_ci;
SELECT Insert_priv FROM mysql.user WHERE Insert_priv='Y' LIMIT 0;
Insert_priv
SELECT Insert_priv FROM mysql.user WHERE Insert_priv='Y_' LIMIT 0;
Insert_priv
SELECT Insert_priv FROM mysql.user WHERE Insert_priv='Y+' LIMIT 0;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (big5_chinese_ci,COERCIBLE) for operation '='
# Same as above, but using BETWEEN (3-operand aggregation)
SELECT Insert_priv FROM mysql.user WHERE Insert_priv BETWEEN 'A' AND 'Z' LIMIT 0;
Insert_priv
SELECT Insert_priv FROM mysql.user WHERE Insert_priv BETWEEN 'A' AND 'Z_' LIMIT 0;
Insert_priv
SELECT Insert_priv FROM mysql.user WHERE Insert_priv BETWEEN 'A_' AND 'Z' LIMIT 0;
Insert_priv
SELECT Insert_priv FROM mysql.user WHERE Insert_priv BETWEEN 'A' AND 'Z+' LIMIT 0;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE), (big5_chinese_ci,COERCIBLE), (big5_chinese_ci,COERCIBLE) for operation 'between'
SELECT Insert_priv FROM mysql.user WHERE Insert_priv BETWEEN 'A+' AND 'Z' LIMIT 0;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE), (big5_chinese_ci,COERCIBLE), (big5_chinese_ci,COERCIBLE) for operation 'between'
# Same as above, but using IN() (N-operand aggregation)
SELECT Insert_priv FROM mysql.user WHERE Insert_priv IN ('Y','N') LIMIT 0;
Insert_priv
SELECT Insert_priv FROM mysql.user WHERE Insert_priv IN ('Y_','N') LIMIT 0;
Insert_priv
SELECT Insert_priv FROM mysql.user WHERE Insert_priv IN ('Y','N+') LIMIT 0;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE), (big5_chinese_ci,COERCIBLE), (big5_chinese_ci,COERCIBLE) for operation 'in'
SELECT Insert_priv FROM mysql.user WHERE Insert_priv IN ('Y+','N') LIMIT 0;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE), (big5_chinese_ci,COERCIBLE), (big5_chinese_ci,COERCIBLE) for operation 'in'
# Same as above, but using STRCMP()
SELECT STRCMP(Insert_priv,'Y') FROM mysql.user LIMIT 0;
STRCMP(Insert_priv,'Y')
SELECT STRCMP(Insert_priv,'Y_') FROM mysql.user LIMIT 0;
STRCMP(Insert_priv,'Y_')
SELECT STRCMP(Insert_priv,'Y+') FROM mysql.user LIMIT 0;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (big5_chinese_ci,COERCIBLE) for operation 'strcmp'
# Same as above, but using LOCATE()/POSITION()/INSTR()
SELECT LOCATE('Y',Insert_priv) FROM mysql.user LIMIT 0;
LOCATE('Y',Insert_priv)
SELECT LOCATE('Y_',Insert_priv) FROM mysql.user LIMIT 0;
LOCATE('Y_',Insert_priv)
SELECT LOCATE('Y+',Insert_priv) FROM mysql.user LIMIT 0;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (big5_chinese_ci,COERCIBLE) for operation 'locate'
SELECT POSITION('Y' IN Insert_priv) FROM mysql.user LIMIT 0;
POSITION('Y' IN Insert_priv)
SELECT POSITION('Y+' IN Insert_priv) FROM mysql.user LIMIT 0;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (big5_chinese_ci,COERCIBLE) for operation 'locate'
SELECT INSTR(Insert_priv,'Y') FROM mysql.user LIMIT 0;
INSTR(Insert_priv,'Y')
SELECT INSTR(Insert_priv,'Y+') FROM mysql.user LIMIT 0;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (big5_chinese_ci,COERCIBLE) for operation 'locate'
# Same as above, but using FIELD()
SELECT FIELD(Insert_priv,'Y','N') FROM mysql.user LIMIT 0;
FIELD(Insert_priv,'Y','N')
SELECT FIELD(Insert_priv,'Y_','N') FROM mysql.user LIMIT 0;
FIELD(Insert_priv,'Y_','N')
SELECT FIELD(Insert_priv,'Y','N+') FROM mysql.user LIMIT 0;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE), (big5_chinese_ci,COERCIBLE), (big5_chinese_ci,COERCIBLE) for operation 'field'
SELECT FIELD(Insert_priv,'Y+','N') FROM mysql.user LIMIT 0;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE), (big5_chinese_ci,COERCIBLE), (big5_chinese_ci,COERCIBLE) for operation 'field'
# Same as above, but using FIND_IN_SET()
# (a single-value haystack, so the ',' separator does not
# itself force a wider repertoire)
SELECT FIND_IN_SET(Insert_priv,'Y') FROM mysql.user LIMIT 0;
FIND_IN_SET(Insert_priv,'Y')
SELECT FIND_IN_SET(Insert_priv,'Y_') FROM mysql.user LIMIT 0;
FIND_IN_SET(Insert_priv,'Y_')
SELECT FIND_IN_SET(Insert_priv,'Y+') FROM mysql.user LIMIT 0;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (big5_chinese_ci,COERCIBLE) for operation 'find_in_set'
# Same as above, but using LIKE
SELECT Insert_priv FROM mysql.user WHERE Insert_priv LIKE 'Y' LIMIT 0;
Insert_priv
SELECT Insert_priv FROM mysql.user WHERE Insert_priv LIKE 'Y_' LIMIT 0;
Insert_priv
SELECT Insert_priv FROM mysql.user WHERE Insert_priv LIKE 'Y+' LIMIT 0;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (big5_chinese_ci,COERCIBLE) for operation 'like'
# Same as above, but using RLIKE
SELECT Insert_priv FROM mysql.user WHERE Insert_priv RLIKE 'Y' LIMIT 0;
Insert_priv
SELECT Insert_priv FROM mysql.user WHERE Insert_priv RLIKE 'Y_' LIMIT 0;
Insert_priv
SELECT Insert_priv FROM mysql.user WHERE Insert_priv RLIKE 'Y+' LIMIT 0;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (big5_chinese_ci,COERCIBLE) for operation 'regexp'
# Same as above, but using REGEXP_INSTR()
SELECT REGEXP_INSTR(Insert_priv,'Y') FROM mysql.user LIMIT 0;
REGEXP_INSTR(Insert_priv,'Y')
SELECT REGEXP_INSTR(Insert_priv,'Y_') FROM mysql.user LIMIT 0;
REGEXP_INSTR(Insert_priv,'Y_')
SELECT REGEXP_INSTR(Insert_priv,'Y+') FROM mysql.user LIMIT 0;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (big5_chinese_ci,COERCIBLE) for operation 'regexp_instr'
# Same as above, but using MATCH ... AGAINST().
# Unlike the other comparison functions above, MATCH ... AGAINST()
# does not aggregate the AGAINST phrase's collation for the illegal-mix
# check: Item_func_match::fix_fields() calls
# agg_arg_charsets_for_comparison() on args+1 (the indexed column(s)
# only), skipping args[0], which is the AGAINST phrase (key_item()).
# The phrase is instead silently converted to the column's collation
# (search_value), so none of the queries below raise an error, even
# with a _bin column.
CREATE TABLE t1 (a VARCHAR(200) CHARACTER SET latin1 COLLATE latin1_swedish_ci,
FULLTEXT(a));
INSERT INTO t1 VALUES ('Y'),('N');
SET NAMES big5 COLLATE big5_chinese_ci;
SELECT MATCH(a) AGAINST('Y') FROM t1;
MATCH(a) AGAINST('Y')
0
0
SELECT MATCH(a) AGAINST('Y_') FROM t1;
MATCH(a) AGAINST('Y_')
0
0
SELECT MATCH(a) AGAINST('Y+') FROM t1;
MATCH(a) AGAINST('Y+')
0
0
DROP TABLE t1;
CREATE TABLE t1 (a VARCHAR(200) CHARACTER SET latin1 COLLATE latin1_bin,
FULLTEXT(a));
INSERT INTO t1 VALUES ('Y'),('N');
SELECT MATCH(a) AGAINST('Y') FROM t1;
MATCH(a) AGAINST('Y')
0
0
DROP TABLE t1;
# Same as above, but using the simple CASE operator
SELECT CASE Insert_priv WHEN 'Y' THEN 1 WHEN 'N' THEN 0 END FROM mysql.user LIMIT 0;
CASE Insert_priv WHEN 'Y' THEN 1 WHEN 'N' THEN 0 END
SELECT CASE Insert_priv WHEN 'Y_' THEN 1 WHEN 'N' THEN 0 END FROM mysql.user LIMIT 0;
CASE Insert_priv WHEN 'Y_' THEN 1 WHEN 'N' THEN 0 END
SELECT CASE Insert_priv WHEN 'Y' THEN 1 WHEN 'N+' THEN 0 END FROM mysql.user LIMIT 0;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE), (big5_chinese_ci,COERCIBLE), (big5_chinese_ci,COERCIBLE) for operation 'case'
SELECT CASE Insert_priv WHEN 'Y+' THEN 1 WHEN 'N' THEN 0 END FROM mysql.user LIMIT 0;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE), (big5_chinese_ci,COERCIBLE), (big5_chinese_ci,COERCIBLE) for operation 'case'
SET NAMES big5 COLLATE big5_bin;
SELECT Insert_priv FROM mysql.user WHERE Insert_priv='Y' LIMIT 0;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (big5_bin,COERCIBLE) for operation '='
SELECT Insert_priv FROM mysql.user WHERE Insert_priv LIKE 'Y' LIMIT 0;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (big5_bin,COERCIBLE) for operation 'like'
SELECT Insert_priv FROM mysql.user WHERE Insert_priv RLIKE 'Y' LIMIT 0;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (big5_bin,COERCIBLE) for operation 'regexp'
SELECT REGEXP_INSTR(Insert_priv,'Y') FROM mysql.user LIMIT 0;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (big5_bin,COERCIBLE) for operation 'regexp_instr'
SELECT Insert_priv FROM mysql.user WHERE Insert_priv BETWEEN 'A' AND 'Z' LIMIT 0;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE), (big5_bin,COERCIBLE), (big5_bin,COERCIBLE) for operation 'between'
SELECT Insert_priv FROM mysql.user WHERE Insert_priv IN ('Y','N') LIMIT 0;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE), (big5_bin,COERCIBLE), (big5_bin,COERCIBLE) for operation 'in'
SELECT STRCMP(Insert_priv,'Y') FROM mysql.user LIMIT 0;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (big5_bin,COERCIBLE) for operation 'strcmp'
SELECT LOCATE('Y',Insert_priv) FROM mysql.user LIMIT 0;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (big5_bin,COERCIBLE) for operation 'locate'
SELECT FIELD(Insert_priv,'Y','N') FROM mysql.user LIMIT 0;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE), (big5_bin,COERCIBLE), (big5_bin,COERCIBLE) for operation 'field'
SELECT FIND_IN_SET(Insert_priv,'Y') FROM mysql.user LIMIT 0;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (big5_bin,COERCIBLE) for operation 'find_in_set'
SELECT CASE Insert_priv WHEN 'Y' THEN 1 WHEN 'N' THEN 0 END FROM mysql.user LIMIT 0;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE), (big5_bin,COERCIBLE), (big5_bin,COERCIBLE) for operation 'case'
#
# The same checks using an own view instead of mysql.user.
# The view has exactly one row, so every query below returns
# a row, or raises an error.
#
SET NAMES big5 COLLATE big5_chinese_ci;
# ASCII digits
d
1
# ASCII minus, dot and digits
e
-1.5
SELECT c FROM v_tailoring WHERE c='Y';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y_';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y+';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (big5_chinese_ci,COERCIBLE) for operation '<>'
# Same as above, but using BETWEEN (3-operand aggregation)
SELECT c FROM v_tailoring WHERE c BETWEEN 'A' AND 'Z';
c
Y
SELECT c FROM v_tailoring WHERE c BETWEEN 'A' AND 'Z_';
c
Y
SELECT c FROM v_tailoring WHERE c BETWEEN 'A_' AND 'Z';
c
Y
SELECT c FROM v_tailoring WHERE c BETWEEN 'A' AND 'Z+';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE), (big5_chinese_ci,COERCIBLE), (big5_chinese_ci,COERCIBLE) for operation 'between'
SELECT c FROM v_tailoring WHERE c BETWEEN 'A+' AND 'Z';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE), (big5_chinese_ci,COERCIBLE), (big5_chinese_ci,COERCIBLE) for operation 'between'
# Same as above, but using IN() (N-operand aggregation)
SELECT c FROM v_tailoring WHERE c IN ('Y','N');
c
Y
SELECT c FROM v_tailoring WHERE c NOT IN ('Y_','N');
c
Y
SELECT c FROM v_tailoring WHERE c IN ('Y','N+');
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE), (big5_chinese_ci,COERCIBLE), (big5_chinese_ci,COERCIBLE) for operation 'in'
SELECT c FROM v_tailoring WHERE c NOT IN ('Y+','N');
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE), (big5_chinese_ci,COERCIBLE), (big5_chinese_ci,COERCIBLE) for operation 'in'
# Same as above, but using STRCMP()
SELECT STRCMP(c,'Y') FROM v_tailoring;
STRCMP(c,'Y')
0
SELECT STRCMP(c,'Y_') FROM v_tailoring;
STRCMP(c,'Y_')
-1
SELECT STRCMP(c,'Y+') FROM v_tailoring;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (big5_chinese_ci,COERCIBLE) for operation 'strcmp'
# Same as above, but using LOCATE()/POSITION()/INSTR()
SELECT LOCATE('Y',c) FROM v_tailoring;
LOCATE('Y',c)
1
SELECT LOCATE('Y_',c) FROM v_tailoring;
LOCATE('Y_',c)
0
SELECT LOCATE('Y+',c) FROM v_tailoring;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (big5_chinese_ci,COERCIBLE) for operation 'locate'
SELECT POSITION('Y' IN c) FROM v_tailoring;
POSITION('Y' IN c)
1
SELECT POSITION('Y+' IN c) FROM v_tailoring;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (big5_chinese_ci,COERCIBLE) for operation 'locate'
SELECT INSTR(c,'Y') FROM v_tailoring;
INSTR(c,'Y')
1
SELECT INSTR(c,'Y+') FROM v_tailoring;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (big5_chinese_ci,COERCIBLE) for operation 'locate'
# Same as above, but using FIELD()
SELECT FIELD(c,'Y','N') FROM v_tailoring;
FIELD(c,'Y','N')
1
SELECT FIELD(c,'Y_','N') FROM v_tailoring;
FIELD(c,'Y_','N')
0
SELECT FIELD(c,'Y','N+') FROM v_tailoring;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE), (big5_chinese_ci,COERCIBLE), (big5_chinese_ci,COERCIBLE) for operation 'field'
SELECT FIELD(c,'Y+','N') FROM v_tailoring;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE), (big5_chinese_ci,COERCIBLE), (big5_chinese_ci,COERCIBLE) for operation 'field'
# Same as above, but using FIND_IN_SET()
# (a single-value haystack, so the ',' separator does not
# itself force a wider repertoire)
SELECT FIND_IN_SET(c,'Y') FROM v_tailoring;
FIND_IN_SET(c,'Y')
1
SELECT FIND_IN_SET(c,'Y_') FROM v_tailoring;
FIND_IN_SET(c,'Y_')
0
SELECT FIND_IN_SET(c,'Y+') FROM v_tailoring;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (big5_chinese_ci,COERCIBLE) for operation 'find_in_set'
# Same as above, but using LIKE
SELECT c FROM v_tailoring WHERE c LIKE 'Y';
c
Y
SELECT c FROM v_tailoring WHERE c NOT LIKE 'Y_';
c
Y
SELECT c FROM v_tailoring WHERE c NOT LIKE 'Y+';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (big5_chinese_ci,COERCIBLE) for operation 'like'
# Same as above, but using RLIKE
SELECT c FROM v_tailoring WHERE c RLIKE 'Y';
c
Y
SELECT c FROM v_tailoring WHERE c NOT RLIKE 'Y_';
c
Y
SELECT c FROM v_tailoring WHERE c RLIKE 'Y+';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (big5_chinese_ci,COERCIBLE) for operation 'regexp'
# Same as above, but using REGEXP_INSTR()
SELECT REGEXP_INSTR(c,'Y') FROM v_tailoring;
REGEXP_INSTR(c,'Y')
1
SELECT REGEXP_INSTR(c,'Y_') FROM v_tailoring;
REGEXP_INSTR(c,'Y_')
0
SELECT REGEXP_INSTR(c,'Y+') FROM v_tailoring;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (big5_chinese_ci,COERCIBLE) for operation 'regexp_instr'
# Same as above, but using the simple CASE operator
SELECT CASE c WHEN 'Y' THEN 1 WHEN 'N' THEN 0 END FROM v_tailoring;
CASE c WHEN 'Y' THEN 1 WHEN 'N' THEN 0 END
1
SELECT CASE c WHEN 'Y_' THEN 1 WHEN 'N' THEN 0 END FROM v_tailoring;
CASE c WHEN 'Y_' THEN 1 WHEN 'N' THEN 0 END
NULL
SELECT CASE c WHEN 'Y' THEN 1 WHEN 'N+' THEN 0 END FROM v_tailoring;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE), (big5_chinese_ci,COERCIBLE), (big5_chinese_ci,COERCIBLE) for operation 'case'
SELECT CASE c WHEN 'Y+' THEN 1 WHEN 'N' THEN 0 END FROM v_tailoring;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE), (big5_chinese_ci,COERCIBLE), (big5_chinese_ci,COERCIBLE) for operation 'case'
SET NAMES big5 COLLATE big5_bin;
SELECT c FROM v_tailoring WHERE c='Y';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (big5_bin,COERCIBLE) for operation '='
SELECT c FROM v_tailoring WHERE c LIKE 'Y';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (big5_bin,COERCIBLE) for operation 'like'
SELECT c FROM v_tailoring WHERE c RLIKE 'Y';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (big5_bin,COERCIBLE) for operation 'regexp'
SELECT REGEXP_INSTR(c,'Y') FROM v_tailoring;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (big5_bin,COERCIBLE) for operation 'regexp_instr'
SELECT c FROM v_tailoring WHERE c BETWEEN 'A' AND 'Z';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE), (big5_bin,COERCIBLE), (big5_bin,COERCIBLE) for operation 'between'
SELECT c FROM v_tailoring WHERE c IN ('Y','N');
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE), (big5_bin,COERCIBLE), (big5_bin,COERCIBLE) for operation 'in'
SELECT STRCMP(c,'Y') FROM v_tailoring;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (big5_bin,COERCIBLE) for operation 'strcmp'
SELECT LOCATE('Y',c) FROM v_tailoring;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (big5_bin,COERCIBLE) for operation 'locate'
SELECT FIELD(c,'Y','N') FROM v_tailoring;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE), (big5_bin,COERCIBLE), (big5_bin,COERCIBLE) for operation 'field'
SELECT FIND_IN_SET(c,'Y') FROM v_tailoring;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (big5_bin,COERCIBLE) for operation 'find_in_set'
SELECT CASE c WHEN 'Y' THEN 1 WHEN 'N' THEN 0 END FROM v_tailoring;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE), (big5_bin,COERCIBLE), (big5_bin,COERCIBLE) for operation 'case'
# The originally reported scenario: a view is created under latin1
# and queried under big5. The comparison must return the right rows.
SET NAMES latin1 COLLATE latin1_swedish_ci;
CREATE VIEW v1 AS SELECT 'Y' AS c1 UNION SELECT 'N';
SET NAMES big5 COLLATE big5_chinese_ci;
SELECT * FROM v1 WHERE c1='y';
c1
Y
SELECT * FROM v1 WHERE c1='Y';
c1
Y
SELECT * FROM v1 WHERE 'n'=c1;
c1
N
SELECT * FROM v1 WHERE c1='N';
c1
N
SELECT * FROM v1 WHERE c1='x';
c1
SELECT * FROM v1 WHERE c1 IN ('y','n') ORDER BY c1;
c1
N
Y
SELECT * FROM v1 WHERE c1 BETWEEN 'm' AND 'z' ORDER BY c1;
c1
N
Y
# The same view with prepared statement parameters.
# A parameter with a non-ALNUM value makes the collations incompatible.
PREPARE stmt FROM 'SELECT c1 FROM v1 WHERE c1=? ORDER BY c1';
SET @y='y', @n='N', @y_plus='Y+';
EXECUTE stmt USING @y;
c1
Y
EXECUTE stmt USING @n;
c1
N
EXECUTE stmt USING @y_plus;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (big5_chinese_ci,COERCIBLE) for operation '='
EXECUTE stmt USING 'y';
c1
Y
EXECUTE stmt USING 'x';
c1
DEALLOCATE PREPARE stmt;
PREPARE stmt FROM 'SELECT c1 FROM v1 WHERE c1 IN (?,?) ORDER BY c1';
EXECUTE stmt USING 'y', 'n';
c1
N
Y
EXECUTE stmt USING 'y', 'Y+';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE), (big5_chinese_ci,COERCIBLE), (big5_chinese_ci,COERCIBLE) for operation 'in'
DEALLOCATE PREPARE stmt;
EXECUTE IMMEDIATE 'SELECT c1 FROM v1 WHERE c1=?' USING 'y';
c1
Y
EXECUTE IMMEDIATE 'SELECT c1 FROM v1 WHERE c1=?' USING 'Y+';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (big5_chinese_ci,COERCIBLE) for operation '='
DROP VIEW v1;
# Prepared statement parameters compared to a literal of another charset.
# A parameter with a non-ALNUM value makes the collations incompatible.
PREPARE stmt FROM 'SELECT _latin1''Y'' = ? AS r';
EXECUTE stmt USING @y;
r
1
EXECUTE stmt USING @n;
r
0
EXECUTE stmt USING @y_plus;
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (big5_chinese_ci,COERCIBLE) for operation '='
DEALLOCATE PREPARE stmt;
PREPARE stmt FROM 'SELECT _latin1''Y+'' = ? AS r';
EXECUTE stmt USING 'y';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (big5_chinese_ci,COERCIBLE) for operation '='
EXECUTE stmt USING 'Y+';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (big5_chinese_ci,COERCIBLE) for operation '='
DEALLOCATE PREPARE stmt;
EXECUTE IMMEDIATE 'SELECT _latin1''Y'' = ? AS r' USING 'y';
r
1
EXECUTE IMMEDIATE 'SELECT _latin1''Y'' = ? AS r' USING 'Y+';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (big5_chinese_ci,COERCIBLE) for operation '='
SET NAMES DEFAULT;
# End of 11.8 tests

View File

@@ -297,3 +297,311 @@ select strcmp(_big5'' collate big5_nopad_bin, _big5 0x0001050001) as c1;
--echo #
--echo # End of 10.5 tests
--echo #
--echo #
--echo # MDEV-41246 "Illegal mix of collations" on the mysql.user view
--echo #
--echo # Two different explicit COLLATE clauses are still not accepted,
--echo # whether the character sets are different or the same
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT _latin1'a' COLLATE latin1_swedish_ci = _big5'a' COLLATE big5_chinese_ci;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT _latin1'a' COLLATE latin1_german1_ci = _latin1'a' COLLATE latin1_swedish_ci;
SET NAMES big5 COLLATE big5_chinese_ci;
--disable_service_connection
--source include/ctype_tailoring_03_mysql_user_Insert_priv_last_error.inc
--echo # Same as above, but using BETWEEN (3-operand aggregation)
SELECT Insert_priv FROM mysql.user WHERE Insert_priv BETWEEN 'A' AND 'Z' LIMIT 0;
SELECT Insert_priv FROM mysql.user WHERE Insert_priv BETWEEN 'A' AND 'Z_' LIMIT 0;
SELECT Insert_priv FROM mysql.user WHERE Insert_priv BETWEEN 'A_' AND 'Z' LIMIT 0;
--error ER_CANT_AGGREGATE_3COLLATIONS
SELECT Insert_priv FROM mysql.user WHERE Insert_priv BETWEEN 'A' AND 'Z+' LIMIT 0;
--error ER_CANT_AGGREGATE_3COLLATIONS
SELECT Insert_priv FROM mysql.user WHERE Insert_priv BETWEEN 'A+' AND 'Z' LIMIT 0;
--echo # Same as above, but using IN() (N-operand aggregation)
SELECT Insert_priv FROM mysql.user WHERE Insert_priv IN ('Y','N') LIMIT 0;
SELECT Insert_priv FROM mysql.user WHERE Insert_priv IN ('Y_','N') LIMIT 0;
--error ER_CANT_AGGREGATE_3COLLATIONS
SELECT Insert_priv FROM mysql.user WHERE Insert_priv IN ('Y','N+') LIMIT 0;
--error ER_CANT_AGGREGATE_3COLLATIONS
SELECT Insert_priv FROM mysql.user WHERE Insert_priv IN ('Y+','N') LIMIT 0;
--echo # Same as above, but using STRCMP()
SELECT STRCMP(Insert_priv,'Y') FROM mysql.user LIMIT 0;
SELECT STRCMP(Insert_priv,'Y_') FROM mysql.user LIMIT 0;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT STRCMP(Insert_priv,'Y+') FROM mysql.user LIMIT 0;
--echo # Same as above, but using LOCATE()/POSITION()/INSTR()
SELECT LOCATE('Y',Insert_priv) FROM mysql.user LIMIT 0;
SELECT LOCATE('Y_',Insert_priv) FROM mysql.user LIMIT 0;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT LOCATE('Y+',Insert_priv) FROM mysql.user LIMIT 0;
SELECT POSITION('Y' IN Insert_priv) FROM mysql.user LIMIT 0;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT POSITION('Y+' IN Insert_priv) FROM mysql.user LIMIT 0;
SELECT INSTR(Insert_priv,'Y') FROM mysql.user LIMIT 0;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT INSTR(Insert_priv,'Y+') FROM mysql.user LIMIT 0;
--echo # Same as above, but using FIELD()
SELECT FIELD(Insert_priv,'Y','N') FROM mysql.user LIMIT 0;
SELECT FIELD(Insert_priv,'Y_','N') FROM mysql.user LIMIT 0;
--error ER_CANT_AGGREGATE_3COLLATIONS
SELECT FIELD(Insert_priv,'Y','N+') FROM mysql.user LIMIT 0;
--error ER_CANT_AGGREGATE_3COLLATIONS
SELECT FIELD(Insert_priv,'Y+','N') FROM mysql.user LIMIT 0;
--echo # Same as above, but using FIND_IN_SET()
--echo # (a single-value haystack, so the ',' separator does not
--echo # itself force a wider repertoire)
SELECT FIND_IN_SET(Insert_priv,'Y') FROM mysql.user LIMIT 0;
SELECT FIND_IN_SET(Insert_priv,'Y_') FROM mysql.user LIMIT 0;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT FIND_IN_SET(Insert_priv,'Y+') FROM mysql.user LIMIT 0;
--echo # Same as above, but using LIKE
SELECT Insert_priv FROM mysql.user WHERE Insert_priv LIKE 'Y' LIMIT 0;
SELECT Insert_priv FROM mysql.user WHERE Insert_priv LIKE 'Y_' LIMIT 0;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT Insert_priv FROM mysql.user WHERE Insert_priv LIKE 'Y+' LIMIT 0;
--echo # Same as above, but using RLIKE
SELECT Insert_priv FROM mysql.user WHERE Insert_priv RLIKE 'Y' LIMIT 0;
SELECT Insert_priv FROM mysql.user WHERE Insert_priv RLIKE 'Y_' LIMIT 0;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT Insert_priv FROM mysql.user WHERE Insert_priv RLIKE 'Y+' LIMIT 0;
--echo # Same as above, but using REGEXP_INSTR()
SELECT REGEXP_INSTR(Insert_priv,'Y') FROM mysql.user LIMIT 0;
SELECT REGEXP_INSTR(Insert_priv,'Y_') FROM mysql.user LIMIT 0;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT REGEXP_INSTR(Insert_priv,'Y+') FROM mysql.user LIMIT 0;
--echo # Same as above, but using MATCH ... AGAINST().
--echo # Unlike the other comparison functions above, MATCH ... AGAINST()
--echo # does not aggregate the AGAINST phrase's collation for the illegal-mix
--echo # check: Item_func_match::fix_fields() calls
--echo # agg_arg_charsets_for_comparison() on args+1 (the indexed column(s)
--echo # only), skipping args[0], which is the AGAINST phrase (key_item()).
--echo # The phrase is instead silently converted to the column's collation
--echo # (search_value), so none of the queries below raise an error, even
--echo # with a _bin column.
CREATE TABLE t1 (a VARCHAR(200) CHARACTER SET latin1 COLLATE latin1_swedish_ci,
FULLTEXT(a));
INSERT INTO t1 VALUES ('Y'),('N');
SET NAMES big5 COLLATE big5_chinese_ci;
SELECT MATCH(a) AGAINST('Y') FROM t1;
SELECT MATCH(a) AGAINST('Y_') FROM t1;
SELECT MATCH(a) AGAINST('Y+') FROM t1;
DROP TABLE t1;
CREATE TABLE t1 (a VARCHAR(200) CHARACTER SET latin1 COLLATE latin1_bin,
FULLTEXT(a));
INSERT INTO t1 VALUES ('Y'),('N');
SELECT MATCH(a) AGAINST('Y') FROM t1;
DROP TABLE t1;
--echo # Same as above, but using the simple CASE operator
SELECT CASE Insert_priv WHEN 'Y' THEN 1 WHEN 'N' THEN 0 END FROM mysql.user LIMIT 0;
SELECT CASE Insert_priv WHEN 'Y_' THEN 1 WHEN 'N' THEN 0 END FROM mysql.user LIMIT 0;
--error ER_CANT_AGGREGATE_3COLLATIONS
SELECT CASE Insert_priv WHEN 'Y' THEN 1 WHEN 'N+' THEN 0 END FROM mysql.user LIMIT 0;
--error ER_CANT_AGGREGATE_3COLLATIONS
SELECT CASE Insert_priv WHEN 'Y+' THEN 1 WHEN 'N' THEN 0 END FROM mysql.user LIMIT 0;
SET NAMES big5 COLLATE big5_bin;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT Insert_priv FROM mysql.user WHERE Insert_priv='Y' LIMIT 0;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT Insert_priv FROM mysql.user WHERE Insert_priv LIKE 'Y' LIMIT 0;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT Insert_priv FROM mysql.user WHERE Insert_priv RLIKE 'Y' LIMIT 0;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT REGEXP_INSTR(Insert_priv,'Y') FROM mysql.user LIMIT 0;
--error ER_CANT_AGGREGATE_3COLLATIONS
SELECT Insert_priv FROM mysql.user WHERE Insert_priv BETWEEN 'A' AND 'Z' LIMIT 0;
--error ER_CANT_AGGREGATE_3COLLATIONS
SELECT Insert_priv FROM mysql.user WHERE Insert_priv IN ('Y','N') LIMIT 0;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT STRCMP(Insert_priv,'Y') FROM mysql.user LIMIT 0;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT LOCATE('Y',Insert_priv) FROM mysql.user LIMIT 0;
--error ER_CANT_AGGREGATE_3COLLATIONS
SELECT FIELD(Insert_priv,'Y','N') FROM mysql.user LIMIT 0;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT FIND_IN_SET(Insert_priv,'Y') FROM mysql.user LIMIT 0;
--error ER_CANT_AGGREGATE_3COLLATIONS
SELECT CASE Insert_priv WHEN 'Y' THEN 1 WHEN 'N' THEN 0 END FROM mysql.user LIMIT 0;
--echo #
--echo # The same checks using an own view instead of mysql.user.
--echo # The view has exactly one row, so every query below returns
--echo # a row, or raises an error.
--echo #
--source include/ctype_tailoring_view_create.inc
SET NAMES big5 COLLATE big5_chinese_ci;
--source include/ctype_tailoring_03_probe_last_error.inc
--echo # Same as above, but using BETWEEN (3-operand aggregation)
SELECT c FROM v_tailoring WHERE c BETWEEN 'A' AND 'Z';
SELECT c FROM v_tailoring WHERE c BETWEEN 'A' AND 'Z_';
SELECT c FROM v_tailoring WHERE c BETWEEN 'A_' AND 'Z';
--error ER_CANT_AGGREGATE_3COLLATIONS
SELECT c FROM v_tailoring WHERE c BETWEEN 'A' AND 'Z+';
--error ER_CANT_AGGREGATE_3COLLATIONS
SELECT c FROM v_tailoring WHERE c BETWEEN 'A+' AND 'Z';
--echo # Same as above, but using IN() (N-operand aggregation)
SELECT c FROM v_tailoring WHERE c IN ('Y','N');
SELECT c FROM v_tailoring WHERE c NOT IN ('Y_','N');
--error ER_CANT_AGGREGATE_3COLLATIONS
SELECT c FROM v_tailoring WHERE c IN ('Y','N+');
--error ER_CANT_AGGREGATE_3COLLATIONS
SELECT c FROM v_tailoring WHERE c NOT IN ('Y+','N');
--echo # Same as above, but using STRCMP()
SELECT STRCMP(c,'Y') FROM v_tailoring;
SELECT STRCMP(c,'Y_') FROM v_tailoring;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT STRCMP(c,'Y+') FROM v_tailoring;
--echo # Same as above, but using LOCATE()/POSITION()/INSTR()
SELECT LOCATE('Y',c) FROM v_tailoring;
SELECT LOCATE('Y_',c) FROM v_tailoring;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT LOCATE('Y+',c) FROM v_tailoring;
SELECT POSITION('Y' IN c) FROM v_tailoring;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT POSITION('Y+' IN c) FROM v_tailoring;
SELECT INSTR(c,'Y') FROM v_tailoring;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT INSTR(c,'Y+') FROM v_tailoring;
--echo # Same as above, but using FIELD()
SELECT FIELD(c,'Y','N') FROM v_tailoring;
SELECT FIELD(c,'Y_','N') FROM v_tailoring;
--error ER_CANT_AGGREGATE_3COLLATIONS
SELECT FIELD(c,'Y','N+') FROM v_tailoring;
--error ER_CANT_AGGREGATE_3COLLATIONS
SELECT FIELD(c,'Y+','N') FROM v_tailoring;
--echo # Same as above, but using FIND_IN_SET()
--echo # (a single-value haystack, so the ',' separator does not
--echo # itself force a wider repertoire)
SELECT FIND_IN_SET(c,'Y') FROM v_tailoring;
SELECT FIND_IN_SET(c,'Y_') FROM v_tailoring;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT FIND_IN_SET(c,'Y+') FROM v_tailoring;
--echo # Same as above, but using LIKE
SELECT c FROM v_tailoring WHERE c LIKE 'Y';
SELECT c FROM v_tailoring WHERE c NOT LIKE 'Y_';
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT c FROM v_tailoring WHERE c NOT LIKE 'Y+';
--echo # Same as above, but using RLIKE
SELECT c FROM v_tailoring WHERE c RLIKE 'Y';
SELECT c FROM v_tailoring WHERE c NOT RLIKE 'Y_';
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT c FROM v_tailoring WHERE c RLIKE 'Y+';
--echo # Same as above, but using REGEXP_INSTR()
SELECT REGEXP_INSTR(c,'Y') FROM v_tailoring;
SELECT REGEXP_INSTR(c,'Y_') FROM v_tailoring;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT REGEXP_INSTR(c,'Y+') FROM v_tailoring;
--echo # Same as above, but using the simple CASE operator
SELECT CASE c WHEN 'Y' THEN 1 WHEN 'N' THEN 0 END FROM v_tailoring;
SELECT CASE c WHEN 'Y_' THEN 1 WHEN 'N' THEN 0 END FROM v_tailoring;
--error ER_CANT_AGGREGATE_3COLLATIONS
SELECT CASE c WHEN 'Y' THEN 1 WHEN 'N+' THEN 0 END FROM v_tailoring;
--error ER_CANT_AGGREGATE_3COLLATIONS
SELECT CASE c WHEN 'Y+' THEN 1 WHEN 'N' THEN 0 END FROM v_tailoring;
SET NAMES big5 COLLATE big5_bin;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT c FROM v_tailoring WHERE c='Y';
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT c FROM v_tailoring WHERE c LIKE 'Y';
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT c FROM v_tailoring WHERE c RLIKE 'Y';
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT REGEXP_INSTR(c,'Y') FROM v_tailoring;
--error ER_CANT_AGGREGATE_3COLLATIONS
SELECT c FROM v_tailoring WHERE c BETWEEN 'A' AND 'Z';
--error ER_CANT_AGGREGATE_3COLLATIONS
SELECT c FROM v_tailoring WHERE c IN ('Y','N');
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT STRCMP(c,'Y') FROM v_tailoring;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT LOCATE('Y',c) FROM v_tailoring;
--error ER_CANT_AGGREGATE_3COLLATIONS
SELECT FIELD(c,'Y','N') FROM v_tailoring;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT FIND_IN_SET(c,'Y') FROM v_tailoring;
--error ER_CANT_AGGREGATE_3COLLATIONS
SELECT CASE c WHEN 'Y' THEN 1 WHEN 'N' THEN 0 END FROM v_tailoring;
--source include/ctype_tailoring_view_drop.inc
--echo # The originally reported scenario: a view is created under latin1
--echo # and queried under big5. The comparison must return the right rows.
SET NAMES latin1 COLLATE latin1_swedish_ci;
CREATE VIEW v1 AS SELECT 'Y' AS c1 UNION SELECT 'N';
SET NAMES big5 COLLATE big5_chinese_ci;
SELECT * FROM v1 WHERE c1='y';
SELECT * FROM v1 WHERE c1='Y';
SELECT * FROM v1 WHERE 'n'=c1;
SELECT * FROM v1 WHERE c1='N';
SELECT * FROM v1 WHERE c1='x';
SELECT * FROM v1 WHERE c1 IN ('y','n') ORDER BY c1;
SELECT * FROM v1 WHERE c1 BETWEEN 'm' AND 'z' ORDER BY c1;
--enable_service_connection
--echo # The same view with prepared statement parameters.
--echo # A parameter with a non-ALNUM value makes the collations incompatible.
PREPARE stmt FROM 'SELECT c1 FROM v1 WHERE c1=? ORDER BY c1';
SET @y='y', @n='N', @y_plus='Y+';
EXECUTE stmt USING @y;
EXECUTE stmt USING @n;
--error ER_CANT_AGGREGATE_2COLLATIONS
EXECUTE stmt USING @y_plus;
EXECUTE stmt USING 'y';
EXECUTE stmt USING 'x';
DEALLOCATE PREPARE stmt;
PREPARE stmt FROM 'SELECT c1 FROM v1 WHERE c1 IN (?,?) ORDER BY c1';
EXECUTE stmt USING 'y', 'n';
--error ER_CANT_AGGREGATE_3COLLATIONS
EXECUTE stmt USING 'y', 'Y+';
DEALLOCATE PREPARE stmt;
EXECUTE IMMEDIATE 'SELECT c1 FROM v1 WHERE c1=?' USING 'y';
--error ER_CANT_AGGREGATE_2COLLATIONS
EXECUTE IMMEDIATE 'SELECT c1 FROM v1 WHERE c1=?' USING 'Y+';
DROP VIEW v1;
--echo # Prepared statement parameters compared to a literal of another charset.
--echo # A parameter with a non-ALNUM value makes the collations incompatible.
PREPARE stmt FROM 'SELECT _latin1''Y'' = ? AS r';
EXECUTE stmt USING @y;
EXECUTE stmt USING @n;
--error ER_CANT_AGGREGATE_2COLLATIONS
EXECUTE stmt USING @y_plus;
DEALLOCATE PREPARE stmt;
PREPARE stmt FROM 'SELECT _latin1''Y+'' = ? AS r';
--error ER_CANT_AGGREGATE_2COLLATIONS
EXECUTE stmt USING 'y';
--error ER_CANT_AGGREGATE_2COLLATIONS
EXECUTE stmt USING 'Y+';
DEALLOCATE PREPARE stmt;
EXECUTE IMMEDIATE 'SELECT _latin1''Y'' = ? AS r' USING 'y';
--error ER_CANT_AGGREGATE_2COLLATIONS
EXECUTE IMMEDIATE 'SELECT _latin1''Y'' = ? AS r' USING 'Y+';
SET NAMES DEFAULT;
--echo # End of 11.8 tests

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,235 @@
--source include/have_big5.inc
--source include/have_utf32.inc
--echo #
--echo # MDEV-41246 "Illegal mix of collations" on the mysql.user view
--echo #
--disable_query_log
SET @mask='^big5';
SET @extra_collations_query=
'INSERT INTO collations VALUES'
'(''big5_chinese_ci''),(''big5_chinese_nopad_ci''),'
'(''big5_bin''),(''big5_nopad_bin'')';
--source include/ctype_tailoring_00.inc
--enable_query_log
--echo # HEX() output is only [0-9A-F], so its repertoire is
--echo # MY_REPERTOIRE_ASCII_ALNUM. It can tailoring-match a collation pair
--echo # that is incompatible on the full ASCII repertoire.
SELECT HEX('a') = _big5'61';
--echo # Item_null has the repertoire MY_REPERTOIRE_NONE, the identity element
--echo # for repertoire aggregation: a NULL operand does not widen
--echo # the repertoire of an IN()/CASE/BETWEEN aggregate...
SELECT _latin1'Y' in (NULL, _big5'Y');
--echo # ... and does not mask a genuine incompatibility either.
--error ER_CANT_AGGREGATE_3COLLATIONS
SELECT _latin1'Y+' in (NULL, _big5'Y+');
--echo # The empty string has the repertoire NONE on both sides, so it is
--echo # always compatible, regardless of collation.
SELECT _latin1'' = _big5'';
--echo #
--echo # MDEV-41246 QUOTE(), GROUP_CONCAT(), MAKE_SET() and EXPORT_SET() add
--echo # characters of their own (quotes/backslashes, the ',' separator) that
--echo # are not in their arguments' repertoire. The result's repertoire must
--echo # include them too, or illegal-mix-by-repertoire detection becomes
--echo # asymmetric.
--echo #
--echo # latin1_swedish_ci and big5_chinese_ci are compatible on the ALNUM
--echo # repertoire, but not on the wider repertoire these functions can add
--echo # (see the C_ascii1 row above).
--echo #
SELECT _latin1'a' = _big5'a';
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT QUOTE(_latin1'a') = _big5'a';
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT _big5'a' = QUOTE(_latin1'a');
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT (SELECT GROUP_CONCAT(_latin1'a')) = _big5'a';
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT _big5'a' = (SELECT GROUP_CONCAT(_latin1'a'));
--echo # An explicit ALNUM or empty separator does not force the repertoire wider
SELECT (SELECT GROUP_CONCAT(_latin1'a' SEPARATOR 'x')) = _big5'a';
SELECT (SELECT GROUP_CONCAT(_latin1'a' SEPARATOR '')) = _big5'a';
--echo # An explicit non-ALNUM separator widens the repertoire
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT (SELECT GROUP_CONCAT(_latin1'a' SEPARATOR ',')) = _big5'a';
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT (SELECT GROUP_CONCAT(_latin1'a' SEPARATOR '+')) = _big5'a';
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT _big5'a' = (SELECT GROUP_CONCAT(_latin1'a' SEPARATOR ' '));
--echo # MAKE_SET() can add a ',' separator as soon as there is more than one
--echo # possible value, even when, like here, the chosen bit produces none.
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT MAKE_SET(3,_latin1'a',_latin1'b') = _big5'a,b';
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT MAKE_SET(1,_latin1'a',_latin1'b') = _big5'a';
--echo # Only one possible value: no separator can ever appear.
SELECT MAKE_SET(1,_latin1'a') = _big5'a';
--echo # EXPORT_SET()'s default ',' separator is outside the ALNUM repertoire.
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT EXPORT_SET(1,_latin1'y',_latin1'n') = _big5'y';
--echo # An explicit ALNUM separator does not force the repertoire wider.
SELECT EXPORT_SET(1,_latin1'y',_latin1'n',_latin1'x',1) = _big5'y';
--echo # An explicit non-ALNUM separator is detected through normal argument
--echo # aggregation, same as for GROUP_CONCAT/MAKE_SET's hard-coded separator.
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT EXPORT_SET(1,_latin1'y',_latin1'n',_latin1',',1) = _big5'y';
--echo # LPAD()/RPAD() with no explicit pad string default to ' ', which is
--echo # outside the ALNUM repertoire.
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT LPAD(_latin1'a',3) = _big5'a';
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT RPAD(_latin1'a',3) = _big5'a';
--echo # An explicit ALNUM pad string does not force the repertoire wider.
SELECT LPAD(_latin1'a',3,_latin1'x') = _big5'xxa';
--echo # An explicit non-ALNUM pad string is detected through normal argument
--echo # aggregation, same as for the default ' ' above.
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT LPAD(_latin1'a',3,_latin1'-') = _big5'--a';
--echo # JSON_OBJECTAGG() adds '{', '}', '"', ':', ',' and ' ' of its own,
--echo # which are outside the ALNUM repertoire.
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT JSON_OBJECTAGG(_latin1'a',_latin1'b') = _big5'a';
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT _big5'a' = JSON_OBJECTAGG(_latin1'a',_latin1'b');
--echo # JSON_ARRAY() and JSON_OBJECT() also add '[', ']', '{', '}', '"', ':',
--echo # ',' and ' ' of their own, so the same applies to them.
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT JSON_ARRAY(_latin1'a') = _big5'a';
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT _big5'a' = JSON_ARRAY(_latin1'a');
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT JSON_OBJECT(_latin1'a',_latin1'b') = _big5'a';
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT _big5'a' = JSON_OBJECT(_latin1'a',_latin1'b');
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT JSON_MERGE_PRESERVE(_latin1'1',_latin1'2') = _big5'a';
--echo # JSON_ARRAY() without arguments returns '[]', which is ASCII
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT JSON_ARRAY() = _big5'a';
--echo # JSON_ARRAYAGG() already inherits the ',' repertoire from GROUP_CONCAT()
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT JSON_ARRAYAGG(_latin1'a') = _big5'a';
--echo #
--echo # DATE_FORMAT() result repertoire depends on the locale
--echo # which is actually used: the explicit third argument, or
--echo # @@lc_time_names. Locale names (e.g. of days) can be non-ASCII.
--echo # big5_chinese_ci and latin1_swedish_ci are not compatible on ASCII,
--echo # unless the DATE_FORMAT() result is allowed to be non-ASCII,
--echo # so its collation can be preferred.
--echo #
SET NAMES big5;
--echo # en_US names are ASCII
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT DATE_FORMAT('2024-01-02','%W') = _latin1'a';
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT DATE_FORMAT('2024-01-02','%W','en_US') = _latin1'a';
--echo # An explicit non-ASCII locale is not ignored
SELECT DATE_FORMAT('2024-01-02','%W','ru_RU') = _latin1'a';
--echo # A non-constant locale is not known at the fixing time
SET @loc='en_US';
SELECT DATE_FORMAT('2024-01-02','%W',@loc) = _latin1'a';
--echo # The session locale is not used when the locale is passed explicitly
SET lc_time_names=ru_RU;
SELECT DATE_FORMAT('2024-01-02','%W') = _latin1'a';
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT DATE_FORMAT('2024-01-02','%W','en_US') = _latin1'a';
SET lc_time_names=DEFAULT;
SET NAMES DEFAULT;
--echo #
--echo # MDEV-41246 Negative cases: the collations are still incompatible
--echo # when the strings are not ASCII only, or when a string result
--echo # function mixes arguments of different collations.
--echo #
SET NAMES latin1;
--echo # Non-ASCII literals. If only one side is non-ASCII, the ASCII side
--echo # is converted to the character set of the non-ASCII one.
SELECT _latin1 0xE9 = _big5'a';
SELECT _latin1'a' = _big5 0xA4A4;
SELECT _latin1 0xE9 IN (_big5'a', _big5'b');
--echo # If both sides are non-ASCII, no conversion is possible
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT _latin1 0xE9 = _big5 0xA4A4;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT CONCAT(_latin1'a',_latin1 0xE9) = _big5 0xA4A4;
--error ER_CANT_AGGREGATE_3COLLATIONS
SELECT _latin1 0xE9 IN (_big5 0xA4A4, _big5'b');
--echo # String result functions do not use the tailoring optimization:
--echo # the collation of the result must be calculated precisely
--error ER_CANT_AGGREGATE_3COLLATIONS
SELECT REPLACE(_latin1'abc', _big5'a', _big5'b');
--error ER_CANT_AGGREGATE_3COLLATIONS
SELECT REPLACE(_latin1'abc', _latin1'a', _big5'b');
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT SUBSTRING_INDEX(_latin1'a,b', _big5',', 1);
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT SUBSTRING_INDEX(_latin1'a,b', _big5'x', 1);
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT TRIM(_big5'a' FROM _latin1'abc');
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT GREATEST(_latin1'a', _big5'b');
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT LEAST(_latin1'a', _big5'b');
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT COALESCE(_latin1'a', _big5'b');
--echo # A non-ASCII argument makes the ASCII argument converted
SELECT COALESCE(_latin1'a', _big5 0xA4A4);
--echo # The same functions with arguments of the same collation
--echo # can be compared with a string of a compatible collation,
--echo # unless the result can contain non-ALNUM characters
SELECT COALESCE(_latin1'a', _latin1'b') = _big5'a';
SELECT GREATEST(_latin1'a', _latin1'b') = _big5'b';
SELECT REPLACE(_latin1'abc', _latin1'a', _latin1'b') = _big5'bbc';
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT TRIM(_latin1' abc ') = _big5'abc';
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT SUBSTRING_INDEX(_latin1'a,b', _latin1',', 1) = _big5'a';
--echo # Indexed columns. A column has a stronger derivation than a literal,
--echo # so the collation of the column is used and the index is used.
CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET latin1 COLLATE latin1_swedish_ci,
KEY(a)) ENGINE=MyISAM;
INSERT INTO t1 VALUES ('a'),('b'),('Y'),('y'),('x');
CREATE TABLE t2 (a VARCHAR(10) CHARACTER SET big5 COLLATE big5_chinese_ci,
KEY(a)) ENGINE=MyISAM;
INSERT INTO t2 VALUES ('a'),('b'),('Y'),('y'),('x');
SET NAMES big5;
EXPLAIN SELECT * FROM t1 WHERE a='y';
SELECT * FROM t1 WHERE a='y' ORDER BY a;
EXPLAIN SELECT * FROM t1 WHERE a=_big5'Y+';
SELECT * FROM t1 WHERE a=_big5'Y+';
SET NAMES latin1;
EXPLAIN SELECT * FROM t2 WHERE a=_latin1'y';
SELECT * FROM t2 WHERE a=_latin1'y' ORDER BY a;
--echo # Two columns of different collations are still incompatible,
--echo # as they have equal derivation, and the repertoire of a column
--echo # is not limited
--error ER_CANT_AGGREGATE_2COLLATIONS
EXPLAIN SELECT * FROM t2, t1 WHERE t1.a=t2.a;
DROP TABLE t1, t2;
SET NAMES DEFAULT;
--echo # End of 11.8 tests

View File

@@ -236,11 +236,8 @@ SELECT DATE_FORMAT('2004-02-02','%W');
SELECT HEX(DATE_FORMAT('2004-02-02','%W'));
#Enable after fix MDEV-33936
--disable_view_protocol
#enable after fix MDEV-34215
--disable_cursor_protocol
SELECT DATE_FORMAT(TIME'-01:01:01','%h');
SELECT HEX(DATE_FORMAT(TIME'-01:01:01','%h'));
--enable_cursor_protocol
--enable_view_protocol
--echo # latin1 format, binary result
@@ -248,11 +245,8 @@ SELECT DATE_FORMAT('2004-02-02',_latin1'%W');
SELECT HEX(DATE_FORMAT('2004-02-02',_latin1'%W'));
#Enable after fix MDEV-33936
--disable_view_protocol
#enable after fix MDEV-34215
--disable_cursor_protocol
SELECT DATE_FORMAT(TIME'-01:01:01',_latin1'%h');
SELECT HEX(DATE_FORMAT(TIME'-01:01:01',_latin1'%h'));
--enable_cursor_protocol
--enable_view_protocol
--echo # Binary format, latin1 result
@@ -261,11 +255,8 @@ SELECT DATE_FORMAT('2004-02-02',_binary'%W');
SELECT HEX(DATE_FORMAT('2004-02-02',_binary'%W'));
#Enable after fix MDEV-33936
--disable_view_protocol
#enable after fix MDEV-34215
--disable_cursor_protocol
SELECT DATE_FORMAT(TIME'-01:01:01',_binary'%h');
SELECT HEX(DATE_FORMAT(TIME'-01:01:01',_binary'%h'));
--enable_cursor_protocol
--enable_view_protocol
--echo #
--echo # End of 10.4 tests

View File

@@ -808,3 +808,25 @@ ts
2024-01-26 21:38:02
drop table t1;
# End of 10.6 tests
#
# MDEV-39530: Collation mix issue after update
#
# Reproduce the environment from the report: character_set_collations
# maps utf8mb3 to utf8mb3_uca1400_ai_ci and the connection uses that
# collation.
SET NAMES utf8mb3 COLLATE utf8mb3_uca1400_ai_ci;
SELECT @@character_set_collations, @@collation_connection;
@@character_set_collations @@collation_connection
utf8mb3=utf8mb3_uca1400_ai_ci,ucs2=ucs2_uca1400_ai_ci,utf8mb4=utf8mb4_uca1400_ai_ci,utf16=utf16_uca1400_ai_ci,utf32=utf32_uca1400_ai_ci utf8mb3_uca1400_ai_ci
CREATE TABLE file (
`ID` int(10) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
`Path` varchar(800) NOT NULL DEFAULT ''
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
INSERT INTO file VALUES (1,"text");
# This query used to work in 11.4 but raises
# ER_CANT_AGGREGATE_2COLLATIONS in 12.1+
SELECT IF((@p:=(SELECT f.Path FROM file f WHERE f.ID=1 AND f.Path REGEXP "^xx"))!="",1,2);
IF((@p:=(SELECT f.Path FROM file f WHERE f.ID=1 AND f.Path REGEXP "^xx"))!="",1,2)
2
DROP TABLE file;
# End of 12.3 tests

View File

@@ -378,3 +378,28 @@ select * from t1 order by ts collate utf8_bin;
drop table t1;
--echo # End of 10.6 tests
--echo #
--echo # MDEV-39530: Collation mix issue after update
--echo #
--echo # Reproduce the environment from the report: character_set_collations
--echo # maps utf8mb3 to utf8mb3_uca1400_ai_ci and the connection uses that
--echo # collation.
SET NAMES utf8mb3 COLLATE utf8mb3_uca1400_ai_ci;
SELECT @@character_set_collations, @@collation_connection;
CREATE TABLE file (
`ID` int(10) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
`Path` varchar(800) NOT NULL DEFAULT ''
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
INSERT INTO file VALUES (1,"text");
--echo # This query used to work in 11.4 but raises
--echo # ER_CANT_AGGREGATE_2COLLATIONS in 12.1+
SELECT IF((@p:=(SELECT f.Path FROM file f WHERE f.ID=1 AND f.Path REGEXP "^xx"))!="",1,2);
DROP TABLE file;
--echo # End of 12.3 tests

View File

@@ -0,0 +1,56 @@
#
# MDEV-41246 "Illegal mix of collations" on the mysql.user view
#
SET NAMES cp1250 COLLATE cp1250_general_ci;
# ASCII digits
d
1
# ASCII minus, dot and digits
e
-1.5
SELECT c FROM v_tailoring WHERE c='Y';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y_';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y+';
c
Y
SET NAMES cp1250 COLLATE cp1250_croatian_ci;
# ASCII digits
d
1
# ASCII minus, dot and digits
e
-1.5
SELECT c FROM v_tailoring WHERE c='Y';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y_';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y+';
c
Y
SET NAMES cp1250 COLLATE cp1250_polish_ci;
# ASCII digits
d
1
# ASCII minus, dot and digits
e
-1.5
SELECT c FROM v_tailoring WHERE c='Y';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y_';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y+';
c
Y
SET NAMES cp1250 COLLATE cp1250_bin;
SELECT c FROM v_tailoring WHERE c='Y';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (cp1250_bin,COERCIBLE) for operation '='
SET NAMES DEFAULT;
# End of 11.8 tests

View File

@@ -0,0 +1,23 @@
--echo #
--echo # MDEV-41246 "Illegal mix of collations" on the mysql.user view
--echo #
SET NAMES cp1250 COLLATE cp1250_general_ci;
--disable_service_connection
--source include/ctype_tailoring_view_create.inc
--source include/ctype_tailoring_01_probe.inc
SET NAMES cp1250 COLLATE cp1250_croatian_ci;
--source include/ctype_tailoring_01_probe.inc
SET NAMES cp1250 COLLATE cp1250_polish_ci;
--source include/ctype_tailoring_01_probe.inc
SET NAMES cp1250 COLLATE cp1250_bin;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT c FROM v_tailoring WHERE c='Y';
--source include/ctype_tailoring_view_drop.inc
--enable_service_connection
SET NAMES DEFAULT;
--echo # End of 11.8 tests

View File

@@ -912,3 +912,24 @@ A401
#
# End of 5.6 tests
#
#
# MDEV-41246 "Illegal mix of collations" on the mysql.user view
#
SET NAMES cp1250 COLLATE cp1250_czech_cs;
# ASCII digits
d
1
# ASCII minus, dot and digits
e
-1.5
SELECT c FROM v_tailoring WHERE c='Y';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (cp1250_czech_cs,COERCIBLE) for operation '='
SELECT c FROM v_tailoring WHERE c<>'Y_';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (cp1250_czech_cs,COERCIBLE) for operation '<>'
SELECT c FROM v_tailoring WHERE c<>'Y+';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (cp1250_czech_cs,COERCIBLE) for operation '<>'
SET NAMES cp1250 COLLATE cp1250_bin;
SELECT c FROM v_tailoring WHERE c='Y';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (cp1250_bin,COERCIBLE) for operation '='
SET NAMES DEFAULT;
# End of 11.8 tests

View File

@@ -114,3 +114,18 @@ set names cp1250 collate cp1250_czech_cs;
--echo # End of 5.6 tests
--echo #
--echo #
--echo # MDEV-41246 "Illegal mix of collations" on the mysql.user view
--echo #
SET NAMES cp1250 COLLATE cp1250_czech_cs;
--source include/ctype_tailoring_view_create.inc
--source include/ctype_tailoring_02_probe_error.inc
SET NAMES cp1250 COLLATE cp1250_bin;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT c FROM v_tailoring WHERE c='Y';
--source include/ctype_tailoring_view_drop.inc
SET NAMES DEFAULT;
--echo # End of 11.8 tests

View File

@@ -3398,3 +3398,71 @@ DROP TABLE t1;
#
# End of 10.1 tests
#
#
# MDEV-41246 "Illegal mix of collations" on the mysql.user view
#
SET NAMES cp1251 COLLATE cp1251_general_ci;
# ASCII digits
d
1
# ASCII minus, dot and digits
e
-1.5
SELECT c FROM v_tailoring WHERE c='Y';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y_';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y+';
c
Y
SET NAMES cp1251 COLLATE cp1251_bulgarian_ci;
# ASCII digits
d
1
# ASCII minus, dot and digits
e
-1.5
SELECT c FROM v_tailoring WHERE c='Y';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y_';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y+';
c
Y
SET NAMES cp1251 COLLATE cp1251_ukrainian_ci;
# ASCII digits
d
1
# ASCII minus, dot and digits
e
-1.5
SELECT c FROM v_tailoring WHERE c='Y';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y_';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y+';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (cp1251_ukrainian_ci,COERCIBLE) for operation '<>'
SET NAMES cp1251 COLLATE cp1251_general_cs;
# ASCII digits
d
1
# ASCII minus, dot and digits
e
-1.5
SELECT c FROM v_tailoring WHERE c='Y';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (cp1251_general_cs,COERCIBLE) for operation '='
SELECT c FROM v_tailoring WHERE c<>'Y_';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (cp1251_general_cs,COERCIBLE) for operation '<>'
SELECT c FROM v_tailoring WHERE c<>'Y+';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (cp1251_general_cs,COERCIBLE) for operation '<>'
SET NAMES cp1251 COLLATE cp1251_bin;
SELECT c FROM v_tailoring WHERE c='Y';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (cp1251_bin,COERCIBLE) for operation '='
SET NAMES DEFAULT;
# End of 11.8 tests

View File

@@ -143,3 +143,33 @@ DROP TABLE t1;
--echo #
--echo # End of 10.1 tests
--echo #
--echo #
--echo # MDEV-41246 "Illegal mix of collations" on the mysql.user view
--echo #
SET NAMES cp1251 COLLATE cp1251_general_ci;
--disable_service_connection
--source include/ctype_tailoring_view_create.inc
--source include/ctype_tailoring_01_probe.inc
SET NAMES cp1251 COLLATE cp1251_bulgarian_ci;
--source include/ctype_tailoring_01_probe.inc
SET NAMES cp1251 COLLATE cp1251_ukrainian_ci;
--source include/ctype_tailoring_03_probe_last_error.inc
SET NAMES cp1251 COLLATE cp1251_general_cs;
--source include/ctype_tailoring_02_probe_error.inc
SET NAMES cp1251 COLLATE cp1251_bin;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT c FROM v_tailoring WHERE c='Y';
--source include/ctype_tailoring_view_drop.inc
--enable_service_connection
SET NAMES DEFAULT;
--echo # End of 11.8 tests

View File

@@ -0,0 +1,24 @@
#
# MDEV-41246 "Illegal mix of collations" on the mysql.user view
#
SET NAMES cp1256 COLLATE cp1256_general_ci;
# ASCII digits
d
1
# ASCII minus, dot and digits
e
-1.5
SELECT c FROM v_tailoring WHERE c='Y';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y_';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y+';
c
Y
SET NAMES cp1256 COLLATE cp1256_bin;
SELECT c FROM v_tailoring WHERE c='Y';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (cp1256_bin,COERCIBLE) for operation '='
SET NAMES DEFAULT;
# End of 11.8 tests

View File

@@ -0,0 +1,17 @@
--echo #
--echo # MDEV-41246 "Illegal mix of collations" on the mysql.user view
--echo #
SET NAMES cp1256 COLLATE cp1256_general_ci;
--disable_service_connection
--source include/ctype_tailoring_view_create.inc
--source include/ctype_tailoring_01_probe.inc
SET NAMES cp1256 COLLATE cp1256_bin;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT c FROM v_tailoring WHERE c='Y';
--source include/ctype_tailoring_view_drop.inc
--enable_service_connection
SET NAMES DEFAULT;
--echo # End of 11.8 tests

View File

@@ -0,0 +1,37 @@
#
# MDEV-41246 "Illegal mix of collations" on the mysql.user view
#
SET NAMES cp1257 COLLATE cp1257_general_ci;
# ASCII digits
d
1
# ASCII minus, dot and digits
e
-1.5
SELECT c FROM v_tailoring WHERE c='Y';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y_';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y+';
c
Y
SET NAMES cp1257 COLLATE cp1257_lithuanian_ci;
# ASCII digits
d
1
# ASCII minus, dot and digits
e
-1.5
SELECT c FROM v_tailoring WHERE c='Y';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (cp1257_lithuanian_ci,COERCIBLE) for operation '='
SELECT c FROM v_tailoring WHERE c<>'Y_';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (cp1257_lithuanian_ci,COERCIBLE) for operation '<>'
SELECT c FROM v_tailoring WHERE c<>'Y+';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (cp1257_lithuanian_ci,COERCIBLE) for operation '<>'
SET NAMES cp1257 COLLATE cp1257_bin;
SELECT c FROM v_tailoring WHERE c='Y';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (cp1257_bin,COERCIBLE) for operation '='
SET NAMES DEFAULT;
# End of 11.8 tests

View File

@@ -0,0 +1,20 @@
--echo #
--echo # MDEV-41246 "Illegal mix of collations" on the mysql.user view
--echo #
SET NAMES cp1257 COLLATE cp1257_general_ci;
--disable_service_connection
--source include/ctype_tailoring_view_create.inc
--source include/ctype_tailoring_01_probe.inc
SET NAMES cp1257 COLLATE cp1257_lithuanian_ci;
--source include/ctype_tailoring_02_probe_error.inc
SET NAMES cp1257 COLLATE cp1257_bin;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT c FROM v_tailoring WHERE c='Y';
--source include/ctype_tailoring_view_drop.inc
--enable_service_connection
SET NAMES DEFAULT;
--echo # End of 11.8 tests

View File

@@ -1062,3 +1062,27 @@ _cp850'' LIKE _cp850'' ESCAPE _cp850 0xFF
#
# End of 10.2 tests
#
#
# MDEV-41246 "Illegal mix of collations" on the mysql.user view
#
SET NAMES cp850 COLLATE cp850_general_ci;
# ASCII digits
d
1
# ASCII minus, dot and digits
e
-1.5
SELECT c FROM v_tailoring WHERE c='Y';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y_';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y+';
c
Y
SET NAMES cp850 COLLATE cp850_bin;
SELECT c FROM v_tailoring WHERE c='Y';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (cp850_bin,COERCIBLE) for operation '='
SET NAMES DEFAULT;
# End of 11.8 tests

View File

@@ -46,3 +46,22 @@ DELIMITER ;$$
--echo #
--echo # End of 10.2 tests
--echo #
--echo #
--echo # MDEV-41246 "Illegal mix of collations" on the mysql.user view
--echo #
SET NAMES cp850 COLLATE cp850_general_ci;
--disable_service_connection
--source include/ctype_tailoring_view_create.inc
--source include/ctype_tailoring_01_probe.inc
SET NAMES cp850 COLLATE cp850_bin;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT c FROM v_tailoring WHERE c='Y';
--source include/ctype_tailoring_view_drop.inc
--enable_service_connection
SET NAMES DEFAULT;
--echo # End of 11.8 tests

View File

@@ -0,0 +1,24 @@
#
# MDEV-41246 "Illegal mix of collations" on the mysql.user view
#
SET NAMES cp852 COLLATE cp852_general_ci;
# ASCII digits
d
1
# ASCII minus, dot and digits
e
-1.5
SELECT c FROM v_tailoring WHERE c='Y';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y_';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y+';
c
Y
SET NAMES cp852 COLLATE cp852_bin;
SELECT c FROM v_tailoring WHERE c='Y';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (cp852_bin,COERCIBLE) for operation '='
SET NAMES DEFAULT;
# End of 11.8 tests

View File

@@ -0,0 +1,17 @@
--echo #
--echo # MDEV-41246 "Illegal mix of collations" on the mysql.user view
--echo #
SET NAMES cp852 COLLATE cp852_general_ci;
--disable_service_connection
--source include/ctype_tailoring_view_create.inc
--source include/ctype_tailoring_01_probe.inc
SET NAMES cp852 COLLATE cp852_bin;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT c FROM v_tailoring WHERE c='Y';
--source include/ctype_tailoring_view_drop.inc
--enable_service_connection
SET NAMES DEFAULT;
--echo # End of 11.8 tests

View File

@@ -10,3 +10,24 @@ _cp866'' LIKE _cp866'' ESCAPE _cp866 0xFF
#
# End of 10.2 tests
#
#
# MDEV-41246 "Illegal mix of collations" on the mysql.user view
#
SET NAMES cp866 COLLATE cp866_general_ci;
# ASCII digits
d
1
# ASCII minus, dot and digits
e
-1.5
SELECT c FROM v_tailoring WHERE c='Y';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (cp866_general_ci,COERCIBLE) for operation '='
SELECT c FROM v_tailoring WHERE c<>'Y_';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (cp866_general_ci,COERCIBLE) for operation '<>'
SELECT c FROM v_tailoring WHERE c<>'Y+';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (cp866_general_ci,COERCIBLE) for operation '<>'
SET NAMES cp866 COLLATE cp866_bin;
SELECT c FROM v_tailoring WHERE c='Y';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (cp866_bin,COERCIBLE) for operation '='
SET NAMES DEFAULT;
# End of 11.8 tests

View File

@@ -12,3 +12,21 @@ SELECT _cp866'' LIKE _cp866'' ESCAPE _cp866 0xFF;
--echo #
--echo # End of 10.2 tests
--echo #
--echo #
--echo # MDEV-41246 "Illegal mix of collations" on the mysql.user view
--echo #
SET NAMES cp866 COLLATE cp866_general_ci;
--disable_service_connection
--source include/ctype_tailoring_view_create.inc
--source include/ctype_tailoring_02_probe_error.inc
SET NAMES cp866 COLLATE cp866_bin;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT c FROM v_tailoring WHERE c='Y';
--source include/ctype_tailoring_view_drop.inc
--enable_service_connection
SET NAMES DEFAULT;
--echo # End of 11.8 tests

View File

@@ -939,3 +939,49 @@ c1
#
# End of 10.5 tests
#
#
# MDEV-41246 "Illegal mix of collations" on the mysql.user view
#
SET NAMES cp932 COLLATE cp932_japanese_ci;
# ASCII digits
d
1
# ASCII minus, dot and digits
e
-1.5
SELECT c FROM v_tailoring WHERE c='Y';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y_';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y+';
c
Y
SET NAMES cp932 COLLATE cp932_bin;
SELECT c FROM v_tailoring WHERE c='Y';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (cp932_bin,COERCIBLE) for operation '='
SET NAMES DEFAULT;
#
# MDEV-41246 ExtractValue() and UpdateXML() return a string, so they
# must not use the tailoring-based collation aggregation, which is only
# intended for comparison operators.
#
SET NAMES latin1;
SELECT COLLATION(ExtractValue(_cp932'<a>x</a>', _latin1'a'));
ERROR HY000: Illegal mix of collations (cp932_japanese_ci,COERCIBLE) and (latin1_swedish_ci,COERCIBLE) for operation 'extractvalue'
SELECT COLLATION(ExtractValue(_latin1'<a>x</a>', _cp932'a'));
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (cp932_japanese_ci,COERCIBLE) for operation 'extractvalue'
SELECT COLLATION(UpdateXML(_latin1'<a>x</a>', _cp932'/a', _cp932'<a>y</a>'));
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE), (cp932_japanese_ci,COERCIBLE), (cp932_japanese_ci,COERCIBLE) for operation 'updatexml'
SELECT COLLATION(UpdateXML(_cp932'<a>x</a>', _latin1'/a', _latin1'<a>y</a>'));
ERROR HY000: Illegal mix of collations (cp932_japanese_ci,COERCIBLE), (latin1_swedish_ci,COERCIBLE), (latin1_swedish_ci,COERCIBLE) for operation 'updatexml'
# Same character set arguments still work
SELECT ExtractValue(_cp932'<a>x</a>', _cp932'/a');
ExtractValue(_cp932'<a>x</a>', _cp932'/a')
x
SELECT UpdateXML(_latin1'<a>x</a>', _latin1'/a', _latin1'<a>y</a>');
UpdateXML(_latin1'<a>x</a>', _latin1'/a', _latin1'<a>y</a>')
<a>y</a>
SET NAMES DEFAULT;
# End of 11.8 tests

View File

@@ -80,3 +80,43 @@ select strcmp(_cp932'' collate cp932_nopad_bin, _cp932 0x0001050001) as c1;
--echo #
--echo # End of 10.5 tests
--echo #
--echo #
--echo # MDEV-41246 "Illegal mix of collations" on the mysql.user view
--echo #
SET NAMES cp932 COLLATE cp932_japanese_ci;
--disable_service_connection
--source include/ctype_tailoring_view_create.inc
--source include/ctype_tailoring_01_probe.inc
SET NAMES cp932 COLLATE cp932_bin;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT c FROM v_tailoring WHERE c='Y';
--source include/ctype_tailoring_view_drop.inc
--enable_service_connection
SET NAMES DEFAULT;
--echo #
--echo # MDEV-41246 ExtractValue() and UpdateXML() return a string, so they
--echo # must not use the tailoring-based collation aggregation, which is only
--echo # intended for comparison operators.
--echo #
SET NAMES latin1;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT COLLATION(ExtractValue(_cp932'<a>x</a>', _latin1'a'));
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT COLLATION(ExtractValue(_latin1'<a>x</a>', _cp932'a'));
--error ER_CANT_AGGREGATE_3COLLATIONS
SELECT COLLATION(UpdateXML(_latin1'<a>x</a>', _cp932'/a', _cp932'<a>y</a>'));
--error ER_CANT_AGGREGATE_3COLLATIONS
SELECT COLLATION(UpdateXML(_cp932'<a>x</a>', _latin1'/a', _latin1'<a>y</a>'));
--echo # Same character set arguments still work
SELECT ExtractValue(_cp932'<a>x</a>', _cp932'/a');
SELECT UpdateXML(_latin1'<a>x</a>', _latin1'/a', _latin1'<a>y</a>');
SET NAMES DEFAULT;
--echo # End of 11.8 tests

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,128 @@
--source include/have_cp932.inc
--source include/have_utf32.inc
--echo #
--echo # MDEV-41246 "Illegal mix of collations" on the mysql.user view
--echo #
--disable_query_log
SET @mask='^cp932';
SET @extra_collations_query=
'INSERT INTO collations VALUES'
'(''cp932_japanese_ci''),(''cp932_japanese_nopad_ci''),'
'(''cp932_bin''),(''cp932_nopad_bin'')';
--source include/ctype_tailoring_00.inc
--enable_query_log
--echo #
--echo # DATE_FORMAT() result repertoire depends on the locale
--echo # which is actually used: the explicit third argument, or
--echo # @@lc_time_names. Locale names (e.g. of days) can be non-ASCII.
--echo # cp932_japanese_ci and latin1_swedish_ci are compatible on ASCII, so
--echo # no error is expected, whatever the repertoire of the result is.
--echo #
SET NAMES cp932;
#
# Why this query does not fail with an error:
# DATE_FORMAT('2024-01-02','%W','en_US') = _latin1'a'
# (see DTCollation::aggregate() and aggregate_by_tailoring() in sql/item.cc):
#
# - Both sides are COERCIBLE, the character sets are different (cp932 and
# latin1), and none of them is a Unicode superset of the other.
# - The names of days in en_US are ASCII, so the repertoire of the left side
# is ASCII only (the format string contains '%'). The right side is
# ASCII only too (_latin1'a'). So the rule "Allow convert from ASCII" in
# left_is_superset() does not choose a winner: neither side is a superset.
# - The next step is the tailoring optimization. Both collations
# are PAD, and none of them is a UCA collation. Their tailorings on
# the cumulative ASCII repertoire are equal (ascii7_caseup_ci), as both
# collations convert lower case letters to upper case ones and sort
# all other ASCII characters in the code point order.
# So the collations are compatible on the ASCII repertoire.
# - Any of the two collations can be used for comparison.
# The algorithmically simpler one wins: latin1_swedish_ci has
# mbmaxlen 1, and cp932_japanese_ci has mbmaxlen 2. So the right side
# wins and the left side is converted to latin1. It is safe, as
# the left side is ASCII only.
#
# With a collation which is not compatible with cp932_japanese_ci on
# the ASCII repertoire, e.g. latin5_turkish_ci (it reorders ASCII letters),
# the same query fails with ER_CANT_AGGREGATE_2COLLATIONS. In
# ctype_big5_tailoring.test the partner is latin1, because big5_chinese_ci
# has no tailoring on the ASCII repertoire, so the query fails there.
#
--echo # en_US names are ASCII
SELECT DATE_FORMAT('2024-01-02','%W') = _latin1'a';
SELECT DATE_FORMAT('2024-01-02','%W','en_US') = _latin1'a';
#
# Why the collation of the left side (cp932_japanese_ci) wins in
# DATE_FORMAT('2024-01-02','%W','ru_RU') = _latin1'a'
# (see DTCollation::aggregate() and left_is_superset() in sql/item.cc):
#
# - Both sides have the same derivation: COERCIBLE (a function result
# with a literal format, and a string literal), so the derivation
# cannot decide.
# - The character sets are different (cp932 and latin1), and none of them
# is a Unicode superset of the other.
# - The right side is _latin1'a'. Its repertoire is ASCII only, so it can be
# converted to any ASCII compatible character set without data loss,
# including cp932.
# - The left side is DATE_FORMAT() with the locale ru_RU. The names of days
# in ru_RU are not ASCII, therefore the repertoire of the result
# includes MY_REPERTOIRE_EXTENDED. So it cannot be converted to latin1.
# - Therefore the rule "Allow convert from ASCII" in left_is_superset() says
# that the left side is a superset of the right side: the right side is
# ASCII only, and the left side is not. The left side wins and the right
# side is converted to cp932. The tailoring optimization is not even tried.
#
# If the repertoire of the left side was ASCII only (e.g. with the locale
# en_US), then neither side would be a superset of the other one, and the
# result would depend on the tailoring of the two collations. The result
# of this query would be the same: cp932_japanese_ci and latin1_swedish_ci
# have equal tailorings on the ASCII repertoire.
#
--echo # An explicit non-ASCII locale is not ignored.
--echo # This query does not fail with an error: the DATE_FORMAT() result is
--echo # non-ASCII, so the collation of the result is used for comparison.
--echo # Note, it would not fail even if the result was ASCII, as
--echo # cp932_japanese_ci and latin1_swedish_ci are compatible on ASCII.
SELECT DATE_FORMAT('2024-01-02','%W','ru_RU') = _latin1'a';
--echo # A non-constant locale is not known at the fixing time
SET @loc='en_US';
SELECT DATE_FORMAT('2024-01-02','%W',@loc) = _latin1'a';
--echo # The session locale is not used when the locale is passed explicitly
SET lc_time_names=ru_RU;
SELECT DATE_FORMAT('2024-01-02','%W') = _latin1'a';
SELECT DATE_FORMAT('2024-01-02','%W','en_US') = _latin1'a';
SET lc_time_names=DEFAULT;
SET NAMES DEFAULT;
--echo #
--echo # DATE_FORMAT() with cp932 and latin5. cp932_japanese_ci and
--echo # latin5_turkish_ci are not compatible on ASCII (latin5_turkish_ci
--echo # reorders ASCII letters), so unlike the latin1 queries above,
--echo # the repertoire of the DATE_FORMAT() result decides the outcome.
--echo #
SET NAMES cp932;
--echo # en_US names are ASCII: no side is a superset, and the tailorings
--echo # are not equal, so the query fails
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT DATE_FORMAT('2024-01-02','%W') = _latin5'a';
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT DATE_FORMAT('2024-01-02','%W','en_US') = _latin5'a';
--echo # ru_RU names are not ASCII: the right side is ASCII only, so it
--echo # is converted to cp932, and the left side collation wins
SELECT DATE_FORMAT('2024-01-02','%W','ru_RU') = _latin5'a';
--echo # A non-constant locale is not known at the fixing time
SET @loc='en_US';
SELECT DATE_FORMAT('2024-01-02','%W',@loc) = _latin5'a';
--echo # The session locale is not used when the locale is passed explicitly
SET lc_time_names=ru_RU;
SELECT DATE_FORMAT('2024-01-02','%W') = _latin5'a';
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT DATE_FORMAT('2024-01-02','%W','en_US') = _latin5'a';
SET lc_time_names=DEFAULT;
SET NAMES DEFAULT;
--echo # End of 11.8 tests

View File

@@ -56,3 +56,27 @@ SET sql_mode=DEFAULT;
#
# End of 10.5 tests
#
#
# MDEV-41246 "Illegal mix of collations" on the mysql.user view
#
SET NAMES dec8 COLLATE dec8_swedish_ci;
# ASCII digits
d
1
# ASCII minus, dot and digits
e
-1.5
SELECT c FROM v_tailoring WHERE c='Y';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y_';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y+';
c
Y
SET NAMES dec8 COLLATE dec8_bin;
SELECT c FROM v_tailoring WHERE c='Y';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (dec8_bin,COERCIBLE) for operation '='
SET NAMES DEFAULT;
# End of 11.8 tests

View File

@@ -13,3 +13,22 @@ SET @seq=_dec8 0xD0;
--echo #
--echo # End of 10.5 tests
--echo #
--echo #
--echo # MDEV-41246 "Illegal mix of collations" on the mysql.user view
--echo #
SET NAMES dec8 COLLATE dec8_swedish_ci;
--disable_service_connection
--source include/ctype_tailoring_view_create.inc
--source include/ctype_tailoring_01_probe.inc
SET NAMES dec8 COLLATE dec8_bin;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT c FROM v_tailoring WHERE c='Y';
--source include/ctype_tailoring_view_drop.inc
--enable_service_connection
SET NAMES DEFAULT;
--echo # End of 11.8 tests

View File

@@ -34833,3 +34833,27 @@ c1
#
# End of 10.5 tests
#
#
# MDEV-41246 "Illegal mix of collations" on the mysql.user view
#
SET NAMES eucjpms COLLATE eucjpms_japanese_ci;
# ASCII digits
d
1
# ASCII minus, dot and digits
e
-1.5
SELECT c FROM v_tailoring WHERE c='Y';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y_';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y+';
c
Y
SET NAMES eucjpms COLLATE eucjpms_bin;
SELECT c FROM v_tailoring WHERE c='Y';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (eucjpms_bin,COERCIBLE) for operation '='
SET NAMES DEFAULT;
# End of 11.8 tests

View File

@@ -630,3 +630,22 @@ select strcmp(_eucjpms'' collate eucjpms_nopad_bin, _eucjpms 0x0001050001) as c1
--echo #
--echo # End of 10.5 tests
--echo #
--echo #
--echo # MDEV-41246 "Illegal mix of collations" on the mysql.user view
--echo #
SET NAMES eucjpms COLLATE eucjpms_japanese_ci;
--disable_service_connection
--source include/ctype_tailoring_view_create.inc
--source include/ctype_tailoring_01_probe.inc
SET NAMES eucjpms COLLATE eucjpms_bin;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT c FROM v_tailoring WHERE c='Y';
--source include/ctype_tailoring_view_drop.inc
--enable_service_connection
SET NAMES DEFAULT;
--echo # End of 11.8 tests

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,18 @@
--source include/have_eucjpms.inc
--source include/have_utf32.inc
--echo #
--echo # MDEV-41246 "Illegal mix of collations" on the mysql.user view
--echo #
--disable_query_log
SET @mask='^eucjpms';
SET @extra_collations_query=
'INSERT INTO collations VALUES'
'(''eucjpms_japanese_ci''),(''eucjpms_japanese_nopad_ci''),'
'(''eucjpms_bin''),(''eucjpms_nopad_bin'')';
--source include/ctype_tailoring_00.inc
--enable_query_log
--echo # End of 11.8 tests

View File

@@ -26346,3 +26346,27 @@ c1
#
# End of 10.5 tests
#
#
# MDEV-41246 "Illegal mix of collations" on the mysql.user view
#
SET NAMES euckr COLLATE euckr_korean_ci;
# ASCII digits
d
1
# ASCII minus, dot and digits
e
-1.5
SELECT c FROM v_tailoring WHERE c='Y';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y_';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y+';
c
Y
SET NAMES euckr COLLATE euckr_bin;
SELECT c FROM v_tailoring WHERE c='Y';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (euckr_bin,COERCIBLE) for operation '='
SET NAMES DEFAULT;
# End of 11.8 tests

View File

@@ -260,3 +260,22 @@ select strcmp(_euckr'' collate euckr_nopad_bin, _euckr 0x0001050001) as c1;
--echo #
--echo # End of 10.5 tests
--echo #
--echo #
--echo # MDEV-41246 "Illegal mix of collations" on the mysql.user view
--echo #
SET NAMES euckr COLLATE euckr_korean_ci;
--disable_service_connection
--source include/ctype_tailoring_view_create.inc
--source include/ctype_tailoring_01_probe.inc
SET NAMES euckr COLLATE euckr_bin;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT c FROM v_tailoring WHERE c='Y';
--source include/ctype_tailoring_view_drop.inc
--enable_service_connection
SET NAMES DEFAULT;
--echo # End of 11.8 tests

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,18 @@
--source include/have_euckr.inc
--source include/have_utf32.inc
--echo #
--echo # MDEV-41246 "Illegal mix of collations" on the mysql.user view
--echo #
--disable_query_log
SET @mask='^euckr';
SET @extra_collations_query=
'INSERT INTO collations VALUES'
'(''euckr_korean_ci''),(''euckr_korean_nopad_ci''),'
'(''euckr_bin''),(''euckr_nopad_bin'')';
--source include/ctype_tailoring_00.inc
--enable_query_log
--echo # End of 11.8 tests

View File

@@ -5334,3 +5334,26 @@ c1
#
# End of 10.5 tests
#
#
# MDEV-41246 "Illegal mix of collations" on the mysql.user view
#
SET NAMES gb2312 COLLATE gb2312_chinese_ci;
# ASCII digits
d
1
# ASCII minus, dot and digits
e
-1.5
SELECT c FROM v_tailoring WHERE c='Y';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y_';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y+';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (gb2312_chinese_ci,COERCIBLE) for operation '<>'
SET NAMES gb2312 COLLATE gb2312_bin;
SELECT c FROM v_tailoring WHERE c='Y';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (gb2312_bin,COERCIBLE) for operation '='
SET NAMES DEFAULT;
# End of 11.8 tests

View File

@@ -210,3 +210,22 @@ select strcmp(_gb2312'' collate gb2312_nopad_bin, _gb2312 0x0001050001) as c1;
--echo #
--echo # End of 10.5 tests
--echo #
--echo #
--echo # MDEV-41246 "Illegal mix of collations" on the mysql.user view
--echo #
SET NAMES gb2312 COLLATE gb2312_chinese_ci;
--disable_service_connection
--source include/ctype_tailoring_view_create.inc
--source include/ctype_tailoring_03_probe_last_error.inc
SET NAMES gb2312 COLLATE gb2312_bin;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT c FROM v_tailoring WHERE c='Y';
--source include/ctype_tailoring_view_drop.inc
--enable_service_connection
SET NAMES DEFAULT;
--echo # End of 11.8 tests

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,18 @@
--source include/have_gb2312.inc
--source include/have_utf32.inc
--echo #
--echo # MDEV-41246 "Illegal mix of collations" on the mysql.user view
--echo #
--disable_query_log
SET @mask='^gb2312';
SET @extra_collations_query=
'INSERT INTO collations VALUES'
'(''gb2312_chinese_ci''),(''gb2312_chinese_nopad_ci''),'
'(''gb2312_bin''),(''gb2312_nopad_bin'')';
--source include/ctype_tailoring_00.inc
--enable_query_log
--echo # End of 11.8 tests

View File

@@ -6804,3 +6804,26 @@ strcmp(_gbk'' collate gbk_nopad_bin, _gbk 0x0001050001)
#
# End of 10.5 tests
#
#
# MDEV-41246 "Illegal mix of collations" on the mysql.user view
#
SET NAMES gbk COLLATE gbk_chinese_ci;
# ASCII digits
d
1
# ASCII minus, dot and digits
e
-1.5
SELECT c FROM v_tailoring WHERE c='Y';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y_';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y+';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (gbk_chinese_ci,COERCIBLE) for operation '<>'
SET NAMES gbk COLLATE gbk_bin;
SELECT c FROM v_tailoring WHERE c='Y';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (gbk_bin,COERCIBLE) for operation '='
SET NAMES DEFAULT;
# End of 11.8 tests

View File

@@ -513,3 +513,22 @@ select strcmp(_gbk'' collate gbk_nopad_bin, _gbk 0x0001050001);
--echo #
--echo # End of 10.5 tests
--echo #
--echo #
--echo # MDEV-41246 "Illegal mix of collations" on the mysql.user view
--echo #
SET NAMES gbk COLLATE gbk_chinese_ci;
--disable_service_connection
--source include/ctype_tailoring_view_create.inc
--source include/ctype_tailoring_03_probe_last_error.inc
SET NAMES gbk COLLATE gbk_bin;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT c FROM v_tailoring WHERE c='Y';
--source include/ctype_tailoring_view_drop.inc
--enable_service_connection
SET NAMES DEFAULT;
--echo # End of 11.8 tests

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,18 @@
--source include/have_gbk.inc
--source include/have_utf32.inc
--echo #
--echo # MDEV-41246 "Illegal mix of collations" on the mysql.user view
--echo #
--disable_query_log
SET @mask='^gbk';
SET @extra_collations_query=
'INSERT INTO collations VALUES'
'(''gbk_chinese_ci''),(''gbk_chinese_nopad_ci''),'
'(''gbk_bin''),(''gbk_nopad_bin'')';
--source include/ctype_tailoring_00.inc
--enable_query_log
--echo # End of 11.8 tests

View File

@@ -0,0 +1,23 @@
#
# MDEV-41246 "Illegal mix of collations" on the mysql.user view
#
SET NAMES geostd8 COLLATE geostd8_general_ci;
# ASCII digits
d
1
# ASCII minus, dot and digits
e
-1.5
SELECT c FROM v_tailoring WHERE c='Y';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y_';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y+';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (geostd8_general_ci,COERCIBLE) for operation '<>'
SET NAMES geostd8 COLLATE geostd8_bin;
SELECT c FROM v_tailoring WHERE c='Y';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (geostd8_bin,COERCIBLE) for operation '='
SET NAMES DEFAULT;
# End of 11.8 tests

View File

@@ -0,0 +1,17 @@
--echo #
--echo # MDEV-41246 "Illegal mix of collations" on the mysql.user view
--echo #
SET NAMES geostd8 COLLATE geostd8_general_ci;
--disable_service_connection
--source include/ctype_tailoring_view_create.inc
--source include/ctype_tailoring_03_probe_last_error.inc
SET NAMES geostd8 COLLATE geostd8_bin;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT c FROM v_tailoring WHERE c='Y';
--source include/ctype_tailoring_view_drop.inc
--enable_service_connection
SET NAMES DEFAULT;
--echo # End of 11.8 tests

View File

@@ -0,0 +1,24 @@
#
# MDEV-41246 "Illegal mix of collations" on the mysql.user view
#
SET NAMES greek COLLATE greek_general_ci;
# ASCII digits
d
1
# ASCII minus, dot and digits
e
-1.5
SELECT c FROM v_tailoring WHERE c='Y';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y_';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y+';
c
Y
SET NAMES greek COLLATE greek_bin;
SELECT c FROM v_tailoring WHERE c='Y';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (greek_bin,COERCIBLE) for operation '='
SET NAMES DEFAULT;
# End of 11.8 tests

View File

@@ -0,0 +1,17 @@
--echo #
--echo # MDEV-41246 "Illegal mix of collations" on the mysql.user view
--echo #
SET NAMES greek COLLATE greek_general_ci;
--disable_service_connection
--source include/ctype_tailoring_view_create.inc
--source include/ctype_tailoring_01_probe.inc
SET NAMES greek COLLATE greek_bin;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT c FROM v_tailoring WHERE c='Y';
--source include/ctype_tailoring_view_drop.inc
--enable_service_connection
SET NAMES DEFAULT;
--echo # End of 11.8 tests

View File

@@ -9,3 +9,27 @@ E2808E
E2808F
DROP TABLE t1;
End of 4.1 tests
#
# MDEV-41246 "Illegal mix of collations" on the mysql.user view
#
SET NAMES hebrew COLLATE hebrew_general_ci;
# ASCII digits
d
1
# ASCII minus, dot and digits
e
-1.5
SELECT c FROM v_tailoring WHERE c='Y';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y_';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y+';
c
Y
SET NAMES hebrew COLLATE hebrew_bin;
SELECT c FROM v_tailoring WHERE c='Y';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (hebrew_bin,COERCIBLE) for operation '='
SET NAMES DEFAULT;
# End of 11.8 tests

View File

@@ -14,3 +14,21 @@ SELECT HEX(a) FROM t1;
DROP TABLE t1;
--echo End of 4.1 tests
--echo #
--echo # MDEV-41246 "Illegal mix of collations" on the mysql.user view
--echo #
SET NAMES hebrew COLLATE hebrew_general_ci;
--disable_service_connection
--source include/ctype_tailoring_view_create.inc
--source include/ctype_tailoring_01_probe.inc
SET NAMES hebrew COLLATE hebrew_bin;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT c FROM v_tailoring WHERE c='Y';
--source include/ctype_tailoring_view_drop.inc
--enable_service_connection
SET NAMES DEFAULT;
--echo # End of 11.8 tests

View File

@@ -0,0 +1,23 @@
#
# MDEV-41246 "Illegal mix of collations" on the mysql.user view
#
SET NAMES hp8 COLLATE hp8_english_ci;
# ASCII digits
d
1
# ASCII minus, dot and digits
e
-1.5
SELECT c FROM v_tailoring WHERE c='Y';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y_';
c
Y
SELECT c FROM v_tailoring WHERE c<>'Y+';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (hp8_english_ci,COERCIBLE) for operation '<>'
SET NAMES hp8 COLLATE hp8_bin;
SELECT c FROM v_tailoring WHERE c='Y';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (hp8_bin,COERCIBLE) for operation '='
SET NAMES DEFAULT;
# End of 11.8 tests

View File

@@ -0,0 +1,17 @@
--echo #
--echo # MDEV-41246 "Illegal mix of collations" on the mysql.user view
--echo #
SET NAMES hp8 COLLATE hp8_english_ci;
--disable_service_connection
--source include/ctype_tailoring_view_create.inc
--source include/ctype_tailoring_03_probe_last_error.inc
SET NAMES hp8 COLLATE hp8_bin;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT c FROM v_tailoring WHERE c='Y';
--source include/ctype_tailoring_view_drop.inc
--enable_service_connection
SET NAMES DEFAULT;
--echo # End of 11.8 tests

Some files were not shown because too many files have changed in this diff Show More