[MySQL] [Postgres] Add support for BLOB and BYTEA types

This commit is contained in:
Ryan Leckey 2019-12-30 02:01:09 -08:00
parent 27759a12c7
commit 19e38ab8d3
6 changed files with 127 additions and 0 deletions

View file

@ -0,0 +1,41 @@
use byteorder::LittleEndian;
use crate::decode::{Decode, DecodeError};
use crate::encode::Encode;
use crate::mysql::protocol::Type;
use crate::mysql::types::MySqlTypeMetadata;
use crate::mysql::io::{BufMutExt, BufExt};
use crate::mysql::MySql;
use crate::types::HasSqlType;
// TODO: We only have support for BLOB below; we map [u8] to BLOB, as we do not have the size information yet
impl HasSqlType<[u8]> for MySql {
fn metadata() -> MySqlTypeMetadata {
MySqlTypeMetadata::new(Type::BLOB)
}
}
impl HasSqlType<Vec<u8>> for MySql {
fn metadata() -> MySqlTypeMetadata {
<Self as HasSqlType<[u8]>>::metadata()
}
}
impl Encode<MySql> for [u8] {
fn encode(&self, buf: &mut Vec<u8>) {
buf.put_bytes_lenenc::<LittleEndian>(self);
}
}
impl Encode<MySql> for Vec<u8> {
fn encode(&self, buf: &mut Vec<u8>) {
<[u8] as Encode<MySql>>::encode(self, buf);
}
}
impl Decode<MySql> for Vec<u8> {
fn decode(mut buf: &[u8]) -> Result<Self, DecodeError> {
Ok(buf.get_bytes_lenenc::<LittleEndian>()?.unwrap_or_default().to_vec())
}
}

View file

@ -7,6 +7,7 @@ mod float;
mod int;
mod str;
mod uint;
mod bytes;
#[cfg(feature = "chrono")]
mod chrono;

View file

@ -0,0 +1,43 @@
use crate::decode::{Decode, DecodeError};
use crate::encode::Encode;
use crate::postgres::types::PgTypeMetadata;
use crate::postgres::Postgres;
use crate::types::HasSqlType;
impl HasSqlType<[u8]> for Postgres {
fn metadata() -> PgTypeMetadata {
PgTypeMetadata::binary(17, 1001)
}
}
impl HasSqlType<Vec<u8>> for Postgres {
fn metadata() -> Self::TypeMetadata {
<Postgres as HasSqlType<[u8]>>::metadata()
}
}
impl Encode<Postgres> for [u8] {
fn encode(&self, buf: &mut Vec<u8>) {
buf.extend_from_slice(self);
}
fn size_hint(&self) -> usize {
self.len()
}
}
impl Encode<Postgres> for Vec<u8> {
fn encode(&self, buf: &mut Vec<u8>) {
<[u8] as Encode<Postgres>>::encode(self, buf);
}
fn size_hint(&self) -> usize {
self.len()
}
}
impl Decode<Postgres> for Vec<u8> {
fn decode(buf: &[u8]) -> Result<Self, DecodeError> {
Ok(buf.to_vec())
}
}

View file

@ -1,4 +1,5 @@
mod bool;
mod bytes;
mod float;
mod int;
mod str;

View file

@ -44,3 +44,24 @@ test!(mysql_longlong_unsigned: u64: "2141512" == 2141512_u64);
test!(mysql_longlong: i64: "2141512" == 2141512_i64);
test!(mysql_string: String: "'helloworld'" == "helloworld");
#[async_std::test]
async fn mysql_bytes() -> anyhow::Result<()> {
let mut conn = connect().await?;
let value = b"Hello, World";
let row = sqlx::query("SELECT X'48656c6c6f2c20576f726c64' = ?, ?")
.bind(&value[..])
.bind(&value[..])
.fetch_one(&mut conn)
.await?;
assert!(row.get::<bool, _>(0));
let output: Vec<u8> = row.get(1);
assert_eq!(&value[..], &*output);
Ok(())
}

View file

@ -35,3 +35,23 @@ test!(postgres_real: f32: "9419.122::real" == 9419.122_f32);
test!(postgres_double: f64: "939399419.1225182::double precision" == 939399419.1225182_f64);
test!(postgres_text: String: "'this is foo'" == "this is foo", "''" == "");
#[async_std::test]
async fn postgres_bytes() -> anyhow::Result<()> {
let mut conn = connect().await?;
let value = b"Hello, World";
let row = sqlx::query("SELECT E'\\\\x48656c6c6f2c20576f726c64' = $1, $1")
.bind(&value[..])
.fetch_one(&mut conn)
.await?;
assert!(row.get::<bool, _>(0));
let output: Vec<u8> = row.get(1);
assert_eq!(&value[..], &*output);
Ok(())
}