Make nice types for parameter and result descs
This commit is contained in:
parent
06a9a7c399
commit
749aa735f6
40
src/lib.rs
40
src/lib.rs
@ -17,7 +17,7 @@ use std::rt::io::net::ip::SocketAddr;
|
||||
use std::rt::io::net::tcp::TcpStream;
|
||||
|
||||
use message::*;
|
||||
use types::{Oid, ToSql, FromSql};
|
||||
use types::{PostgresType, ToSql, FromSql};
|
||||
|
||||
mod message;
|
||||
mod types;
|
||||
@ -295,11 +295,20 @@ impl PostgresConnection {
|
||||
})
|
||||
|
||||
let param_types = match_read_message_or_fail!(self, {
|
||||
ParameterDescription { types } => types
|
||||
ParameterDescription { types } =>
|
||||
types.iter().map(|ty| { PostgresType::from_oid(*ty) })
|
||||
.collect()
|
||||
});
|
||||
|
||||
let result_desc = match_read_message_or_fail!(self, {
|
||||
RowDescription { descriptions } => descriptions,
|
||||
RowDescription { descriptions } => {
|
||||
let mut res: ~[ResultDescription] = descriptions
|
||||
.move_rev_iter().map(|desc| {
|
||||
ResultDescription::from_row_description_entry(desc)
|
||||
}).collect();
|
||||
res.reverse();
|
||||
res
|
||||
},
|
||||
NoData => ~[]
|
||||
});
|
||||
|
||||
@ -424,11 +433,28 @@ pub trait PostgresStatement {
|
||||
pub struct NormalPostgresStatement<'self> {
|
||||
priv conn: &'self PostgresConnection,
|
||||
priv name: ~str,
|
||||
priv param_types: ~[Oid],
|
||||
priv result_desc: ~[RowDescriptionEntry],
|
||||
priv param_types: ~[PostgresType],
|
||||
priv result_desc: ~[ResultDescription],
|
||||
priv next_portal_id: Cell<uint>
|
||||
}
|
||||
|
||||
pub struct ResultDescription {
|
||||
name: ~str,
|
||||
ty: PostgresType
|
||||
}
|
||||
|
||||
impl ResultDescription {
|
||||
fn from_row_description_entry(row: RowDescriptionEntry)
|
||||
-> ResultDescription {
|
||||
let RowDescriptionEntry { name, type_oid, _ } = row;
|
||||
|
||||
ResultDescription {
|
||||
name: name,
|
||||
ty: PostgresType::from_oid(type_oid)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl<'self> Drop for NormalPostgresStatement<'self> {
|
||||
fn drop(&self) {
|
||||
@ -461,7 +487,7 @@ impl<'self> NormalPostgresStatement<'self> {
|
||||
};
|
||||
|
||||
let result_formats: ~[i16] = self.result_desc.iter().map(|desc| {
|
||||
types::result_format(desc.type_oid) as i16
|
||||
desc.ty.result_format() as i16
|
||||
}).collect();
|
||||
|
||||
self.conn.write_messages([
|
||||
@ -717,7 +743,7 @@ impl<'self> Container for PostgresRow<'self> {
|
||||
impl<'self, I: RowIndex, T: FromSql> Index<I, T> for PostgresRow<'self> {
|
||||
fn index(&self, idx: &I) -> T {
|
||||
let idx = idx.idx(self.stmt);
|
||||
FromSql::from_sql(self.stmt.result_desc[idx].type_oid,
|
||||
FromSql::from_sql(self.stmt.result_desc[idx].ty,
|
||||
&self.data[idx])
|
||||
}
|
||||
}
|
||||
|
170
src/types.rs
170
src/types.rs
@ -25,25 +25,63 @@ static BPCHAROID: Oid = 1042;
|
||||
static VARCHAROID: Oid = 1043;
|
||||
static UUIDOID: Oid = 2950;
|
||||
|
||||
pub enum PostgresType {
|
||||
PgBool,
|
||||
PgByteA,
|
||||
PgChar,
|
||||
PgInt8,
|
||||
PgInt2,
|
||||
PgInt4,
|
||||
PgText,
|
||||
PgJson,
|
||||
PgFloat4,
|
||||
PgFloat8,
|
||||
PgCharN,
|
||||
PgVarchar,
|
||||
PgUuid,
|
||||
PgUnknownType(Oid)
|
||||
}
|
||||
|
||||
impl PostgresType {
|
||||
pub fn from_oid(oid: Oid) -> PostgresType {
|
||||
match oid {
|
||||
BOOLOID => PgBool,
|
||||
BYTEAOID => PgByteA,
|
||||
CHAROID => PgChar,
|
||||
INT8OID => PgInt8,
|
||||
INT2OID => PgInt2,
|
||||
INT4OID => PgInt4,
|
||||
TEXTOID => PgText,
|
||||
JSONOID => PgJson,
|
||||
FLOAT4OID => PgFloat4,
|
||||
FLOAT8OID => PgFloat8,
|
||||
BPCHAROID => PgCharN,
|
||||
VARCHAROID => PgVarchar,
|
||||
UUIDOID => PgUuid,
|
||||
oid => PgUnknownType(oid)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn result_format(&self) -> Format {
|
||||
match *self {
|
||||
PgBool
|
||||
| PgByteA
|
||||
| PgInt8
|
||||
| PgInt2
|
||||
| PgInt4
|
||||
| PgFloat4
|
||||
| PgFloat8
|
||||
| PgUuid => Binary,
|
||||
_ => Text
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Format {
|
||||
Text = 0,
|
||||
Binary = 1
|
||||
}
|
||||
|
||||
pub fn result_format(ty: Oid) -> Format {
|
||||
match ty {
|
||||
BOOLOID |
|
||||
BYTEAOID |
|
||||
INT8OID |
|
||||
INT2OID |
|
||||
INT4OID |
|
||||
FLOAT4OID |
|
||||
FLOAT8OID |
|
||||
UUIDOID => Binary,
|
||||
_ => Text
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! check_oid(
|
||||
($($expected:ident)|+, $actual:ident) => (
|
||||
match $actual {
|
||||
@ -54,13 +92,13 @@ macro_rules! check_oid(
|
||||
)
|
||||
|
||||
pub trait FromSql {
|
||||
fn from_sql(ty: Oid, raw: &Option<~[u8]>) -> Self;
|
||||
fn from_sql(ty: PostgresType, raw: &Option<~[u8]>) -> Self;
|
||||
}
|
||||
|
||||
macro_rules! from_map_impl(
|
||||
($($oid:ident)|+, $t:ty, $blk:expr) => (
|
||||
impl FromSql for Option<$t> {
|
||||
fn from_sql(ty: Oid, raw: &Option<~[u8]>) -> Option<$t> {
|
||||
fn from_sql(ty: PostgresType, raw: &Option<~[u8]>) -> Option<$t> {
|
||||
check_oid!($($oid)|+, ty)
|
||||
raw.map($blk)
|
||||
}
|
||||
@ -80,7 +118,7 @@ macro_rules! from_conversions_impl(
|
||||
macro_rules! from_option_impl(
|
||||
($t:ty) => (
|
||||
impl FromSql for $t {
|
||||
fn from_sql(ty: Oid, raw: &Option<~[u8]>) -> $t {
|
||||
fn from_sql(ty: PostgresType, raw: &Option<~[u8]>) -> $t {
|
||||
// FIXME when you can specify Self types properly
|
||||
let ret: Option<$t> = FromSql::from_sql(ty, raw);
|
||||
ret.unwrap()
|
||||
@ -89,53 +127,53 @@ macro_rules! from_option_impl(
|
||||
)
|
||||
)
|
||||
|
||||
from_map_impl!(BOOLOID, bool, |buf| { buf[0] != 0 })
|
||||
from_map_impl!(PgBool, bool, |buf| { buf[0] != 0 })
|
||||
from_option_impl!(bool)
|
||||
|
||||
from_conversions_impl!(CHAROID, i8, read_i8_)
|
||||
from_conversions_impl!(PgChar, i8, read_i8_)
|
||||
from_option_impl!(i8)
|
||||
from_conversions_impl!(INT2OID, i16, read_be_i16_)
|
||||
from_conversions_impl!(PgInt2, i16, read_be_i16_)
|
||||
from_option_impl!(i16)
|
||||
from_conversions_impl!(INT4OID, i32, read_be_i32_)
|
||||
from_conversions_impl!(PgInt4, i32, read_be_i32_)
|
||||
from_option_impl!(i32)
|
||||
from_conversions_impl!(INT8OID, i64, read_be_i64_)
|
||||
from_conversions_impl!(PgInt8, i64, read_be_i64_)
|
||||
from_option_impl!(i64)
|
||||
from_conversions_impl!(FLOAT4OID, f32, read_be_f32_)
|
||||
from_conversions_impl!(PgFloat4, f32, read_be_f32_)
|
||||
from_option_impl!(f32)
|
||||
from_conversions_impl!(FLOAT8OID, f64, read_be_f64_)
|
||||
from_conversions_impl!(PgFloat8, f64, read_be_f64_)
|
||||
from_option_impl!(f64)
|
||||
|
||||
from_map_impl!(VARCHAROID | TEXTOID | BPCHAROID, ~str, |buf| {
|
||||
from_map_impl!(PgVarchar | PgText | PgCharN, ~str, |buf| {
|
||||
str::from_bytes(buf.as_slice())
|
||||
})
|
||||
from_option_impl!(~str)
|
||||
|
||||
impl FromSql for Option<~[u8]> {
|
||||
fn from_sql(ty: Oid, raw: &Option<~[u8]>) -> Option<~[u8]> {
|
||||
check_oid!(BYTEAOID, ty)
|
||||
fn from_sql(ty: PostgresType, raw: &Option<~[u8]>) -> Option<~[u8]> {
|
||||
check_oid!(PgByteA, ty)
|
||||
raw.clone()
|
||||
}
|
||||
}
|
||||
from_option_impl!(~[u8])
|
||||
|
||||
from_map_impl!(JSONOID, Json, |buf| {
|
||||
from_map_impl!(PgJson, Json, |buf| {
|
||||
json::from_str(str::from_bytes_slice(buf.as_slice())).unwrap()
|
||||
})
|
||||
from_option_impl!(Json)
|
||||
|
||||
from_map_impl!(UUIDOID, Uuid, |buf| {
|
||||
from_map_impl!(PgUuid, Uuid, |buf| {
|
||||
Uuid::from_bytes(buf.as_slice()).unwrap()
|
||||
})
|
||||
from_option_impl!(Uuid)
|
||||
|
||||
pub trait ToSql {
|
||||
fn to_sql(&self, ty: Oid) -> (Format, Option<~[u8]>);
|
||||
fn to_sql(&self, ty: PostgresType) -> (Format, Option<~[u8]>);
|
||||
}
|
||||
|
||||
macro_rules! to_option_impl(
|
||||
($($oid:ident)|+, $t:ty) => (
|
||||
impl ToSql for Option<$t> {
|
||||
fn to_sql(&self, ty: Oid) -> (Format, Option<~[u8]>) {
|
||||
fn to_sql(&self, ty: PostgresType) -> (Format, Option<~[u8]>) {
|
||||
check_oid!($($oid)|+, ty)
|
||||
|
||||
match *self {
|
||||
@ -147,7 +185,7 @@ macro_rules! to_option_impl(
|
||||
);
|
||||
(self, $($oid:ident)|+, $t:ty) => (
|
||||
impl<'self> ToSql for Option<$t> {
|
||||
fn to_sql(&self, ty: Oid) -> (Format, Option<~[u8]>) {
|
||||
fn to_sql(&self, ty: PostgresType) -> (Format, Option<~[u8]>) {
|
||||
check_oid!($($oid)|+, ty)
|
||||
|
||||
match *self {
|
||||
@ -162,7 +200,7 @@ macro_rules! to_option_impl(
|
||||
macro_rules! to_conversions_impl(
|
||||
($($oid:ident)|+, $t:ty, $f:ident) => (
|
||||
impl ToSql for $t {
|
||||
fn to_sql(&self, ty: Oid) -> (Format, Option<~[u8]>) {
|
||||
fn to_sql(&self, ty: PostgresType) -> (Format, Option<~[u8]>) {
|
||||
check_oid!($($oid)|+, ty)
|
||||
|
||||
let mut writer = MemWriter::new();
|
||||
@ -174,74 +212,74 @@ macro_rules! to_conversions_impl(
|
||||
)
|
||||
|
||||
impl ToSql for bool {
|
||||
fn to_sql(&self, ty: Oid) -> (Format, Option<~[u8]>) {
|
||||
check_oid!(BOOLOID, ty)
|
||||
fn to_sql(&self, ty: PostgresType) -> (Format, Option<~[u8]>) {
|
||||
check_oid!(PgBool, ty)
|
||||
(Binary, Some(~[*self as u8]))
|
||||
}
|
||||
}
|
||||
to_option_impl!(BOOLOID, bool)
|
||||
to_option_impl!(PgBool, bool)
|
||||
|
||||
to_conversions_impl!(CHAROID, i8, write_i8_)
|
||||
to_option_impl!(CHAROID, i8)
|
||||
to_conversions_impl!(INT2OID, i16, write_be_i16_)
|
||||
to_option_impl!(INT2OID, i16)
|
||||
to_conversions_impl!(INT4OID, i32, write_be_i32_)
|
||||
to_option_impl!(INT4OID, i32)
|
||||
to_conversions_impl!(INT8OID, i64, write_be_i64_)
|
||||
to_option_impl!(INT8OID, i64)
|
||||
to_conversions_impl!(FLOAT4OID, f32, write_be_f32_)
|
||||
to_option_impl!(FLOAT4OID, f32)
|
||||
to_conversions_impl!(FLOAT8OID, f64, write_be_f64_)
|
||||
to_option_impl!(FLOAT8OID, f64)
|
||||
to_conversions_impl!(PgChar, i8, write_i8_)
|
||||
to_option_impl!(PgChar, i8)
|
||||
to_conversions_impl!(PgInt2, i16, write_be_i16_)
|
||||
to_option_impl!(PgInt2, i16)
|
||||
to_conversions_impl!(PgInt4, i32, write_be_i32_)
|
||||
to_option_impl!(PgInt4, i32)
|
||||
to_conversions_impl!(PgInt8, i64, write_be_i64_)
|
||||
to_option_impl!(PgInt8, i64)
|
||||
to_conversions_impl!(PgFloat4, f32, write_be_f32_)
|
||||
to_option_impl!(PgFloat4, f32)
|
||||
to_conversions_impl!(PgFloat8, f64, write_be_f64_)
|
||||
to_option_impl!(PgFloat8, f64)
|
||||
|
||||
impl ToSql for ~str {
|
||||
fn to_sql(&self, ty: Oid) -> (Format, Option<~[u8]>) {
|
||||
check_oid!(VARCHAROID | TEXTOID | BPCHAROID, ty)
|
||||
fn to_sql(&self, ty: PostgresType) -> (Format, Option<~[u8]>) {
|
||||
check_oid!(PgVarchar | PgText | PgCharN, ty)
|
||||
(Text, Some(self.as_bytes().to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'self> ToSql for &'self str {
|
||||
fn to_sql(&self, ty: Oid) -> (Format, Option<~[u8]>) {
|
||||
check_oid!(VARCHAROID | TEXTOID | BPCHAROID, ty)
|
||||
fn to_sql(&self, ty: PostgresType) -> (Format, Option<~[u8]>) {
|
||||
check_oid!(PgVarchar | PgText | PgCharN, ty)
|
||||
(Text, Some(self.as_bytes().to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
to_option_impl!(VARCHAROID | TEXTOID | BPCHAROID, ~str)
|
||||
to_option_impl!(self, VARCHAROID | TEXTOID | BPCHAROID, &'self str)
|
||||
to_option_impl!(PgVarchar | PgText | PgCharN, ~str)
|
||||
to_option_impl!(self, PgVarchar | PgText | PgCharN, &'self str)
|
||||
|
||||
impl ToSql for ~[u8] {
|
||||
fn to_sql(&self, ty: Oid) -> (Format, Option<~[u8]>) {
|
||||
check_oid!(BYTEAOID, ty)
|
||||
fn to_sql(&self, ty: PostgresType) -> (Format, Option<~[u8]>) {
|
||||
check_oid!(PgByteA, ty)
|
||||
(Binary, Some(self.to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'self> ToSql for &'self [u8] {
|
||||
fn to_sql(&self, ty: Oid) -> (Format, Option<~[u8]>) {
|
||||
check_oid!(BYTEAOID, ty)
|
||||
fn to_sql(&self, ty: PostgresType) -> (Format, Option<~[u8]>) {
|
||||
check_oid!(PgByteA, ty)
|
||||
(Binary, Some(self.to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
to_option_impl!(BYTEAOID, ~[u8])
|
||||
to_option_impl!(self, BYTEAOID, &'self [u8])
|
||||
to_option_impl!(PgByteA, ~[u8])
|
||||
to_option_impl!(self, PgByteA, &'self [u8])
|
||||
|
||||
impl ToSql for Json {
|
||||
fn to_sql(&self, ty: Oid) -> (Format, Option<~[u8]>) {
|
||||
check_oid!(JSONOID, ty)
|
||||
fn to_sql(&self, ty: PostgresType) -> (Format, Option<~[u8]>) {
|
||||
check_oid!(PgJson, ty)
|
||||
(Text, Some(self.to_str().into_bytes()))
|
||||
}
|
||||
}
|
||||
|
||||
to_option_impl!(JSONOID, Json)
|
||||
to_option_impl!(PgJson, Json)
|
||||
|
||||
impl ToSql for Uuid {
|
||||
fn to_sql(&self, ty: Oid) -> (Format, Option<~[u8]>) {
|
||||
check_oid!(UUIDOID, ty)
|
||||
fn to_sql(&self, ty: PostgresType) -> (Format, Option<~[u8]>) {
|
||||
check_oid!(PgUuid, ty)
|
||||
(Binary, Some(self.to_bytes().to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
to_option_impl!(UUIDOID, Uuid)
|
||||
to_option_impl!(PgUuid, Uuid)
|
||||
|
Loading…
Reference in New Issue
Block a user