2013-10-20 21:34:50 +00:00
|
|
|
//! Traits dealing with Postgres data types
|
2015-02-13 06:52:55 +00:00
|
|
|
pub use self::slice::Slice;
|
|
|
|
|
2014-06-06 03:50:23 +00:00
|
|
|
use std::collections::HashMap;
|
2015-01-09 18:50:54 +00:00
|
|
|
use std::fmt;
|
2015-02-26 17:02:32 +00:00
|
|
|
use std::io::prelude::*;
|
|
|
|
use byteorder::{ReadBytesExt, WriteBytesExt, BigEndian};
|
2013-08-28 04:36:27 +00:00
|
|
|
|
2014-11-01 23:12:05 +00:00
|
|
|
use Result;
|
2014-11-21 05:47:13 +00:00
|
|
|
use error::Error;
|
2015-04-08 06:57:22 +00:00
|
|
|
use util;
|
2013-10-29 06:55:11 +00:00
|
|
|
|
2015-02-19 05:04:44 +00:00
|
|
|
pub use ugh_privacy::Other;
|
2015-02-06 07:23:20 +00:00
|
|
|
|
2015-03-04 04:44:47 +00:00
|
|
|
/// Generates a simple implementation of `ToSql::accepts` which accepts the
|
|
|
|
/// types passed to it.
|
2015-02-15 23:11:15 +00:00
|
|
|
#[macro_export]
|
2015-02-15 01:07:10 +00:00
|
|
|
macro_rules! accepts {
|
|
|
|
($($expected:pat),+) => (
|
2015-02-28 04:46:43 +00:00
|
|
|
fn accepts(ty: &$crate::types::Type) -> bool {
|
2015-02-15 01:07:10 +00:00
|
|
|
match *ty {
|
|
|
|
$($expected)|+ => true,
|
|
|
|
_ => false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2015-03-04 04:44:47 +00:00
|
|
|
/// Generates an implementation of `ToSql::to_sql_checked`.
|
|
|
|
///
|
|
|
|
/// All `ToSql` implementations should use this macro.
|
2015-02-15 23:11:15 +00:00
|
|
|
#[macro_export]
|
|
|
|
macro_rules! to_sql_checked {
|
|
|
|
() => {
|
2015-02-28 04:46:43 +00:00
|
|
|
fn to_sql_checked(&self, ty: &$crate::types::Type, out: &mut ::std::io::Write)
|
|
|
|
-> $crate::Result<$crate::types::IsNull> {
|
|
|
|
if !<Self as $crate::types::ToSql>::accepts(ty) {
|
2015-02-15 23:11:15 +00:00
|
|
|
return Err($crate::Error::WrongType(ty.clone()));
|
2014-11-17 17:43:10 +00:00
|
|
|
}
|
2015-02-15 23:11:15 +00:00
|
|
|
self.to_sql(ty, out)
|
2014-11-17 17:43:10 +00:00
|
|
|
}
|
2014-12-15 00:43:17 +00:00
|
|
|
}
|
2014-12-19 18:43:42 +00:00
|
|
|
}
|
2014-12-15 00:43:17 +00:00
|
|
|
|
2014-11-17 17:43:10 +00:00
|
|
|
#[cfg(feature = "uuid")]
|
|
|
|
mod uuid;
|
2015-02-08 03:52:45 +00:00
|
|
|
#[cfg(feature = "time")]
|
2014-11-18 03:11:32 +00:00
|
|
|
mod time;
|
2015-02-13 06:52:55 +00:00
|
|
|
mod slice;
|
2015-02-08 03:20:18 +00:00
|
|
|
#[cfg(feature = "rustc-serialize")]
|
|
|
|
mod json;
|
2013-10-29 05:35:52 +00:00
|
|
|
|
2013-09-30 02:47:30 +00:00
|
|
|
/// A Postgres OID
|
2014-01-03 07:10:26 +00:00
|
|
|
pub type Oid = u32;
|
2013-08-30 05:58:26 +00:00
|
|
|
|
2015-02-14 20:46:18 +00:00
|
|
|
/// Represents the kind of a Postgres type.
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
|
|
pub enum Kind {
|
|
|
|
/// A simple type like `VARCHAR` or `INTEGER`.
|
|
|
|
Simple,
|
|
|
|
/// An array type along with the type of its elements.
|
|
|
|
Array(Type),
|
|
|
|
/// A range type along with the type of its elements.
|
|
|
|
Range(Type),
|
|
|
|
}
|
|
|
|
|
2015-02-19 05:04:44 +00:00
|
|
|
macro_rules! as_pat {
|
|
|
|
($p:pat) => ($p)
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! as_expr {
|
|
|
|
($e:expr) => ($e)
|
|
|
|
}
|
|
|
|
|
2014-12-19 18:43:42 +00:00
|
|
|
macro_rules! make_postgres_type {
|
2015-02-19 05:04:44 +00:00
|
|
|
($(#[$doc:meta] $oid:tt => $variant:ident: $kind:expr),+) => (
|
2013-12-08 03:34:48 +00:00
|
|
|
/// A Postgres type
|
2015-01-10 21:58:46 +00:00
|
|
|
#[derive(PartialEq, Eq, Clone)]
|
2014-11-04 05:29:16 +00:00
|
|
|
pub enum Type {
|
2013-12-08 03:34:48 +00:00
|
|
|
$(
|
2014-03-29 21:33:11 +00:00
|
|
|
#[$doc]
|
2013-12-08 03:34:48 +00:00
|
|
|
$variant,
|
|
|
|
)+
|
|
|
|
/// An unknown type
|
2015-02-19 05:04:44 +00:00
|
|
|
Other(Box<Other>),
|
2013-09-05 04:26:43 +00:00
|
|
|
}
|
|
|
|
|
2015-01-23 18:44:15 +00:00
|
|
|
impl fmt::Debug for Type {
|
2015-01-10 21:58:46 +00:00
|
|
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
let s = match *self {
|
|
|
|
$(Type::$variant => stringify!($variant),)+
|
2015-02-19 05:04:44 +00:00
|
|
|
Type::Other(ref u) => return fmt::Debug::fmt(u, fmt),
|
2015-01-10 21:58:46 +00:00
|
|
|
};
|
|
|
|
fmt.write_str(s)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-04 05:29:16 +00:00
|
|
|
impl Type {
|
2014-12-25 04:58:27 +00:00
|
|
|
/// Creates a `Type` from an OID.
|
|
|
|
///
|
2015-01-22 06:11:43 +00:00
|
|
|
/// If the OID is unknown, `None` is returned.
|
|
|
|
pub fn from_oid(oid: Oid) -> Option<Type> {
|
2013-12-08 03:34:48 +00:00
|
|
|
match oid {
|
2015-02-19 05:04:44 +00:00
|
|
|
$(as_pat!($oid) => Some(Type::$variant),)+
|
2015-01-22 06:11:43 +00:00
|
|
|
_ => None
|
2013-12-08 03:34:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-25 04:58:27 +00:00
|
|
|
/// Returns the OID of the `Type`.
|
2015-04-08 06:57:22 +00:00
|
|
|
///
|
|
|
|
/// # Deprecated
|
|
|
|
///
|
|
|
|
/// Use `oid` instead.
|
2013-12-08 19:44:37 +00:00
|
|
|
pub fn to_oid(&self) -> Oid {
|
2015-04-08 06:57:22 +00:00
|
|
|
self.oid()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the OID of the `Type`.
|
|
|
|
pub fn oid(&self) -> Oid {
|
2013-12-08 19:44:37 +00:00
|
|
|
match *self {
|
2015-02-19 05:04:44 +00:00
|
|
|
$(Type::$variant => as_expr!($oid),)+
|
|
|
|
Type::Other(ref u) => u.oid(),
|
2013-12-08 19:44:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-14 20:46:18 +00:00
|
|
|
/// The kind of this type
|
2015-02-18 07:49:11 +00:00
|
|
|
pub fn kind(&self) -> &Kind {
|
2013-12-08 19:44:37 +00:00
|
|
|
match *self {
|
|
|
|
$(
|
2015-02-18 07:49:11 +00:00
|
|
|
Type::$variant => {
|
|
|
|
const V: &'static Kind = &$kind;
|
|
|
|
V
|
|
|
|
}
|
2013-12-08 19:44:37 +00:00
|
|
|
)+
|
2015-02-19 05:04:44 +00:00
|
|
|
Type::Other(ref u) => u.kind(),
|
2013-12-08 19:44:37 +00:00
|
|
|
}
|
|
|
|
}
|
2013-09-05 04:26:43 +00:00
|
|
|
}
|
2013-12-08 03:34:48 +00:00
|
|
|
)
|
2014-12-19 18:43:42 +00:00
|
|
|
}
|
2013-12-08 03:34:48 +00:00
|
|
|
|
2015-02-19 05:04:44 +00:00
|
|
|
// Values from pg_type.h
|
2014-12-19 18:43:42 +00:00
|
|
|
make_postgres_type! {
|
2015-02-19 05:04:44 +00:00
|
|
|
#[doc="BOOL - boolean, 'true'/'false'"]
|
|
|
|
16 => Bool: Kind::Simple,
|
|
|
|
#[doc="BYTEA - variable-length string, binary values escaped"]
|
2015-02-19 07:30:06 +00:00
|
|
|
17 => Bytea: Kind::Simple,
|
2015-02-19 05:04:44 +00:00
|
|
|
#[doc="\"char\" - single character"]
|
|
|
|
18 => Char: Kind::Simple,
|
|
|
|
#[doc="NAME - 63-byte type for storing system identifiers"]
|
|
|
|
19 => Name: Kind::Simple,
|
|
|
|
#[doc="INT8/BIGINT - ~18 digit integer, 8-byte storage"]
|
|
|
|
20 => Int8: Kind::Simple,
|
|
|
|
#[doc="INT2/SMALLINT - -32 thousand to 32 thousand, 2-byte storage"]
|
|
|
|
21 => Int2: Kind::Simple,
|
|
|
|
#[doc="INT2VECTOR - array of int2, used in system tables"]
|
|
|
|
22 => Int2Vector: Kind::Array(Type::Int2),
|
|
|
|
#[doc="INT4/INT - -2 billion to 2 billion integer, 4-byte storage"]
|
|
|
|
23 => Int4: Kind::Simple,
|
|
|
|
#[doc="REGPROC - registered procedure"]
|
|
|
|
24 => Regproc: Kind::Simple,
|
|
|
|
#[doc="TEXT - variable-length string, no limit specified"]
|
|
|
|
25 => Text: Kind::Simple,
|
|
|
|
#[doc="OID - object identifier(oid), maximum 4 billion"]
|
|
|
|
26 => Oid: Kind::Simple,
|
|
|
|
#[doc="TID - (block, offset), physical location of tuple"]
|
|
|
|
27 => Tid: Kind::Simple,
|
|
|
|
#[doc="XID - transaction id"]
|
|
|
|
28 => Xid: Kind::Simple,
|
|
|
|
#[doc="CID - command identifier type, sequence in transaction id"]
|
|
|
|
29 => Cid: Kind::Simple,
|
|
|
|
#[doc="OIDVECTOR - array of oids, used in system tables"]
|
|
|
|
30 => OidVector: Kind::Array(Type::Oid),
|
|
|
|
#[doc="PG_TYPE"]
|
|
|
|
71 => PgType: Kind::Simple,
|
|
|
|
#[doc="PG_ATTRIBUTE"]
|
|
|
|
75 => PgAttribute: Kind::Simple,
|
|
|
|
#[doc="PG_PROC"]
|
|
|
|
81 => PgProc: Kind::Simple,
|
|
|
|
#[doc="PG_CLASS"]
|
|
|
|
83 => PgClass: Kind::Simple,
|
2013-12-08 03:34:48 +00:00
|
|
|
#[doc="JSON"]
|
2015-02-19 05:04:44 +00:00
|
|
|
114 => Json: Kind::Simple,
|
|
|
|
#[doc="XML - XML content"]
|
|
|
|
142 => Xml: Kind::Simple,
|
|
|
|
#[doc="XML[]"]
|
|
|
|
143 => XmlArray: Kind::Array(Type::Xml),
|
|
|
|
#[doc="PG_NODE_TREE - string representing an internal node tree"]
|
|
|
|
194 => PgNodeTree: Kind::Simple,
|
2013-12-09 00:00:33 +00:00
|
|
|
#[doc="JSON[]"]
|
2015-02-19 05:04:44 +00:00
|
|
|
199 => JsonArray: Kind::Array(Type::Json),
|
|
|
|
#[doc="SMGR - storage manager"]
|
|
|
|
210 => Smgr: Kind::Simple,
|
|
|
|
#[doc="POINT - geometric point '(x, y)'"]
|
|
|
|
600 => Point: Kind::Simple,
|
|
|
|
#[doc="LSEG - geometric line segment '(pt1,pt2)'"]
|
|
|
|
601 => Lseg: Kind::Simple,
|
|
|
|
#[doc="PATH - geometric path '(pt1,...)'"]
|
|
|
|
602 => Path: Kind::Simple,
|
|
|
|
#[doc="BOX - geometric box '(lower left,upper right)'"]
|
|
|
|
603 => Box: Kind::Simple,
|
|
|
|
#[doc="POLYGON - geometric polygon '(pt1,...)'"]
|
|
|
|
604 => Polygon: Kind::Simple,
|
|
|
|
#[doc="LINE - geometric line"]
|
|
|
|
628 => Line: Kind::Simple,
|
|
|
|
#[doc="LINE[]"]
|
|
|
|
629 => LineArray: Kind::Array(Type::Line),
|
|
|
|
#[doc="CIDR - network IP address/netmask, network address"]
|
|
|
|
650 => Cidr: Kind::Simple,
|
|
|
|
#[doc="CIDR[]"]
|
|
|
|
651 => CidrArray: Kind::Array(Type::Cidr),
|
|
|
|
#[doc="FLOAT4/REAL - single-precision floating point number, 4-byte storage"]
|
|
|
|
700 => Float4: Kind::Simple,
|
|
|
|
#[doc="FLOAT8/DOUBLE PRECISION - double-precision floating point number, 8-byte storage"]
|
|
|
|
701 => Float8: Kind::Simple,
|
|
|
|
#[doc="ABSTIME - absolute, limited-range date and time (Unix system time)"]
|
|
|
|
702 => Abstime: Kind::Simple,
|
|
|
|
#[doc="RELTIME - relative, limited-range date and time (Unix delta time)"]
|
|
|
|
703 => Reltime: Kind::Simple,
|
|
|
|
#[doc="TINTERVAL - (abstime,abstime), time interval"]
|
|
|
|
704 => Tinterval: Kind::Simple,
|
|
|
|
#[doc="UNKNOWN"]
|
|
|
|
705 => Unknown: Kind::Simple,
|
|
|
|
#[doc="CIRCLE - geometric circle '(center,radius)'"]
|
|
|
|
718 => Circle: Kind::Simple,
|
|
|
|
#[doc="CIRCLE[]"]
|
|
|
|
719 => CircleArray: Kind::Array(Type::Circle),
|
|
|
|
#[doc="MONEY - monetary amounts, $d,ddd.cc"]
|
|
|
|
790 => Money: Kind::Simple,
|
|
|
|
#[doc="MONEY[]"]
|
|
|
|
791 => MoneyArray: Kind::Array(Type::Money),
|
|
|
|
#[doc="MACADDR - XX:XX:XX:XX:XX:XX, MAC address"]
|
|
|
|
829 => Macaddr: Kind::Simple,
|
|
|
|
#[doc="INET - IP address/netmask, host address, netmask optional"]
|
|
|
|
869 => Inet: Kind::Simple,
|
2013-12-08 03:34:48 +00:00
|
|
|
#[doc="BOOL[]"]
|
2015-02-19 05:04:44 +00:00
|
|
|
1000 => BoolArray: Kind::Array(Type::Bool),
|
2013-12-08 03:34:48 +00:00
|
|
|
#[doc="BYTEA[]"]
|
2015-02-19 07:30:06 +00:00
|
|
|
1001 => ByteaArray: Kind::Array(Type::Bytea),
|
2013-12-08 03:34:48 +00:00
|
|
|
#[doc="\"char\"[]"]
|
2015-02-19 05:04:44 +00:00
|
|
|
1002 => CharArray: Kind::Array(Type::Char),
|
2014-05-02 23:38:06 +00:00
|
|
|
#[doc="NAME[]"]
|
2015-02-19 05:04:44 +00:00
|
|
|
1003 => NameArray: Kind::Array(Type::Name),
|
2013-12-08 03:34:48 +00:00
|
|
|
#[doc="INT2[]"]
|
2015-02-19 05:04:44 +00:00
|
|
|
1005 => Int2Array: Kind::Array(Type::Int2),
|
|
|
|
#[doc="INT2VECTOR[]"]
|
|
|
|
1006 => Int2VectorArray: Kind::Array(Type::Int2Vector),
|
2013-12-08 03:34:48 +00:00
|
|
|
#[doc="INT4[]"]
|
2015-02-19 05:04:44 +00:00
|
|
|
1007 => Int4Array: Kind::Array(Type::Int4),
|
|
|
|
#[doc="REGPROC[]"]
|
|
|
|
1008 => RegprocArray: Kind::Array(Type::Regproc),
|
2013-12-08 03:34:48 +00:00
|
|
|
#[doc="TEXT[]"]
|
2015-02-19 05:04:44 +00:00
|
|
|
1009 => TextArray: Kind::Array(Type::Text),
|
|
|
|
#[doc="TID[]"]
|
|
|
|
1010 => TidArray: Kind::Array(Type::Tid),
|
|
|
|
#[doc="XID[]"]
|
|
|
|
1011 => XidArray: Kind::Array(Type::Xid),
|
|
|
|
#[doc="CID[]"]
|
|
|
|
1012 => CidArray: Kind::Array(Type::Cid),
|
|
|
|
#[doc="OIDVECTOR[]"]
|
|
|
|
1013 => OidVectorArray: Kind::Array(Type::OidVector),
|
|
|
|
#[doc="BPCHAR[]"]
|
|
|
|
1014 => BpcharArray: Kind::Array(Type::Bpchar),
|
2013-12-08 21:58:41 +00:00
|
|
|
#[doc="VARCHAR[]"]
|
2015-02-19 05:04:44 +00:00
|
|
|
1015 => VarcharArray: Kind::Array(Type::Varchar),
|
2013-12-08 03:34:48 +00:00
|
|
|
#[doc="INT8[]"]
|
2015-02-19 05:04:44 +00:00
|
|
|
1016 => Int8Array: Kind::Array(Type::Int8),
|
|
|
|
#[doc="POINT[]"]
|
|
|
|
1017 => PointArray: Kind::Array(Type::Point),
|
|
|
|
#[doc="LSEG[]"]
|
|
|
|
1018 => LsegArray: Kind::Array(Type::Lseg),
|
|
|
|
#[doc="PATH[]"]
|
|
|
|
1019 => PathArray: Kind::Array(Type::Path),
|
|
|
|
#[doc="BOX[]"]
|
|
|
|
1020 => BoxArray: Kind::Array(Type::Box),
|
2013-12-08 03:34:48 +00:00
|
|
|
#[doc="FLOAT4[]"]
|
2015-02-19 05:04:44 +00:00
|
|
|
1021 => Float4Array: Kind::Array(Type::Float4),
|
2013-12-08 03:34:48 +00:00
|
|
|
#[doc="FLOAT8[]"]
|
2015-02-19 05:04:44 +00:00
|
|
|
1022 => Float8Array: Kind::Array(Type::Float8),
|
|
|
|
#[doc="ABSTIME[]"]
|
|
|
|
1023 => AbstimeArray: Kind::Array(Type::Abstime),
|
|
|
|
#[doc="RELTIME[]"]
|
|
|
|
1024 => ReltimeArray: Kind::Array(Type::Reltime),
|
|
|
|
#[doc="TINTERVAL[]"]
|
|
|
|
1025 => TintervalArray: Kind::Array(Type::Tinterval),
|
|
|
|
#[doc="POLYGON[]"]
|
|
|
|
1027 => PolygonArray: Kind::Array(Type::Polygon),
|
|
|
|
#[doc="OID[]"]
|
|
|
|
1028 => OidArray: Kind::Array(Type::Oid),
|
|
|
|
#[doc="ACLITEM - access control list"]
|
|
|
|
1033 => Aclitem: Kind::Simple,
|
|
|
|
#[doc="ACLITEM[]"]
|
|
|
|
1034 => AclitemArray: Kind::Array(Type::Aclitem),
|
|
|
|
#[doc="MACADDR[]"]
|
|
|
|
1040 => MacaddrArray: Kind::Array(Type::Macaddr),
|
|
|
|
#[doc="INET[]"]
|
|
|
|
1041 => InetArray: Kind::Array(Type::Inet),
|
|
|
|
#[doc="BPCHAR - char(length), blank-padded string, fixed storage length"]
|
|
|
|
1042 => Bpchar: Kind::Simple,
|
|
|
|
#[doc="VARCHAR - varchar(length), non-blank-padded string, variable storage length"]
|
|
|
|
1043 => Varchar: Kind::Simple,
|
|
|
|
#[doc="DATE - date"]
|
|
|
|
1082 => Date: Kind::Simple,
|
|
|
|
#[doc="TIME - time of day"]
|
|
|
|
1083 => Time: Kind::Simple,
|
|
|
|
#[doc="TIMESTAMP - date and time"]
|
|
|
|
1114 => Timestamp: Kind::Simple,
|
2013-12-08 22:04:26 +00:00
|
|
|
#[doc="TIMESTAMP[]"]
|
2015-02-19 05:04:44 +00:00
|
|
|
1115 => TimestampArray: Kind::Array(Type::Timestamp),
|
|
|
|
#[doc="DATE[]"]
|
|
|
|
1182 => DateArray: Kind::Array(Type::Date),
|
|
|
|
#[doc="TIME[]"]
|
|
|
|
1183 => TimeArray: Kind::Array(Type::Time),
|
|
|
|
#[doc="TIMESTAMPTZ - date and time with time zone"]
|
|
|
|
1184 => TimestampTZ: Kind::Simple,
|
|
|
|
#[doc="TIMESTAMPTZ[]"]
|
|
|
|
1185 => TimestampTZArray: Kind::Array(Type::TimestampTZ),
|
2015-02-19 07:32:35 +00:00
|
|
|
#[doc="INTERVAL - @ <number> <units>, time interval"]
|
2015-02-19 05:04:44 +00:00
|
|
|
1186 => Interval: Kind::Simple,
|
|
|
|
#[doc="INTERVAL[]"]
|
|
|
|
1187 => IntervalArray: Kind::Array(Type::Interval),
|
|
|
|
#[doc="NUMERIC[]"]
|
|
|
|
1231 => NumericArray: Kind::Array(Type::Numeric),
|
|
|
|
#[doc="CSTRING[]"]
|
|
|
|
1263 => CstringArray: Kind::Array(Type::Cstring),
|
|
|
|
#[doc="TIMETZ - time of day with time zone"]
|
|
|
|
1266 => Timetz: Kind::Simple,
|
|
|
|
#[doc="TIMETZ[]"]
|
|
|
|
1270 => TimetzArray: Kind::Array(Type::Timetz),
|
|
|
|
#[doc="BIT - fixed-length bit string"]
|
|
|
|
1560 => Bit: Kind::Simple,
|
|
|
|
#[doc="BIT[]"]
|
|
|
|
1561 => BitArray: Kind::Array(Type::Bit),
|
|
|
|
#[doc="VARBIT - variable-length bit string"]
|
|
|
|
1562 => Varbit: Kind::Simple,
|
|
|
|
#[doc="VARBIT[]"]
|
|
|
|
1563 => VarbitArray: Kind::Array(Type::Varbit),
|
|
|
|
#[doc="NUMERIC - numeric(precision, decimal), arbitrary precision number"]
|
|
|
|
1700 => Numeric: Kind::Simple,
|
|
|
|
#[doc="REFCURSOR - reference to cursor (portal name)"]
|
|
|
|
1790 => Refcursor: Kind::Simple,
|
|
|
|
#[doc="REFCURSOR[]"]
|
|
|
|
2201 => RefcursorArray: Kind::Array(Type::Refcursor),
|
|
|
|
#[doc="REGPROCEDURE - registered procedure (with args)"]
|
|
|
|
2202 => Regprocedure: Kind::Simple,
|
|
|
|
#[doc="REGOPER - registered operator"]
|
|
|
|
2203 => Regoper: Kind::Simple,
|
|
|
|
#[doc="REGOPERATOR - registered operator (with args)"]
|
|
|
|
2204 => Regoperator: Kind::Simple,
|
|
|
|
#[doc="REGCLASS - registered class"]
|
|
|
|
2205 => Regclass: Kind::Simple,
|
|
|
|
#[doc="REGTYPE - registered type"]
|
|
|
|
2206 => Regtype: Kind::Simple,
|
|
|
|
#[doc="REGPROCEDURE[]"]
|
|
|
|
2207 => RegprocedureArray: Kind::Array(Type::Regprocedure),
|
|
|
|
#[doc="REGOPER[]"]
|
|
|
|
2208 => RegoperArray: Kind::Array(Type::Regoper),
|
|
|
|
#[doc="REGOPERATOR[]"]
|
|
|
|
2209 => RegoperatorArray: Kind::Array(Type::Regoperator),
|
|
|
|
#[doc="REGCLASS[]"]
|
|
|
|
2210 => RegclassArray: Kind::Array(Type::Regclass),
|
|
|
|
#[doc="REGTYPE[]"]
|
|
|
|
2211 => RegtypeArray: Kind::Array(Type::Regtype),
|
|
|
|
#[doc="RECORD"]
|
|
|
|
2249 => Record: Kind::Simple,
|
|
|
|
#[doc="CSTRING"]
|
|
|
|
2275 => Cstring: Kind::Simple,
|
|
|
|
#[doc="ANY"]
|
|
|
|
2276 => Any: Kind::Simple,
|
|
|
|
#[doc="ANY[]"]
|
|
|
|
2277 => AnyArray: Kind::Array(Type::Any),
|
|
|
|
#[doc="VOID"]
|
|
|
|
2278 => Void: Kind::Simple,
|
|
|
|
#[doc="TRIGGER"]
|
|
|
|
2279 => Trigger: Kind::Simple,
|
|
|
|
#[doc="LANGUAGE_HANDLER"]
|
|
|
|
2280 => LanguageHandler: Kind::Simple,
|
|
|
|
#[doc="INTERNAL"]
|
|
|
|
2281 => Internal: Kind::Simple,
|
|
|
|
#[doc="OPAQUE"]
|
|
|
|
2282 => Opaque: Kind::Simple,
|
|
|
|
#[doc="ANYELEMENT"]
|
|
|
|
2283 => Anyelement: Kind::Simple,
|
|
|
|
#[doc="RECORD[]"]
|
|
|
|
2287 => RecordArray: Kind::Array(Type::Record),
|
|
|
|
#[doc="ANYNONARRAY"]
|
|
|
|
2776 => Anynonarray: Kind::Simple,
|
|
|
|
#[doc="TXID_SNAPSHOT[]"]
|
|
|
|
2949 => TxidSnapshotArray: Kind::Array(Type::TxidSnapshot),
|
|
|
|
#[doc="UUID - UUID datatype"]
|
|
|
|
2950 => Uuid: Kind::Simple,
|
|
|
|
#[doc="TXID_SNAPSHOT - txid snapshot"]
|
|
|
|
2970 => TxidSnapshot: Kind::Simple,
|
2014-11-06 15:53:16 +00:00
|
|
|
#[doc="UUID[]"]
|
2015-02-19 05:04:44 +00:00
|
|
|
2951 => UuidArray: Kind::Array(Type::Uuid),
|
|
|
|
#[doc="FDW_HANDLER"]
|
|
|
|
3115 => FdwHandler: Kind::Simple,
|
|
|
|
#[doc="PG_LSN - PostgreSQL LSN datatype"]
|
|
|
|
3320 => PgLsn: Kind::Simple,
|
|
|
|
#[doc="PG_LSN[]"]
|
|
|
|
3321 => PgLsnArray: Kind::Array(Type::PgLsn),
|
|
|
|
#[doc="ANYENUM"]
|
|
|
|
3500 => Anyenum: Kind::Simple,
|
|
|
|
#[doc="TSVECTOR - text representation for text search"]
|
|
|
|
3614 => Tsvector: Kind::Simple,
|
|
|
|
#[doc="TSQUERY - query representation for text search"]
|
|
|
|
3615 => Tsquery: Kind::Simple,
|
|
|
|
#[doc="GTSVECTOR - GiST index internal text representation for text search"]
|
|
|
|
3642 => Gtsvector: Kind::Simple,
|
|
|
|
#[doc="TSVECTOR[]"]
|
|
|
|
3643 => TsvectorArray: Kind::Array(Type::Tsvector),
|
|
|
|
#[doc="GTSVECTOR[]"]
|
|
|
|
3644 => GtsvectorArray: Kind::Array(Type::Gtsvector),
|
|
|
|
#[doc="TSQUERY[]"]
|
|
|
|
3645 => TsqueryArray: Kind::Array(Type::Tsquery),
|
|
|
|
#[doc="REGCONFIG - registered text search configuration"]
|
|
|
|
3734 => Regconfig: Kind::Simple,
|
|
|
|
#[doc="REGCONFIG[]"]
|
|
|
|
3735 => RegconfigArray: Kind::Array(Type::Regconfig),
|
|
|
|
#[doc="REGDICTIONARY - registered text search dictionary"]
|
|
|
|
3769 => Regdictionary: Kind::Simple,
|
|
|
|
#[doc="REGDICTIONARY[]"]
|
|
|
|
3770 => RegdictionaryArray: Kind::Array(Type::Regdictionary),
|
2014-12-23 02:04:13 +00:00
|
|
|
#[doc="JSONB"]
|
2015-02-19 05:04:44 +00:00
|
|
|
3802 => Jsonb: Kind::Simple,
|
|
|
|
#[doc="ANYRANGE"]
|
|
|
|
3831 => Anyrange: Kind::Simple,
|
2014-12-23 02:04:13 +00:00
|
|
|
#[doc="JSONB[]"]
|
2015-02-19 05:04:44 +00:00
|
|
|
3807 => JsonbArray: Kind::Array(Type::Jsonb),
|
|
|
|
#[doc="INT4RANGE - range of integers"]
|
|
|
|
3904 => Int4Range: Kind::Range(Type::Int4),
|
2013-12-08 22:37:31 +00:00
|
|
|
#[doc="INT4RANGE[]"]
|
2015-02-19 05:04:44 +00:00
|
|
|
3905 => Int4RangeArray: Kind::Array(Type::Int4Range),
|
|
|
|
#[doc="NUMRANGE - range of numerics"]
|
|
|
|
3906 => NumRange: Kind::Range(Type::Numeric),
|
|
|
|
#[doc="NUMRANGE[]"]
|
|
|
|
3907 => NumRangeArray: Kind::Array(Type::NumRange),
|
|
|
|
#[doc="TSRANGE - range of timestamps without time zone"]
|
|
|
|
3908 => TsRange: Kind::Range(Type::Timestamp),
|
2013-12-08 23:02:38 +00:00
|
|
|
#[doc="TSRANGE[]"]
|
2015-02-19 05:04:44 +00:00
|
|
|
3909 => TsRangeArray: Kind::Array(Type::TsRange),
|
|
|
|
#[doc="TSTZRANGE - range of timestamps with time zone"]
|
|
|
|
3910 => TstzRange: Kind::Range(Type::TimestampTZ),
|
2013-12-08 23:02:38 +00:00
|
|
|
#[doc="TSTZRANGE[]"]
|
2015-02-19 05:04:44 +00:00
|
|
|
3911 => TstzRangeArray: Kind::Array(Type::TstzRange),
|
|
|
|
#[doc="DATERANGE - range of dates"]
|
|
|
|
3912 => DateRange: Kind::Range(Type::Date),
|
|
|
|
#[doc="DATERANGE[]"]
|
|
|
|
3913 => DateRangeArray: Kind::Array(Type::DateRange),
|
|
|
|
#[doc="INT8RANGE - range of bigints"]
|
|
|
|
3926 => Int8Range: Kind::Range(Type::Int8),
|
2013-12-08 23:07:11 +00:00
|
|
|
#[doc="INT8RANGE[]"]
|
2015-02-19 05:04:44 +00:00
|
|
|
3927 => Int8RangeArray: Kind::Array(Type::Int8Range),
|
|
|
|
#[doc="EVENT_TRIGGER"]
|
|
|
|
3838 => EventTrigger: Kind::Simple
|
2014-12-19 18:43:42 +00:00
|
|
|
}
|
2013-09-02 19:42:24 +00:00
|
|
|
|
2015-02-15 01:07:10 +00:00
|
|
|
/// A trait for types that can be created from a Postgres value.
|
|
|
|
pub trait FromSql: Sized {
|
2015-02-26 17:02:32 +00:00
|
|
|
/// Creates a new value of this type from a `Read` of Postgres data.
|
2013-09-30 02:47:30 +00:00
|
|
|
///
|
2015-02-26 17:02:32 +00:00
|
|
|
/// If the value was `NULL`, the `Read` will be `None`.
|
2015-02-15 01:07:10 +00:00
|
|
|
///
|
|
|
|
/// The caller of this method is responsible for ensuring that this type
|
|
|
|
/// is compatible with the Postgres `Type`.
|
|
|
|
///
|
|
|
|
/// The default implementation calls `FromSql::from_sql` when `raw` is
|
|
|
|
/// `Some` and returns `Err(Error::WasNull)` when `raw` is `None`. It does
|
|
|
|
/// not typically need to be overridden.
|
2015-02-26 17:02:32 +00:00
|
|
|
fn from_sql_nullable<R: Read>(ty: &Type, raw: Option<&mut R>) -> Result<Self> {
|
2015-02-15 01:07:10 +00:00
|
|
|
match raw {
|
|
|
|
Some(raw) => FromSql::from_sql(ty, raw),
|
|
|
|
None => Err(Error::WasNull),
|
|
|
|
}
|
|
|
|
}
|
2013-08-28 04:36:27 +00:00
|
|
|
|
2015-04-08 06:57:22 +00:00
|
|
|
/// Creates a new value of this type from a `Read`er of the binary format
|
2015-02-15 23:31:07 +00:00
|
|
|
/// of the specified Postgres `Type`.
|
2015-01-22 06:31:04 +00:00
|
|
|
///
|
2015-02-15 01:07:10 +00:00
|
|
|
/// The caller of this method is responsible for ensuring that this type
|
|
|
|
/// is compatible with the Postgres `Type`.
|
2015-02-26 17:02:32 +00:00
|
|
|
fn from_sql<R: Read>(ty: &Type, raw: &mut R) -> Result<Self>;
|
2015-02-15 01:07:10 +00:00
|
|
|
|
|
|
|
/// Determines if a value of this type can be created from the specified
|
|
|
|
/// Postgres `Type`.
|
|
|
|
fn accepts(ty: &Type) -> bool;
|
2013-10-31 02:55:25 +00:00
|
|
|
}
|
|
|
|
|
2015-02-15 01:07:10 +00:00
|
|
|
impl<T: FromSql> FromSql for Option<T> {
|
2015-02-26 17:02:32 +00:00
|
|
|
fn from_sql_nullable<R: Read>(ty: &Type, raw: Option<&mut R>) -> Result<Option<T>> {
|
2015-02-15 01:07:10 +00:00
|
|
|
match raw {
|
|
|
|
Some(raw) => <T as FromSql>::from_sql(ty, raw).map(|e| Some(e)),
|
|
|
|
None => Ok(None),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-26 17:02:32 +00:00
|
|
|
fn from_sql<R: Read>(ty: &Type, raw: &mut R) -> Result<Option<T>> {
|
2015-02-15 01:07:10 +00:00
|
|
|
<T as FromSql>::from_sql(ty, raw).map(|e| Some(e))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn accepts(ty: &Type) -> bool {
|
|
|
|
<T as FromSql>::accepts(ty)
|
2013-12-07 23:39:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-15 01:07:10 +00:00
|
|
|
impl FromSql for bool {
|
2015-02-26 17:02:32 +00:00
|
|
|
fn from_sql<R: Read>(_: &Type, raw: &mut R) -> Result<bool> {
|
2015-02-15 01:07:10 +00:00
|
|
|
Ok(try!(raw.read_u8()) != 0)
|
|
|
|
}
|
|
|
|
|
|
|
|
accepts!(Type::Bool);
|
|
|
|
}
|
|
|
|
|
|
|
|
impl FromSql for Vec<u8> {
|
2015-02-26 17:02:32 +00:00
|
|
|
fn from_sql<R: Read>(_: &Type, raw: &mut R) -> Result<Vec<u8>> {
|
|
|
|
let mut buf = vec![];
|
|
|
|
try!(raw.read_to_end(&mut buf));
|
|
|
|
Ok(buf)
|
2014-11-17 17:43:10 +00:00
|
|
|
}
|
2015-02-15 01:07:10 +00:00
|
|
|
|
2015-02-19 07:30:06 +00:00
|
|
|
accepts!(Type::Bytea);
|
2014-11-17 17:43:10 +00:00
|
|
|
}
|
2013-12-08 22:37:31 +00:00
|
|
|
|
2015-02-15 01:07:10 +00:00
|
|
|
impl FromSql for String {
|
2015-02-26 17:02:32 +00:00
|
|
|
fn from_sql<R: Read>(_: &Type, raw: &mut R) -> Result<String> {
|
|
|
|
let mut buf = vec![];
|
|
|
|
try!(raw.read_to_end(&mut buf));
|
|
|
|
String::from_utf8(buf).map_err(|_| Error::BadResponse)
|
2014-11-17 17:43:10 +00:00
|
|
|
}
|
2015-02-15 01:07:10 +00:00
|
|
|
|
|
|
|
fn accepts(ty: &Type) -> bool {
|
|
|
|
match *ty {
|
2015-02-19 05:04:44 +00:00
|
|
|
Type::Varchar | Type::Text | Type::Bpchar | Type::Name => true,
|
|
|
|
Type::Other(ref u) if u.name() == "citext" => true,
|
2015-02-15 01:07:10 +00:00
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
2014-11-17 17:43:10 +00:00
|
|
|
}
|
|
|
|
|
2015-02-15 01:07:10 +00:00
|
|
|
macro_rules! primitive_from {
|
|
|
|
($t:ty, $f:ident, $($expected:pat),+) => {
|
|
|
|
impl FromSql for $t {
|
2015-02-26 17:02:32 +00:00
|
|
|
fn from_sql<R: Read>(_: &Type, raw: &mut R) -> Result<$t> {
|
|
|
|
Ok(try!(raw.$f::<BigEndian>()))
|
2015-02-15 01:07:10 +00:00
|
|
|
}
|
2014-11-17 17:43:10 +00:00
|
|
|
|
2015-02-15 01:07:10 +00:00
|
|
|
accepts!($($expected),+);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-26 17:02:32 +00:00
|
|
|
impl FromSql for i8 {
|
|
|
|
fn from_sql<R: Read>(_: &Type, raw: &mut R) -> Result<i8> {
|
|
|
|
Ok(try!(raw.read_i8()))
|
|
|
|
}
|
|
|
|
|
|
|
|
accepts!(Type::Char);
|
|
|
|
}
|
|
|
|
|
|
|
|
primitive_from!(i16, read_i16, Type::Int2);
|
|
|
|
primitive_from!(i32, read_i32, Type::Int4);
|
|
|
|
primitive_from!(u32, read_u32, Type::Oid);
|
|
|
|
primitive_from!(i64, read_i64, Type::Int8);
|
|
|
|
primitive_from!(f32, read_f32, Type::Float4);
|
|
|
|
primitive_from!(f64, read_f64, Type::Float8);
|
2015-02-15 01:07:10 +00:00
|
|
|
|
|
|
|
impl FromSql for HashMap<String, Option<String>> {
|
2015-02-26 17:02:32 +00:00
|
|
|
fn from_sql<R: Read>(_: &Type, raw: &mut R)
|
2015-02-15 01:07:10 +00:00
|
|
|
-> Result<HashMap<String, Option<String>>> {
|
|
|
|
let mut map = HashMap::new();
|
|
|
|
|
2015-02-26 17:02:32 +00:00
|
|
|
let count = try!(raw.read_i32::<BigEndian>());
|
2015-02-15 01:07:10 +00:00
|
|
|
|
2015-02-26 17:02:32 +00:00
|
|
|
for _ in 0..count {
|
|
|
|
let key_len = try!(raw.read_i32::<BigEndian>());
|
|
|
|
let mut key = vec![];
|
2015-04-08 06:57:22 +00:00
|
|
|
key.extend((0..key_len).map(|_| 0));
|
|
|
|
try!(util::read_all(raw, &mut key));
|
2015-02-15 01:07:10 +00:00
|
|
|
let key = match String::from_utf8(key) {
|
|
|
|
Ok(key) => key,
|
|
|
|
Err(_) => return Err(Error::BadResponse),
|
|
|
|
};
|
|
|
|
|
2015-02-26 17:02:32 +00:00
|
|
|
let val_len = try!(raw.read_i32::<BigEndian>());
|
2015-02-15 01:07:10 +00:00
|
|
|
let val = if val_len < 0 {
|
|
|
|
None
|
|
|
|
} else {
|
2015-02-26 17:02:32 +00:00
|
|
|
let mut val = vec![];
|
2015-04-08 06:57:22 +00:00
|
|
|
val.extend((0..val_len).map(|_| 0));
|
|
|
|
try!(util::read_all(raw, &mut val));
|
2015-02-15 01:07:10 +00:00
|
|
|
match String::from_utf8(val) {
|
|
|
|
Ok(val) => Some(val),
|
|
|
|
Err(_) => return Err(Error::BadResponse),
|
|
|
|
}
|
|
|
|
};
|
2014-12-15 00:43:17 +00:00
|
|
|
|
2015-02-15 01:07:10 +00:00
|
|
|
map.insert(key, val);
|
2014-12-15 00:43:17 +00:00
|
|
|
}
|
|
|
|
|
2015-02-15 01:07:10 +00:00
|
|
|
Ok(map)
|
|
|
|
}
|
2013-12-06 05:58:22 +00:00
|
|
|
|
2015-02-15 01:07:10 +00:00
|
|
|
fn accepts(ty: &Type) -> bool {
|
2014-03-13 06:50:10 +00:00
|
|
|
match *ty {
|
2015-02-19 05:04:44 +00:00
|
|
|
Type::Other(ref u) if u.name() == "hstore" => true,
|
2015-02-15 01:07:10 +00:00
|
|
|
_ => false
|
2014-03-28 05:43:10 +00:00
|
|
|
}
|
2013-12-05 05:20:48 +00:00
|
|
|
}
|
2014-03-13 06:50:10 +00:00
|
|
|
}
|
2013-12-05 05:20:48 +00:00
|
|
|
|
2015-02-15 23:11:15 +00:00
|
|
|
/// An enum representing the nullability of a Postgres value.
|
|
|
|
pub enum IsNull {
|
|
|
|
/// The value is NULL.
|
|
|
|
Yes,
|
|
|
|
/// The value is not NULL.
|
|
|
|
No,
|
2013-08-28 04:36:27 +00:00
|
|
|
}
|
|
|
|
|
2015-02-15 23:11:15 +00:00
|
|
|
/// A trait for types that can be converted into Postgres values.
|
2015-03-31 06:22:31 +00:00
|
|
|
pub trait ToSql: fmt::Debug {
|
2015-02-15 23:31:07 +00:00
|
|
|
/// Converts the value of `self` into the binary format of the specified
|
|
|
|
/// Postgres `Type`, writing it to `out`.
|
2015-01-22 06:31:04 +00:00
|
|
|
///
|
2015-02-15 23:11:15 +00:00
|
|
|
/// The caller of this method is responsible for ensuring that this type
|
|
|
|
/// is compatible with the Postgres `Type`.
|
|
|
|
///
|
|
|
|
/// The return value indicates if this value should be represented as
|
|
|
|
/// `NULL`. If this is the case, implementations **must not** write
|
|
|
|
/// anything to `out`.
|
|
|
|
fn to_sql<W: ?Sized>(&self, ty: &Type, out: &mut W) -> Result<IsNull>
|
2015-02-26 17:02:32 +00:00
|
|
|
where Self: Sized, W: Write;
|
2015-02-15 23:11:15 +00:00
|
|
|
|
|
|
|
/// Determines if a value of this type can be converted to the specified
|
|
|
|
/// Postgres `Type`.
|
|
|
|
fn accepts(ty: &Type) -> bool where Self: Sized;
|
|
|
|
|
|
|
|
/// An adaptor method used internally by Rust-Postgres.
|
|
|
|
///
|
|
|
|
/// *All* implementations of this method should be generated by the
|
|
|
|
/// `to_sql_checked!()` macro.
|
2015-02-26 17:02:32 +00:00
|
|
|
fn to_sql_checked(&self, ty: &Type, out: &mut Write) -> Result<IsNull>;
|
2013-10-31 02:55:25 +00:00
|
|
|
}
|
|
|
|
|
2015-02-15 23:11:15 +00:00
|
|
|
impl<T: ToSql> ToSql for Option<T> {
|
|
|
|
to_sql_checked!();
|
|
|
|
|
2015-02-26 17:02:32 +00:00
|
|
|
fn to_sql<W: Write+?Sized>(&self, ty: &Type, out: &mut W) -> Result<IsNull> {
|
2015-02-15 23:11:15 +00:00
|
|
|
match *self {
|
|
|
|
Some(ref val) => val.to_sql(ty, out),
|
|
|
|
None => Ok(IsNull::Yes),
|
|
|
|
}
|
2013-12-07 23:39:44 +00:00
|
|
|
}
|
|
|
|
|
2015-02-15 23:11:15 +00:00
|
|
|
fn accepts(ty: &Type) -> bool {
|
|
|
|
<T as ToSql>::accepts(ty)
|
2014-03-15 06:01:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-15 23:11:15 +00:00
|
|
|
impl ToSql for bool {
|
|
|
|
to_sql_checked!();
|
|
|
|
|
2015-02-26 17:02:32 +00:00
|
|
|
fn to_sql<W: Write+?Sized>(&self, _: &Type, mut w: &mut W) -> Result<IsNull> {
|
2015-02-15 23:11:15 +00:00
|
|
|
try!(w.write_u8(*self as u8));
|
|
|
|
Ok(IsNull::No)
|
2013-12-08 03:13:21 +00:00
|
|
|
}
|
2015-02-15 23:11:15 +00:00
|
|
|
|
|
|
|
accepts!(Type::Bool);
|
2013-12-08 03:13:21 +00:00
|
|
|
}
|
|
|
|
|
2015-02-15 23:11:15 +00:00
|
|
|
impl<'a> ToSql for &'a [u8] {
|
2015-04-12 18:10:02 +00:00
|
|
|
// FIXME should use to_sql_checked!() but blocked on rust-lang/rust#24308
|
|
|
|
fn to_sql_checked(&self, ty: &Type, out: &mut Write) -> Result<IsNull> {
|
|
|
|
if !<&'a [u8] as ToSql>::accepts(ty) {
|
|
|
|
return Err(Error::WrongType(ty.clone()));
|
|
|
|
}
|
|
|
|
self.to_sql(ty, out)
|
|
|
|
}
|
2013-10-31 02:55:25 +00:00
|
|
|
|
2015-02-26 17:02:32 +00:00
|
|
|
fn to_sql<W: Write+?Sized>(&self, _: &Type, w: &mut W) -> Result<IsNull> {
|
2015-02-15 23:11:15 +00:00
|
|
|
try!(w.write_all(*self));
|
|
|
|
Ok(IsNull::No)
|
2014-12-14 19:39:26 +00:00
|
|
|
}
|
2015-02-15 23:11:15 +00:00
|
|
|
|
|
|
|
accepts!(Type::Bytea);
|
2014-12-14 19:39:26 +00:00
|
|
|
}
|
|
|
|
|
2015-02-15 23:11:15 +00:00
|
|
|
impl ToSql for Vec<u8> {
|
|
|
|
to_sql_checked!();
|
2014-12-15 00:43:17 +00:00
|
|
|
|
2015-02-26 17:02:32 +00:00
|
|
|
fn to_sql<W: Write+?Sized>(&self, ty: &Type, w: &mut W) -> Result<IsNull> {
|
2015-02-15 23:11:15 +00:00
|
|
|
(&**self).to_sql(ty, w)
|
2014-12-15 00:43:17 +00:00
|
|
|
}
|
|
|
|
|
2015-02-15 23:11:15 +00:00
|
|
|
fn accepts(ty: &Type) -> bool {
|
|
|
|
<&[u8] as ToSql>::accepts(ty)
|
2014-12-15 00:43:17 +00:00
|
|
|
}
|
|
|
|
}
|
2014-12-14 23:07:48 +00:00
|
|
|
|
2014-10-26 03:24:08 +00:00
|
|
|
impl<'a> ToSql for &'a str {
|
2015-04-12 18:10:02 +00:00
|
|
|
// FIXME should use to_sql_checked!() but blocked on rust-lang/rust#24308
|
|
|
|
fn to_sql_checked(&self, ty: &Type, out: &mut Write) -> Result<IsNull> {
|
|
|
|
if !<&'a str as ToSql>::accepts(ty) {
|
|
|
|
return Err(Error::WrongType(ty.clone()));
|
|
|
|
}
|
|
|
|
self.to_sql(ty, out)
|
|
|
|
}
|
2015-02-15 23:11:15 +00:00
|
|
|
|
2015-02-26 17:02:32 +00:00
|
|
|
fn to_sql<W: Write+?Sized>(&self, _: &Type, w: &mut W) -> Result<IsNull> {
|
2015-02-15 23:11:15 +00:00
|
|
|
try!(w.write_all(self.as_bytes()));
|
|
|
|
Ok(IsNull::No)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn accepts(ty: &Type) -> bool {
|
2014-12-15 00:43:17 +00:00
|
|
|
match *ty {
|
2015-02-15 23:11:15 +00:00
|
|
|
Type::Varchar | Type::Text | Type::Bpchar | Type::Name => true,
|
|
|
|
Type::Other(ref u) if u.name() == "citext" => true,
|
|
|
|
_ => false,
|
2014-12-15 00:43:17 +00:00
|
|
|
}
|
2013-08-28 04:36:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-15 23:11:15 +00:00
|
|
|
impl ToSql for String {
|
|
|
|
to_sql_checked!();
|
|
|
|
|
2015-02-26 17:02:32 +00:00
|
|
|
fn to_sql<W: Write+?Sized>(&self, ty: &Type, w: &mut W) -> Result<IsNull> {
|
2015-02-15 23:11:15 +00:00
|
|
|
(&**self).to_sql(ty, w)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn accepts(ty: &Type) -> bool {
|
|
|
|
<&str as ToSql>::accepts(ty)
|
2014-12-15 00:43:17 +00:00
|
|
|
}
|
|
|
|
}
|
2013-09-02 19:42:24 +00:00
|
|
|
|
2015-02-15 23:11:15 +00:00
|
|
|
macro_rules! to_primitive {
|
|
|
|
($t:ty, $f:ident, $($expected:pat),+) => {
|
|
|
|
impl ToSql for $t {
|
|
|
|
to_sql_checked!();
|
|
|
|
|
2015-02-26 17:02:32 +00:00
|
|
|
fn to_sql<W: Write+?Sized>(&self, _: &Type, mut w: &mut W) -> Result<IsNull> {
|
|
|
|
try!(w.$f::<BigEndian>(*self));
|
2015-02-15 23:11:15 +00:00
|
|
|
Ok(IsNull::No)
|
|
|
|
}
|
|
|
|
|
|
|
|
accepts!($($expected),+);
|
|
|
|
}
|
2013-09-02 19:42:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-26 17:02:32 +00:00
|
|
|
impl ToSql for i8 {
|
|
|
|
to_sql_checked!();
|
|
|
|
|
|
|
|
fn to_sql<W: Write+?Sized>(&self, _: &Type, mut w: &mut W) -> Result<IsNull> {
|
|
|
|
try!(w.write_i8(*self));
|
|
|
|
Ok(IsNull::No)
|
|
|
|
}
|
|
|
|
|
|
|
|
accepts!(Type::Char);
|
|
|
|
}
|
|
|
|
|
|
|
|
to_primitive!(i16, write_i16, Type::Int2);
|
|
|
|
to_primitive!(i32, write_i32, Type::Int4);
|
|
|
|
to_primitive!(u32, write_u32, Type::Oid);
|
|
|
|
to_primitive!(i64, write_i64, Type::Int8);
|
|
|
|
to_primitive!(f32, write_f32, Type::Float4);
|
|
|
|
to_primitive!(f64, write_f64, Type::Float8);
|
2014-12-19 18:43:42 +00:00
|
|
|
|
2015-02-15 23:11:15 +00:00
|
|
|
impl ToSql for HashMap<String, Option<String>> {
|
|
|
|
to_sql_checked!();
|
2013-12-05 05:20:48 +00:00
|
|
|
|
2015-02-26 17:02:32 +00:00
|
|
|
fn to_sql<W: Write+?Sized>(&self, _: &Type, mut w: &mut W) -> Result<IsNull> {
|
|
|
|
try!(w.write_i32::<BigEndian>(self.len() as i32));
|
2013-12-05 05:20:48 +00:00
|
|
|
|
|
|
|
for (key, val) in self.iter() {
|
2015-02-26 17:02:32 +00:00
|
|
|
try!(w.write_i32::<BigEndian>(key.len() as i32));
|
2015-02-15 23:11:15 +00:00
|
|
|
try!(w.write_all(key.as_bytes()));
|
2013-12-05 05:20:48 +00:00
|
|
|
|
|
|
|
match *val {
|
|
|
|
Some(ref val) => {
|
2015-02-26 17:02:32 +00:00
|
|
|
try!(w.write_i32::<BigEndian>(val.len() as i32));
|
2015-02-15 23:11:15 +00:00
|
|
|
try!(w.write_all(val.as_bytes()));
|
2013-12-05 05:20:48 +00:00
|
|
|
}
|
2015-02-26 17:02:32 +00:00
|
|
|
None => try!(w.write_i32::<BigEndian>(-1))
|
2013-12-05 05:20:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-15 23:11:15 +00:00
|
|
|
Ok(IsNull::No)
|
2013-12-05 05:20:48 +00:00
|
|
|
}
|
2014-03-13 06:50:10 +00:00
|
|
|
|
2015-02-15 23:11:15 +00:00
|
|
|
fn accepts(ty: &Type) -> bool {
|
2014-03-13 06:50:10 +00:00
|
|
|
match *ty {
|
2015-02-15 23:11:15 +00:00
|
|
|
Type::Other(ref u) if u.name() == "hstore" => true,
|
|
|
|
_ => false,
|
2014-03-13 06:50:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|