Commit 9d07b052 authored by Vladislav Vaintroub's avatar Vladislav Vaintroub

MDEV-31608 - Connector/NET fails to connect since 10.10

Connector/NET does not expect collation IDs returned by "show collations"
to be NULL, runs into an exception.

The fix is to determine connector/net using its connection attributes,
then make sure "show collations" does not output NULL IDs.

The patch introduces new old_mode NO_NULL_COLLATION_IDs, that is
automatically set, once MySQL Connector/NET connection is determined.

A test was added, that uses MySql.Data from powershell - only works
if MySql.Data is installed into GAC (i.e with C/NET MSI package)
parent 6d0bcfc4
$assembly = [system.reflection.Assembly]::LoadWithPartialName("MySql.Data")
if ($assembly -eq $null)
{
"Can't load assembly MySql.Data"
exit 100
}
try
{
$connectionString =[string]::Format("server=127.0.0.1;uid=root;port={0};Connection Reset=true;",$Env:MASTER_MYPORT)
$connection = [MySql.Data.MySqlClient.MySqlConnection]@{ConnectionString=$connectionString}
$connection.Open()
# Test ExecuteReader()
$command = New-Object MySql.Data.MySqlClient.MySqlCommand
$command.Connection = $connection
$command.CommandText = "SELECT @@old_mode"
$reader = $command.ExecuteReader()
$reader.GetName(0)
while ($reader.Read())
{
$reader.GetValue(0)
}
# Test connection reset
$connection.Close()
$connection.Open()
# Test ExecuteNonQuery()
$command.CommandText="do 1";
$affected_rows = $command.ExecuteNonQuery()
if ($affected_rows -ne 0)
{
"Expected affected rows 0, actual $affected_rows"
exit 1
}
# Test Prepared Statement
$command.CommandText = "SELECT @var";
[void]$command.Parameters.AddWithValue("@var", 1);
$command.Prepare();
$out = $command.ExecuteScalar();
if ($out -ne 1)
{
"Expected output 1, actual $out"
exit 1
}
$connection.Close()
}
catch
{
# Dump exception
$_
$inner = $PSItem.Exception.InnerException
if ($inner -ne $null)
{
$PSItem.Exception.InnerException.Message
$PSItem.Exception.InnerException.StackTrace
}
}
@@old_mode
UTF8_IS_UTF8MB3,NO_NULL_COLLATION_IDS
--source include/windows.inc
let $sys_errno=0;
# Error 100 is returned by the powershell script
# if MySql.Data is not installed
--error 0,100
--exec powershell -NoLogo -NoProfile -File main\mysql_connector_net.ps1
if ($sys_errno != 0)
{
--skip Connector/NET is not installed
}
@@ -180,6 +180,7 @@ --- main/mysqld--help.result 2023-11-30 02:21:51.951132200 +0100
+++ main/mysqld--help,win.reject 2023-11-30 02:35:44.404612300 +0100
@@ -191,6 +191,7 @@
--console Write error output on screen; don't remove the console --console Write error output on screen; don't remove the console
window on windows. window on windows.
--core-file Write core on crashes --core-file Write core on crashes
...@@ -6,7 +8,7 @@ ...@@ -6,7 +8,7 @@
-h, --datadir=name Path to the database root directory -h, --datadir=name Path to the database root directory
--date-format=name The DATE format (ignored) --date-format=name The DATE format (ignored)
--datetime-format=name --datetime-format=name
@@ -650,6 +651,7 @@ @@ -696,6 +697,7 @@
Use MySQL-5.6 (instead of MariaDB-5.3) format for TIME, Use MySQL-5.6 (instead of MariaDB-5.3) format for TIME,
DATETIME, TIMESTAMP columns. DATETIME, TIMESTAMP columns.
(Defaults to on; use --skip-mysql56-temporal-format to disable.) (Defaults to on; use --skip-mysql56-temporal-format to disable.)
...@@ -14,7 +16,7 @@ ...@@ -14,7 +16,7 @@
--net-buffer-length=# --net-buffer-length=#
Buffer length for TCP/IP and socket communication Buffer length for TCP/IP and socket communication
--net-read-timeout=# --net-read-timeout=#
@@ -1327,6 +1328,10 @@ @@ -1351,6 +1353,10 @@
Alias for log_slow_query_file. Log slow queries to given Alias for log_slow_query_file. Log slow queries to given
log file. Defaults logging to 'hostname'-slow.log. Must log file. Defaults logging to 'hostname'-slow.log. Must
be enabled to activate other slow log options be enabled to activate other slow log options
...@@ -25,7 +27,7 @@ ...@@ -25,7 +27,7 @@
--socket=name Socket file to use for connection --socket=name Socket file to use for connection
--sort-buffer-size=# --sort-buffer-size=#
Each thread that needs to do a sort allocates a buffer of Each thread that needs to do a sort allocates a buffer of
@@ -1351,6 +1356,7 @@ @@ -1376,6 +1382,7 @@
deleting or updating every row in a table. deleting or updating every row in a table.
--stack-trace Print a symbolic stack trace on failure --stack-trace Print a symbolic stack trace on failure
(Defaults to on; use --skip-stack-trace to disable.) (Defaults to on; use --skip-stack-trace to disable.)
...@@ -33,7 +35,7 @@ ...@@ -33,7 +35,7 @@
--standard-compliant-cte --standard-compliant-cte
Allow only CTEs compliant to SQL standard Allow only CTEs compliant to SQL standard
(Defaults to on; use --skip-standard-compliant-cte to disable.) (Defaults to on; use --skip-standard-compliant-cte to disable.)
@@ -1426,6 +1432,11 @@ @@ -1454,6 +1461,11 @@
--thread-pool-max-threads=# --thread-pool-max-threads=#
Maximum allowed number of worker threads in the thread Maximum allowed number of worker threads in the thread
pool pool
...@@ -45,7 +47,7 @@ ...@@ -45,7 +47,7 @@
--thread-pool-oversubscribe=# --thread-pool-oversubscribe=#
How many additional active worker threads in a group are How many additional active worker threads in a group are
allowed. allowed.
@@ -1464,8 +1475,8 @@ @@ -1493,8 +1505,8 @@
automatically convert it to an on-disk MyISAM or Aria automatically convert it to an on-disk MyISAM or Aria
table. table.
-t, --tmpdir=name Path for temporary files. Several paths may be specified, -t, --tmpdir=name Path for temporary files. Several paths may be specified,
...@@ -56,7 +58,7 @@ ...@@ -56,7 +58,7 @@
--transaction-alloc-block-size=# --transaction-alloc-block-size=#
Allocation block size for transactions to be stored in Allocation block size for transactions to be stored in
binary log binary log
@@ -1685,6 +1696,7 @@ @@ -1716,6 +1728,7 @@
myisam-stats-method NULLS_UNEQUAL myisam-stats-method NULLS_UNEQUAL
myisam-use-mmap FALSE myisam-use-mmap FALSE
mysql56-temporal-format TRUE mysql56-temporal-format TRUE
...@@ -64,7 +66,7 @@ ...@@ -64,7 +66,7 @@
net-buffer-length 16384 net-buffer-length 16384
net-read-timeout 30 net-read-timeout 30
net-retry-count 10 net-retry-count 10
@@ -1841,6 +1853,7 @@ @@ -1874,6 +1887,7 @@
slave-type-conversions slave-type-conversions
slow-launch-time 2 slow-launch-time 2
slow-query-log FALSE slow-query-log FALSE
...@@ -72,7 +74,7 @@ ...@@ -72,7 +74,7 @@
sort-buffer-size 2097152 sort-buffer-size 2097152
sql-mode STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION sql-mode STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
sql-safe-updates FALSE sql-safe-updates FALSE
@@ -1867,6 +1880,8 @@ @@ -1901,6 +1915,8 @@
thread-pool-exact-stats FALSE thread-pool-exact-stats FALSE
thread-pool-idle-timeout 60 thread-pool-idle-timeout 60
thread-pool-max-threads 65536 thread-pool-max-threads 65536
......
...@@ -721,7 +721,8 @@ The following specify which files/extra groups are read (specified before remain ...@@ -721,7 +721,8 @@ The following specify which files/extra groups are read (specified before remain
MySQL versions. Any combination of: MySQL versions. Any combination of:
NO_DUP_KEY_WARNINGS_WITH_IGNORE, NO_PROGRESS_INFO, NO_DUP_KEY_WARNINGS_WITH_IGNORE, NO_PROGRESS_INFO,
ZERO_DATE_TIME_CAST, UTF8_IS_UTF8MB3, ZERO_DATE_TIME_CAST, UTF8_IS_UTF8MB3,
IGNORE_INDEX_ONLY_FOR_JOIN, COMPAT_5_1_CHECKSUM IGNORE_INDEX_ONLY_FOR_JOIN, COMPAT_5_1_CHECKSUM,
NO_NULL_COLLATION_IDS
Use 'ALL' to set all combinations. Use 'ALL' to set all combinations.
--old-passwords Use old password encryption method (needed for 4.0 and --old-passwords Use old password encryption method (needed for 4.0 and
older clients) older clients)
......
...@@ -257,3 +257,13 @@ Warning 1264 Out of range value for column 'a' at row 2 ...@@ -257,3 +257,13 @@ Warning 1264 Out of range value for column 'a' at row 2
DROP TABLE t1; DROP TABLE t1;
SET @@time_zone=DEFAULT; SET @@time_zone=DEFAULT;
SET TIMESTAMP=DEFAULT; SET TIMESTAMP=DEFAULT;
#
# MDEV-31608 - Connector/NET fails to connect since 10.10
#
select count(*) > 0 from information_schema.collations where id IS NULL;
count(*) > 0
1
SET old_mode=no_null_collation_ids;
select count(*) > 0 from information_schema.collations where id IS NULL;
count(*) > 0
0
...@@ -169,3 +169,11 @@ DROP TABLE t1; ...@@ -169,3 +169,11 @@ DROP TABLE t1;
SET @@time_zone=DEFAULT; SET @@time_zone=DEFAULT;
SET TIMESTAMP=DEFAULT; SET TIMESTAMP=DEFAULT;
--echo #
--echo # MDEV-31608 - Connector/NET fails to connect since 10.10
--echo #
select count(*) > 0 from information_schema.collations where id IS NULL;
SET old_mode=no_null_collation_ids;
select count(*) > 0 from information_schema.collations where id IS NULL;
...@@ -114,8 +114,8 @@ SET @@global.old_mode = 4; ...@@ -114,8 +114,8 @@ SET @@global.old_mode = 4;
SELECT @@global.old_mode; SELECT @@global.old_mode;
@@global.old_mode @@global.old_mode
ZERO_DATE_TIME_CAST ZERO_DATE_TIME_CAST
SET @@global.old_mode = 64; SET @@global.old_mode = 128;
ERROR 42000: Variable 'old_mode' can't be set to the value of '64' ERROR 42000: Variable 'old_mode' can't be set to the value of '128'
SELECT @@global.old_mode; SELECT @@global.old_mode;
@@global.old_mode @@global.old_mode
ZERO_DATE_TIME_CAST ZERO_DATE_TIME_CAST
......
...@@ -2299,7 +2299,7 @@ VARIABLE_COMMENT Used to emulate old behavior from earlier MariaDB or MySQL vers ...@@ -2299,7 +2299,7 @@ VARIABLE_COMMENT Used to emulate old behavior from earlier MariaDB or MySQL vers
NUMERIC_MIN_VALUE NULL NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST NO_DUP_KEY_WARNINGS_WITH_IGNORE,NO_PROGRESS_INFO,ZERO_DATE_TIME_CAST,UTF8_IS_UTF8MB3,IGNORE_INDEX_ONLY_FOR_JOIN,COMPAT_5_1_CHECKSUM ENUM_VALUE_LIST NO_DUP_KEY_WARNINGS_WITH_IGNORE,NO_PROGRESS_INFO,ZERO_DATE_TIME_CAST,UTF8_IS_UTF8MB3,IGNORE_INDEX_ONLY_FOR_JOIN,COMPAT_5_1_CHECKSUM,NO_NULL_COLLATION_IDS
READ_ONLY NO READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME OLD_PASSWORDS VARIABLE_NAME OLD_PASSWORDS
......
...@@ -2469,7 +2469,7 @@ VARIABLE_COMMENT Used to emulate old behavior from earlier MariaDB or MySQL vers ...@@ -2469,7 +2469,7 @@ VARIABLE_COMMENT Used to emulate old behavior from earlier MariaDB or MySQL vers
NUMERIC_MIN_VALUE NULL NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST NO_DUP_KEY_WARNINGS_WITH_IGNORE,NO_PROGRESS_INFO,ZERO_DATE_TIME_CAST,UTF8_IS_UTF8MB3,IGNORE_INDEX_ONLY_FOR_JOIN,COMPAT_5_1_CHECKSUM ENUM_VALUE_LIST NO_DUP_KEY_WARNINGS_WITH_IGNORE,NO_PROGRESS_INFO,ZERO_DATE_TIME_CAST,UTF8_IS_UTF8MB3,IGNORE_INDEX_ONLY_FOR_JOIN,COMPAT_5_1_CHECKSUM,NO_NULL_COLLATION_IDS
READ_ONLY NO READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME OLD_PASSWORDS VARIABLE_NAME OLD_PASSWORDS
......
...@@ -172,7 +172,7 @@ SET @@global.old_mode = 4; ...@@ -172,7 +172,7 @@ SET @@global.old_mode = 4;
SELECT @@global.old_mode; SELECT @@global.old_mode;
--Error ER_WRONG_VALUE_FOR_VAR --Error ER_WRONG_VALUE_FOR_VAR
SET @@global.old_mode = 64; SET @@global.old_mode = 128;
SELECT @@global.old_mode; SELECT @@global.old_mode;
# use of decimal values # use of decimal values
......
...@@ -13576,8 +13576,37 @@ static bool find_mpvio_user(MPVIO_EXT *mpvio) ...@@ -13576,8 +13576,37 @@ static bool find_mpvio_user(MPVIO_EXT *mpvio)
DBUG_RETURN(0); DBUG_RETURN(0);
} }
/**
Determine if the client is MySQL Connector/NET.
Checks whether the given connection attributes blob corresponds to
MySQL Connector/NET by examining the "_client_name" attribute, which is
expected to be the first attribute in the blob.
@param connection_attrs - The connection attributes blob.
@param length - The length of the blob.
@return true if the client is MySQL Connector/NET, false otherwise.
*/
static inline bool is_connector_net_client(const char *connection_attrs,
size_t length)
{
constexpr LEX_CSTRING prefix=
{STRING_WITH_LEN("\x0c_client_name\x13mysql-connector-net")};
if (length < prefix.length)
return false;
/* Optimization to avoid following memcmp in common cases.*/
if (connection_attrs[prefix.length - 1] != prefix.str[prefix.length - 1])
return false;
return !memcmp(connection_attrs, prefix.str, prefix.length);
}
static bool static bool
read_client_connect_attrs(char **ptr, char *end, CHARSET_INFO *from_cs) read_client_connect_attrs(char **ptr, char *end, THD* thd)
{ {
ulonglong length; ulonglong length;
char *ptr_save= *ptr; char *ptr_save= *ptr;
...@@ -13600,10 +13629,14 @@ read_client_connect_attrs(char **ptr, char *end, CHARSET_INFO *from_cs) ...@@ -13600,10 +13629,14 @@ read_client_connect_attrs(char **ptr, char *end, CHARSET_INFO *from_cs)
if (length > 65535) if (length > 65535)
return true; return true;
if (PSI_CALL_set_thread_connect_attrs(*ptr, (uint)length, from_cs) && if (PSI_CALL_set_thread_connect_attrs(*ptr, (uint)length, thd->charset()) &&
current_thd->variables.log_warnings) current_thd->variables.log_warnings)
sql_print_warning("Connection attributes of length %llu were truncated", sql_print_warning("Connection attributes of length %llu were truncated",
length); length);
/* Connector/Net crashes, when "show collations" returns NULL IDs*/
if (is_connector_net_client(*ptr, length))
thd->variables.old_behavior |= OLD_MODE_NO_NULL_COLLATION_IDS;
return false; return false;
} }
...@@ -13737,7 +13770,7 @@ static bool parse_com_change_user_packet(MPVIO_EXT *mpvio, uint packet_length) ...@@ -13737,7 +13770,7 @@ static bool parse_com_change_user_packet(MPVIO_EXT *mpvio, uint packet_length)
} }
if ((thd->client_capabilities & CLIENT_CONNECT_ATTRS) && if ((thd->client_capabilities & CLIENT_CONNECT_ATTRS) &&
read_client_connect_attrs(&next_field, end, thd->charset())) read_client_connect_attrs(&next_field, end, thd))
{ {
my_message(ER_UNKNOWN_COM_ERROR, ER_THD(thd, ER_UNKNOWN_COM_ERROR), my_message(ER_UNKNOWN_COM_ERROR, ER_THD(thd, ER_UNKNOWN_COM_ERROR),
MYF(0)); MYF(0));
...@@ -13987,7 +14020,7 @@ static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio, ...@@ -13987,7 +14020,7 @@ static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio,
if ((thd->client_capabilities & CLIENT_CONNECT_ATTRS) && if ((thd->client_capabilities & CLIENT_CONNECT_ATTRS) &&
read_client_connect_attrs(&next_field, ((char *)net->read_pos) + pkt_len, read_client_connect_attrs(&next_field, ((char *)net->read_pos) + pkt_len,
mpvio->auth_info.thd->charset())) mpvio->auth_info.thd))
return packet_error; return packet_error;
/* /*
......
...@@ -201,6 +201,7 @@ enum enum_binlog_row_image { ...@@ -201,6 +201,7 @@ enum enum_binlog_row_image {
#define OLD_MODE_UTF8_IS_UTF8MB3 (1 << 3) #define OLD_MODE_UTF8_IS_UTF8MB3 (1 << 3)
#define OLD_MODE_IGNORE_INDEX_ONLY_FOR_JOIN (1 << 4) #define OLD_MODE_IGNORE_INDEX_ONLY_FOR_JOIN (1 << 4)
#define OLD_MODE_COMPAT_5_1_CHECKSUM (1 << 5) #define OLD_MODE_COMPAT_5_1_CHECKSUM (1 << 5)
#define OLD_MODE_NO_NULL_COLLATION_IDS (1 << 6)
extern char internal_table_name[2]; extern char internal_table_name[2];
extern char empty_c_string[1]; extern char empty_c_string[1];
......
...@@ -6398,7 +6398,8 @@ int fill_schema_collation(THD *thd, TABLE_LIST *tables, COND *cond) ...@@ -6398,7 +6398,8 @@ int fill_schema_collation(THD *thd, TABLE_LIST *tables, COND *cond)
tmp_cl->get_collation_name(MY_COLLATION_NAME_MODE_CONTEXT); tmp_cl->get_collation_name(MY_COLLATION_NAME_MODE_CONTEXT);
LEX_CSTRING full_collation_name= LEX_CSTRING full_collation_name=
tmp_cl->get_collation_name(MY_COLLATION_NAME_MODE_FULL); tmp_cl->get_collation_name(MY_COLLATION_NAME_MODE_FULL);
bool is_context= cmp(context_collation_name, full_collation_name); bool is_context= cmp(context_collation_name, full_collation_name) &&
!(thd->variables.old_behavior & OLD_MODE_NO_NULL_COLLATION_IDS);
/* /*
Some collations are applicable to multiple character sets. Some collations are applicable to multiple character sets.
Display them only once, with the short name (without the Display them only once, with the short name (without the
......
...@@ -3886,6 +3886,7 @@ static const char *old_mode_names[]= ...@@ -3886,6 +3886,7 @@ static const char *old_mode_names[]=
"UTF8_IS_UTF8MB3", "UTF8_IS_UTF8MB3",
"IGNORE_INDEX_ONLY_FOR_JOIN", "IGNORE_INDEX_ONLY_FOR_JOIN",
"COMPAT_5_1_CHECKSUM", "COMPAT_5_1_CHECKSUM",
"NO_NULL_COLLATION_IDS",
0 0
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment