Reduce some duplication in type parsing

This commit is contained in:
Ryan Leckey 2020-03-12 20:14:28 -07:00
parent 7ab07016da
commit 1a48cf3b2c
5 changed files with 41 additions and 61 deletions

View File

@ -110,16 +110,16 @@ impl<'c> Row<'c> {
if is_null { if is_null {
values.push(None); values.push(None);
} else { } else {
let size = match columns[column_idx] { let (offset, size) = match columns[column_idx] {
TypeId::TINY_INT => 1, TypeId::TINY_INT => (0, 1),
TypeId::SMALL_INT => 2, TypeId::SMALL_INT => (0, 2),
TypeId::INT | TypeId::FLOAT => 4, TypeId::INT | TypeId::FLOAT => (0, 4),
TypeId::BIG_INT | TypeId::DOUBLE => 8, TypeId::BIG_INT | TypeId::DOUBLE => (0, 8),
TypeId::DATE => 5, TypeId::DATE => (0, 5),
TypeId::TIME => 1 + buffer[index] as usize, TypeId::TIME => (0, 1 + buffer[index] as usize),
TypeId::TIMESTAMP | TypeId::DATETIME => 1 + buffer[index] as usize, TypeId::TIMESTAMP | TypeId::DATETIME => (0, 1 + buffer[index] as usize),
TypeId::TINY_BLOB TypeId::TINY_BLOB
| TypeId::MEDIUM_BLOB | TypeId::MEDIUM_BLOB
@ -129,7 +129,7 @@ impl<'c> Row<'c> {
| TypeId::VAR_CHAR => { | TypeId::VAR_CHAR => {
let (len_size, len) = get_lenenc(&buffer[index..]); let (len_size, len) = get_lenenc(&buffer[index..]);
len_size + len.unwrap_or_default() (len_size, len.unwrap_or_default())
} }
id => { id => {
@ -137,8 +137,8 @@ impl<'c> Row<'c> {
} }
}; };
values.push(Some(index..(index + size))); values.push(Some((index + offset)..(index + offset + size)));
index += size; index += size + offset;
} }
} }

View File

@ -2,7 +2,7 @@ use byteorder::LittleEndian;
use crate::decode::Decode; use crate::decode::Decode;
use crate::encode::Encode; use crate::encode::Encode;
use crate::mysql::io::{BufExt, BufMutExt}; use crate::mysql::io::{BufMutExt};
use crate::mysql::protocol::TypeId; use crate::mysql::protocol::TypeId;
use crate::mysql::types::MySqlTypeInfo; use crate::mysql::types::MySqlTypeInfo;
use crate::mysql::{MySql, MySqlValue}; use crate::mysql::{MySql, MySqlValue};
@ -41,16 +41,7 @@ impl Encode<MySql> for Vec<u8> {
impl<'de> Decode<'de, MySql> for Vec<u8> { impl<'de> Decode<'de, MySql> for Vec<u8> {
fn decode(value: Option<MySqlValue<'de>>) -> crate::Result<Self> { fn decode(value: Option<MySqlValue<'de>>) -> crate::Result<Self> {
match value.try_into()? { match value.try_into()? {
MySqlValue::Binary(mut buf) => { MySqlValue::Binary(buf) | MySqlValue::Text(buf) => Ok(buf.to_vec()),
let len = buf
.get_uint_lenenc::<LittleEndian>()
.map_err(crate::Error::decode)?
.unwrap_or_default();
Ok((&buf[..(len as usize)]).to_vec())
}
MySqlValue::Text(s) => Ok(s.to_vec()),
} }
} }
} }
@ -58,16 +49,7 @@ impl<'de> Decode<'de, MySql> for Vec<u8> {
impl<'de> Decode<'de, MySql> for &'de [u8] { impl<'de> Decode<'de, MySql> for &'de [u8] {
fn decode(value: Option<MySqlValue<'de>>) -> crate::Result<Self> { fn decode(value: Option<MySqlValue<'de>>) -> crate::Result<Self> {
match value.try_into()? { match value.try_into()? {
MySqlValue::Binary(mut buf) => { MySqlValue::Binary(buf) | MySqlValue::Text(buf) => Ok(buf),
let len = buf
.get_uint_lenenc::<LittleEndian>()
.map_err(crate::Error::decode)?
.unwrap_or_default();
Ok(&buf[..(len as usize)])
}
MySqlValue::Text(s) => Ok(s),
} }
} }
} }

View File

@ -4,7 +4,7 @@ use byteorder::LittleEndian;
use crate::decode::Decode; use crate::decode::Decode;
use crate::encode::Encode; use crate::encode::Encode;
use crate::mysql::io::{BufExt, BufMutExt}; use crate::mysql::io::{BufMutExt};
use crate::mysql::protocol::TypeId; use crate::mysql::protocol::TypeId;
use crate::mysql::types::MySqlTypeInfo; use crate::mysql::types::MySqlTypeInfo;
use crate::mysql::{MySql, MySqlValue}; use crate::mysql::{MySql, MySqlValue};
@ -44,16 +44,9 @@ impl Encode<MySql> for String {
impl<'de> Decode<'de, MySql> for &'de str { impl<'de> Decode<'de, MySql> for &'de str {
fn decode(value: Option<MySqlValue<'de>>) -> crate::Result<Self> { fn decode(value: Option<MySqlValue<'de>>) -> crate::Result<Self> {
match value.try_into()? { match value.try_into()? {
MySqlValue::Binary(mut buf) => { MySqlValue::Binary(buf) | MySqlValue::Text(buf) => {
let len = buf from_utf8(buf).map_err(crate::Error::decode)
.get_uint_lenenc::<LittleEndian>()
.map_err(crate::Error::decode)?
.unwrap_or_default();
from_utf8(&buf[..(len as usize)]).map_err(crate::Error::decode)
} }
MySqlValue::Text(s) => from_utf8(s).map_err(crate::Error::decode),
} }
} }
} }

View File

@ -25,10 +25,10 @@ pub(crate) fn expand_derive_encode(input: DeriveInput) -> syn::Result<proc_macro
Ok(quote!( Ok(quote!(
impl #impl_generics sqlx::encode::Encode<DB> for #ident #ty_generics #where_clause { impl #impl_generics sqlx::encode::Encode<DB> for #ident #ty_generics #where_clause {
fn encode(&self, buf: &mut std::vec::Vec<u8>) { fn encode(&self, buf: &mut <DB as sqlx::Database>::RawBuffer) {
sqlx::encode::Encode::encode(&self.0, buf) sqlx::encode::Encode::encode(&self.0, buf)
} }
fn encode_nullable(&self, buf: &mut std::vec::Vec<u8>) -> sqlx::encode::IsNull { fn encode_nullable(&self, buf: &mut <DB as sqlx::Database>::RawBuffer) -> sqlx::encode::IsNull {
sqlx::encode::Encode::encode_nullable(&self.0, buf) sqlx::encode::Encode::encode_nullable(&self.0, buf)
} }
fn size_hint(&self) -> usize { fn size_hint(&self) -> usize {

View File

@ -4,31 +4,36 @@ use sqlx::encode::Encode;
#[derive(PartialEq, Debug, Encode, Decode)] #[derive(PartialEq, Debug, Encode, Decode)]
struct Foo(i32); struct Foo(i32);
#[test]
#[cfg(feature = "mysql")]
fn encode_mysql() {
encode_with_db::<sqlx::MySql>();
}
#[test] #[test]
#[cfg(feature = "postgres")] #[cfg(feature = "postgres")]
fn encode_postgres() { fn encode_with_postgres()
encode_with_db::<sqlx::Postgres>();
}
#[allow(dead_code)]
fn encode_with_db<DB: sqlx::Database>()
where
Foo: Encode<DB>,
i32: Encode<DB>,
{ {
use sqlx_core::postgres::Postgres;
let example = Foo(0x1122_3344); let example = Foo(0x1122_3344);
let mut encoded = Vec::new(); let mut encoded = Vec::new();
let mut encoded_orig = Vec::new(); let mut encoded_orig = Vec::new();
Encode::<DB>::encode(&example, &mut encoded); Encode::<Postgres>::encode(&example, &mut encoded);
Encode::<DB>::encode(&example.0, &mut encoded_orig); Encode::<Postgres>::encode(&example.0, &mut encoded_orig);
assert_eq!(encoded, encoded_orig);
}
#[test]
#[cfg(feature = "mysql")]
fn encode_with_mysql()
{
use sqlx_core::mysql::MySql;
let example = Foo(0x1122_3344);
let mut encoded = Vec::new();
let mut encoded_orig = Vec::new();
Encode::<MySql>::encode(&example, &mut encoded);
Encode::<MySql>::encode(&example.0, &mut encoded_orig);
assert_eq!(encoded, encoded_orig); assert_eq!(encoded, encoded_orig);
} }