feat: support ancient mysql versions (5.0+)

This commit is contained in:
Ryan Leckey 2020-07-18 21:43:05 -07:00
parent 49ffcf6f46
commit cdd88b5338
5 changed files with 59 additions and 9 deletions

View File

@ -2,7 +2,9 @@ use bytes::Bytes;
use crate::common::StatementCache;
use crate::error::Error;
use crate::mysql::connection::{tls, MySqlStream, COLLATE_UTF8MB4_UNICODE_CI, MAX_PACKET_SIZE};
use crate::mysql::connection::{
tls, MySqlStream, COLLATE_UTF8MB4_UNICODE_CI, COLLATE_UTF8_UNICODE_CI, MAX_PACKET_SIZE,
};
use crate::mysql::protocol::connect::{
AuthSwitchRequest, AuthSwitchResponse, Handshake, HandshakeResponse,
};
@ -22,6 +24,35 @@ impl MySqlConnection {
let mut plugin = handshake.auth_plugin;
let mut nonce = handshake.auth_plugin_data;
// FIXME: server version parse is a bit ugly
// expecting MAJOR.MINOR.PATCH
let mut server_version = handshake.server_version.split('.');
let server_version_major: u16 = server_version
.next()
.unwrap_or_default()
.parse()
.unwrap_or(0);
let server_version_minor: u16 = server_version
.next()
.unwrap_or_default()
.parse()
.unwrap_or(0);
let server_version_patch: u16 = server_version
.next()
.unwrap_or_default()
.parse()
.unwrap_or(0);
stream.server_version = (
server_version_major,
server_version_minor,
server_version_patch,
);
stream.capabilities &= handshake.server_capabilities;
stream.capabilities |= Capabilities::PROTOCOL_41;
@ -39,8 +70,14 @@ impl MySqlConnection {
None
};
let char_set = if stream.server_version >= (5, 5, 3) {
COLLATE_UTF8MB4_UNICODE_CI
} else {
COLLATE_UTF8_UNICODE_CI
};
stream.write_packet(HandshakeResponse {
char_set: COLLATE_UTF8MB4_UNICODE_CI,
char_set,
max_packet_size: MAX_PACKET_SIZE,
username: &options.username,
database: options.database.as_deref(),

View File

@ -22,7 +22,8 @@ mod tls;
use crate::transaction::Transaction;
pub(crate) use stream::{Busy, MySqlStream};
const COLLATE_UTF8MB4_UNICODE_CI: u8 = 224;
pub(crate) const COLLATE_UTF8_UNICODE_CI: u8 = 192;
pub(crate) const COLLATE_UTF8MB4_UNICODE_CI: u8 = 224;
const MAX_PACKET_SIZE: u32 = 1024;

View File

@ -12,6 +12,7 @@ use crate::net::{MaybeTlsStream, Socket};
pub struct MySqlStream {
stream: BufStream<MaybeTlsStream<Socket>>,
pub(crate) server_version: (u16, u16, u16),
pub(super) capabilities: Capabilities,
pub(crate) sequence_id: u8,
pub(crate) busy: Busy,
@ -55,6 +56,7 @@ impl MySqlStream {
Ok(Self {
busy: Busy::NotBusy,
capabilities,
server_version: (0, 0, 0),
sequence_id: 0,
stream: BufStream::new(MaybeTlsStream::Raw(socket)),
})

View File

@ -39,11 +39,19 @@ impl ConnectOptions for MySqlConnectOptions {
// https://mathiasbynens.be/notes/mysql-utf8mb4
conn.execute(concat!(
r#"SET sql_mode=(SELECT CONCAT(@@sql_mode, ',PIPES_AS_CONCAT,NO_ENGINE_SUBSTITUTION')),"#,
r#"time_zone='+00:00',"#,
r#"NAMES utf8mb4 COLLATE utf8mb4_unicode_ci;"#,
)).await?;
let mut options = String::new();
options.push_str(r#"SET sql_mode=(SELECT CONCAT(@@sql_mode, ',PIPES_AS_CONCAT,NO_ENGINE_SUBSTITUTION')),"#);
options.push_str(r#"time_zone='+00:00',"#);
let char_set = if conn.stream.server_version >= (5, 5, 3) {
"utf8mb4"
} else {
"utf8"
};
options.push_str(&format!(r#"NAMES {0} COLLATE {0}_unicode_ci;"#, char_set));
conn.execute(&*options).await?;
Ok(conn)
})

View File

@ -1,6 +1,7 @@
use crate::decode::Decode;
use crate::encode::{Encode, IsNull};
use crate::error::BoxDynError;
use crate::mysql::connection::{COLLATE_UTF8MB4_UNICODE_CI, COLLATE_UTF8_UNICODE_CI};
use crate::mysql::io::MySqlBufMutExt;
use crate::mysql::protocol::text::{ColumnFlags, ColumnType};
use crate::mysql::{MySql, MySqlTypeInfo, MySqlValueRef};
@ -26,7 +27,8 @@ impl Type<MySql> for str {
| ColumnType::String
| ColumnType::VarString
| ColumnType::Enum
) && ty.char_set == 224
) && (ty.char_set == COLLATE_UTF8MB4_UNICODE_CI.into()
|| ty.char_set == COLLATE_UTF8_UNICODE_CI.into())
}
}