mirror of
https://github.com/MariaDB/server.git
synced 2025-07-27 18:02:13 +03:00
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)
This commit is contained in:
58
mysql-test/main/mysql_connector_net.ps1
Normal file
58
mysql-test/main/mysql_connector_net.ps1
Normal file
@ -0,0 +1,58 @@
|
||||
$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
|
||||
}
|
||||
}
|
2
mysql-test/main/mysql_connector_net.result
Normal file
2
mysql-test/main/mysql_connector_net.result
Normal file
@ -0,0 +1,2 @@
|
||||
@@old_mode
|
||||
UTF8_IS_UTF8MB3,NO_NULL_COLLATION_IDS
|
11
mysql-test/main/mysql_connector_net.test
Normal file
11
mysql-test/main/mysql_connector_net.test
Normal file
@ -0,0 +1,11 @@
|
||||
--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
|
||||
}
|
@ -1,4 +1,6 @@
|
||||
@@ -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
|
||||
window on windows.
|
||||
--core-file Write core on crashes
|
||||
@ -6,7 +8,7 @@
|
||||
-h, --datadir=name Path to the database root directory
|
||||
--date-format=name The DATE format (ignored)
|
||||
--datetime-format=name
|
||||
@@ -650,6 +651,7 @@
|
||||
@@ -696,6 +697,7 @@
|
||||
Use MySQL-5.6 (instead of MariaDB-5.3) format for TIME,
|
||||
DATETIME, TIMESTAMP columns.
|
||||
(Defaults to on; use --skip-mysql56-temporal-format to disable.)
|
||||
@ -14,7 +16,7 @@
|
||||
--net-buffer-length=#
|
||||
Buffer length for TCP/IP and socket communication
|
||||
--net-read-timeout=#
|
||||
@@ -1327,6 +1328,10 @@
|
||||
@@ -1351,6 +1353,10 @@
|
||||
Alias for log_slow_query_file. Log slow queries to given
|
||||
log file. Defaults logging to 'hostname'-slow.log. Must
|
||||
be enabled to activate other slow log options
|
||||
@ -25,7 +27,7 @@
|
||||
--socket=name Socket file to use for connection
|
||||
--sort-buffer-size=#
|
||||
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.
|
||||
--stack-trace Print a symbolic stack trace on failure
|
||||
(Defaults to on; use --skip-stack-trace to disable.)
|
||||
@ -33,7 +35,7 @@
|
||||
--standard-compliant-cte
|
||||
Allow only CTEs compliant to SQL standard
|
||||
(Defaults to on; use --skip-standard-compliant-cte to disable.)
|
||||
@@ -1426,6 +1432,11 @@
|
||||
@@ -1454,6 +1461,11 @@
|
||||
--thread-pool-max-threads=#
|
||||
Maximum allowed number of worker threads in the thread
|
||||
pool
|
||||
@ -45,7 +47,7 @@
|
||||
--thread-pool-oversubscribe=#
|
||||
How many additional active worker threads in a group are
|
||||
allowed.
|
||||
@@ -1464,8 +1475,8 @@
|
||||
@@ -1493,8 +1505,8 @@
|
||||
automatically convert it to an on-disk MyISAM or Aria
|
||||
table.
|
||||
-t, --tmpdir=name Path for temporary files. Several paths may be specified,
|
||||
@ -56,7 +58,7 @@
|
||||
--transaction-alloc-block-size=#
|
||||
Allocation block size for transactions to be stored in
|
||||
binary log
|
||||
@@ -1685,6 +1696,7 @@
|
||||
@@ -1716,6 +1728,7 @@
|
||||
myisam-stats-method NULLS_UNEQUAL
|
||||
myisam-use-mmap FALSE
|
||||
mysql56-temporal-format TRUE
|
||||
@ -64,7 +66,7 @@
|
||||
net-buffer-length 16384
|
||||
net-read-timeout 30
|
||||
net-retry-count 10
|
||||
@@ -1841,6 +1853,7 @@
|
||||
@@ -1874,6 +1887,7 @@
|
||||
slave-type-conversions
|
||||
slow-launch-time 2
|
||||
slow-query-log FALSE
|
||||
@ -72,7 +74,7 @@
|
||||
sort-buffer-size 2097152
|
||||
sql-mode STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
|
||||
sql-safe-updates FALSE
|
||||
@@ -1867,6 +1880,8 @@
|
||||
@@ -1901,6 +1915,8 @@
|
||||
thread-pool-exact-stats FALSE
|
||||
thread-pool-idle-timeout 60
|
||||
thread-pool-max-threads 65536
|
||||
|
@ -721,7 +721,8 @@ The following specify which files/extra groups are read (specified before remain
|
||||
MySQL versions. Any combination of:
|
||||
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
|
||||
IGNORE_INDEX_ONLY_FOR_JOIN, COMPAT_5_1_CHECKSUM,
|
||||
NO_NULL_COLLATION_IDS
|
||||
Use 'ALL' to set all combinations.
|
||||
--old-passwords Use old password encryption method (needed for 4.0 and
|
||||
older clients)
|
||||
|
@ -257,3 +257,13 @@ Warning 1264 Out of range value for column 'a' at row 2
|
||||
DROP TABLE t1;
|
||||
SET @@time_zone=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;
|
||||
|
||||
SET @@time_zone=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;
|
||||
SELECT @@global.old_mode;
|
||||
@@global.old_mode
|
||||
ZERO_DATE_TIME_CAST
|
||||
SET @@global.old_mode = 64;
|
||||
ERROR 42000: Variable 'old_mode' can't be set to the value of '64'
|
||||
SET @@global.old_mode = 128;
|
||||
ERROR 42000: Variable 'old_mode' can't be set to the value of '128'
|
||||
SELECT @@global.old_mode;
|
||||
@@global.old_mode
|
||||
ZERO_DATE_TIME_CAST
|
||||
|
@ -2299,7 +2299,7 @@ VARIABLE_COMMENT Used to emulate old behavior from earlier MariaDB or MySQL vers
|
||||
NUMERIC_MIN_VALUE NULL
|
||||
NUMERIC_MAX_VALUE 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
|
||||
COMMAND_LINE_ARGUMENT REQUIRED
|
||||
VARIABLE_NAME OLD_PASSWORDS
|
||||
|
@ -2469,7 +2469,7 @@ VARIABLE_COMMENT Used to emulate old behavior from earlier MariaDB or MySQL vers
|
||||
NUMERIC_MIN_VALUE NULL
|
||||
NUMERIC_MAX_VALUE 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
|
||||
COMMAND_LINE_ARGUMENT REQUIRED
|
||||
VARIABLE_NAME OLD_PASSWORDS
|
||||
|
@ -172,7 +172,7 @@ SET @@global.old_mode = 4;
|
||||
SELECT @@global.old_mode;
|
||||
|
||||
--Error ER_WRONG_VALUE_FOR_VAR
|
||||
SET @@global.old_mode = 64;
|
||||
SET @@global.old_mode = 128;
|
||||
SELECT @@global.old_mode;
|
||||
|
||||
# use of decimal values
|
||||
|
@ -13576,8 +13576,37 @@ static bool find_mpvio_user(MPVIO_EXT *mpvio)
|
||||
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
|
||||
read_client_connect_attrs(char **ptr, char *end, CHARSET_INFO *from_cs)
|
||||
read_client_connect_attrs(char **ptr, char *end, THD* thd)
|
||||
{
|
||||
ulonglong length;
|
||||
char *ptr_save= *ptr;
|
||||
@ -13600,10 +13629,14 @@ read_client_connect_attrs(char **ptr, char *end, CHARSET_INFO *from_cs)
|
||||
if (length > 65535)
|
||||
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)
|
||||
sql_print_warning("Connection attributes of length %llu were truncated",
|
||||
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;
|
||||
}
|
||||
|
||||
@ -13737,7 +13770,7 @@ static bool parse_com_change_user_packet(MPVIO_EXT *mpvio, uint packet_length)
|
||||
}
|
||||
|
||||
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),
|
||||
MYF(0));
|
||||
@ -13987,7 +14020,7 @@ static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio,
|
||||
|
||||
if ((thd->client_capabilities & CLIENT_CONNECT_ATTRS) &&
|
||||
read_client_connect_attrs(&next_field, ((char *)net->read_pos) + pkt_len,
|
||||
mpvio->auth_info.thd->charset()))
|
||||
mpvio->auth_info.thd))
|
||||
return packet_error;
|
||||
|
||||
/*
|
||||
|
@ -201,6 +201,7 @@ enum enum_binlog_row_image {
|
||||
#define OLD_MODE_UTF8_IS_UTF8MB3 (1 << 3)
|
||||
#define OLD_MODE_IGNORE_INDEX_ONLY_FOR_JOIN (1 << 4)
|
||||
#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 empty_c_string[1];
|
||||
|
@ -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);
|
||||
LEX_CSTRING full_collation_name=
|
||||
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.
|
||||
Display them only once, with the short name (without the
|
||||
|
@ -3886,6 +3886,7 @@ static const char *old_mode_names[]=
|
||||
"UTF8_IS_UTF8MB3",
|
||||
"IGNORE_INDEX_ONLY_FOR_JOIN",
|
||||
"COMPAT_5_1_CHECKSUM",
|
||||
"NO_NULL_COLLATION_IDS",
|
||||
0
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user