rust-postgres/message.rs

377 lines
9.8 KiB
Rust
Raw Normal View History

2013-09-30 02:47:30 +00:00
#[allow(missing_doc)];
2013-08-22 05:52:15 +00:00
use std::str;
use std::rt::io::{Decorator, Reader, Writer};
use std::rt::io::mem::{MemWriter, MemReader};
2013-10-18 06:51:00 +00:00
use std::mem;
2013-08-22 06:41:26 +00:00
use std::vec;
2013-08-22 05:52:15 +00:00
use super::types::Oid;
2013-08-22 05:52:15 +00:00
pub static PROTOCOL_VERSION: i32 = 0x0003_0000;
2013-10-21 00:32:14 +00:00
pub static CANCEL_CODE: i32 = 80877102;
2013-08-22 05:52:15 +00:00
2013-08-23 05:24:14 +00:00
#[deriving(ToStr)]
2013-08-22 05:52:15 +00:00
pub enum BackendMessage {
2013-09-12 05:02:32 +00:00
AuthenticationOk,
AuthenticationKerberosV5,
AuthenticationCleartextPassword,
AuthenticationMD5Password {
salt: ~[u8]
},
2013-09-12 05:02:32 +00:00
AuthenticationSCMCredential,
AuthenticationGSS,
AuthenticationSSPI,
BackendKeyData {
process_id: i32,
secret_key: i32
},
2013-08-22 07:12:35 +00:00
BindComplete,
CloseComplete,
CommandComplete {
tag: ~str
},
DataRow {
row: ~[Option<~[u8]>]
},
2013-08-23 05:24:14 +00:00
EmptyQueryResponse,
ErrorResponse {
fields: ~[(u8, ~str)]
},
2013-08-22 06:41:26 +00:00
NoData,
NoticeResponse {
fields: ~[(u8, ~str)]
},
NotificationResponse {
pid: i32,
channel: ~str,
payload: ~str
},
ParameterDescription {
types: ~[Oid]
},
ParameterStatus {
parameter: ~str,
value: ~str
},
2013-08-22 05:52:15 +00:00
ParseComplete,
PortalSuspended,
ReadyForQuery {
state: u8
},
RowDescription {
descriptions: ~[RowDescriptionEntry]
}
2013-08-22 05:52:15 +00:00
}
2013-08-23 05:24:14 +00:00
#[deriving(ToStr)]
2013-08-22 06:41:26 +00:00
pub struct RowDescriptionEntry {
name: ~str,
table_oid: Oid,
2013-08-22 06:41:26 +00:00
column_id: i16,
type_oid: Oid,
2013-08-22 06:41:26 +00:00
type_size: i16,
type_modifier: i32,
format: i16
}
pub enum FrontendMessage<'self> {
Bind {
portal: &'self str,
statement: &'self str,
formats: &'self [i16],
values: &'self [Option<~[u8]>],
result_formats: &'self [i16]
},
2013-10-21 00:32:14 +00:00
CancelRequest {
code: i32,
process_id: i32,
secret_key: i32,
},
Close {
variant: u8,
name: &'self str
},
Describe {
variant: u8,
name: &'self str
},
Execute {
portal: &'self str,
max_rows: i32
},
Parse {
name: &'self str,
query: &'self str,
param_types: &'self [i32]
},
PasswordMessage {
password: &'self str
},
Query {
query: &'self str
},
StartupMessage {
version: i32,
parameters: &'self [(~str, ~str)]
},
2013-08-22 05:52:15 +00:00
Sync,
Terminate
}
trait WriteString {
fn write_string(&mut self, s: &str);
}
impl<W: Writer> WriteString for W {
fn write_string(&mut self, s: &str) {
self.write(s.as_bytes());
2013-10-29 05:35:52 +00:00
self.write_u8(0);
2013-08-22 05:52:15 +00:00
}
}
pub trait WriteMessage {
fn write_message(&mut self, &FrontendMessage);
}
impl<W: Writer> WriteMessage for W {
fn write_message(&mut self, message: &FrontendMessage) {
2013-10-21 04:06:12 +00:00
debug!("Writing message {:?}", message);
2013-08-22 05:52:15 +00:00
let mut buf = MemWriter::new();
let mut ident = None;
match *message {
Bind { portal, statement, formats, values, result_formats } => {
2013-08-22 07:12:35 +00:00
ident = Some('B');
buf.write_string(portal);
buf.write_string(statement);
2013-08-22 07:12:35 +00:00
2013-10-29 05:35:52 +00:00
buf.write_be_i16(formats.len() as i16);
2013-08-22 07:12:35 +00:00
for format in formats.iter() {
2013-10-29 05:35:52 +00:00
buf.write_be_i16(*format);
2013-08-22 07:12:35 +00:00
}
2013-10-29 05:35:52 +00:00
buf.write_be_i16(values.len() as i16);
2013-08-22 07:12:35 +00:00
for value in values.iter() {
match *value {
None => {
2013-10-29 05:35:52 +00:00
buf.write_be_i32(-1);
2013-08-22 07:12:35 +00:00
}
2013-08-25 03:47:36 +00:00
Some(ref value) => {
2013-10-29 05:35:52 +00:00
buf.write_be_i32(value.len() as i32);
2013-08-25 03:47:36 +00:00
buf.write(*value);
2013-08-22 07:12:35 +00:00
}
}
}
2013-10-29 05:35:52 +00:00
buf.write_be_i16(result_formats.len() as i16);
2013-08-22 07:12:35 +00:00
for format in result_formats.iter() {
2013-10-29 05:35:52 +00:00
buf.write_be_i16(*format);
2013-08-22 07:12:35 +00:00
}
}
2013-10-21 00:32:14 +00:00
CancelRequest { code, process_id, secret_key } => {
2013-10-29 05:35:52 +00:00
buf.write_be_i32(code);
buf.write_be_i32(process_id);
buf.write_be_i32(secret_key);
2013-10-21 00:32:14 +00:00
}
Close { variant, name } => {
2013-08-22 07:12:35 +00:00
ident = Some('C');
2013-10-29 05:35:52 +00:00
buf.write_u8(variant);
2013-08-22 07:12:35 +00:00
buf.write_string(name);
}
Describe { variant, name } => {
2013-08-22 06:41:26 +00:00
ident = Some('D');
2013-10-29 05:35:52 +00:00
buf.write_u8(variant);
2013-08-22 07:12:35 +00:00
buf.write_string(name);
2013-08-22 06:41:26 +00:00
}
Execute { portal, max_rows } => {
2013-08-23 05:24:14 +00:00
ident = Some('E');
buf.write_string(portal);
2013-10-29 05:35:52 +00:00
buf.write_be_i32(max_rows);
2013-08-23 05:24:14 +00:00
}
Parse { name, query, param_types } => {
2013-08-22 05:52:15 +00:00
ident = Some('P');
2013-08-22 07:12:35 +00:00
buf.write_string(name);
buf.write_string(query);
2013-10-29 05:35:52 +00:00
buf.write_be_i16(param_types.len() as i16);
2013-08-22 05:52:15 +00:00
for ty in param_types.iter() {
2013-10-29 05:35:52 +00:00
buf.write_be_i32(*ty);
2013-08-22 05:52:15 +00:00
}
}
PasswordMessage { password } => {
ident = Some('p');
buf.write_string(password);
}
Query { query } => {
2013-08-22 05:52:15 +00:00
ident = Some('Q');
2013-08-22 07:12:35 +00:00
buf.write_string(query);
2013-08-22 05:52:15 +00:00
}
StartupMessage { version, parameters } => {
2013-10-29 05:35:52 +00:00
buf.write_be_i32(version);
for &(ref k, ref v) in parameters.iter() {
buf.write_string(k.as_slice());
buf.write_string(v.as_slice());
2013-08-22 05:52:15 +00:00
}
2013-10-29 05:35:52 +00:00
buf.write_u8(0);
2013-08-22 05:52:15 +00:00
}
Sync => {
ident = Some('S');
}
Terminate => {
ident = Some('X');
}
}
match ident {
2013-10-29 05:35:52 +00:00
Some(ident) => self.write_u8(ident as u8),
2013-08-22 05:52:15 +00:00
None => ()
}
// add size of length value
2013-10-29 05:35:52 +00:00
self.write_be_i32((buf.inner_ref().len() + mem::size_of::<i32>())
2013-08-22 05:52:15 +00:00
as i32);
self.write(buf.inner());
}
}
trait ReadString {
fn read_string(&mut self) -> ~str;
}
impl<R: Reader> ReadString for R {
fn read_string(&mut self) -> ~str {
let mut buf = ~[];
loop {
2013-10-29 05:35:52 +00:00
let byte = self.read_u8();
2013-08-22 05:52:15 +00:00
if byte == 0 {
break;
}
buf.push(byte);
}
str::from_utf8_owned(buf)
2013-08-22 05:52:15 +00:00
}
}
pub trait ReadMessage {
fn read_message(&mut self) -> BackendMessage;
}
impl<R: Reader> ReadMessage for R {
fn read_message(&mut self) -> BackendMessage {
debug!("Reading message");
2013-10-29 05:35:52 +00:00
let ident = self.read_u8();
2013-08-22 05:52:15 +00:00
// subtract size of length value
2013-10-29 05:35:52 +00:00
let len = self.read_be_i32() as uint - mem::size_of::<i32>();
2013-08-22 05:52:15 +00:00
let mut buf = MemReader::new(self.read_bytes(len));
let ret = match ident as char {
'1' => ParseComplete,
2013-08-22 07:12:35 +00:00
'2' => BindComplete,
'3' => CloseComplete,
'A' => NotificationResponse {
2013-10-29 05:35:52 +00:00
pid: buf.read_be_i32(),
channel: buf.read_string(),
payload: buf.read_string()
},
'C' => CommandComplete { tag: buf.read_string() },
2013-08-23 05:24:14 +00:00
'D' => read_data_row(&mut buf),
'E' => ErrorResponse { fields: read_fields(&mut buf) },
2013-08-23 05:24:14 +00:00
'I' => EmptyQueryResponse,
'K' => BackendKeyData {
2013-10-29 05:35:52 +00:00
process_id: buf.read_be_i32(),
secret_key: buf.read_be_i32()
},
2013-08-22 06:41:26 +00:00
'n' => NoData,
'N' => NoticeResponse { fields: read_fields(&mut buf) },
2013-08-22 05:52:15 +00:00
'R' => read_auth_message(&mut buf),
's' => PortalSuspended,
'S' => ParameterStatus {
parameter: buf.read_string(),
value: buf.read_string()
},
2013-08-22 06:41:26 +00:00
't' => read_parameter_description(&mut buf),
'T' => read_row_description(&mut buf),
2013-10-29 05:35:52 +00:00
'Z' => ReadyForQuery { state: buf.read_u8() },
2013-10-21 04:06:12 +00:00
ident => fail!("Unknown message identifier `{}`", ident)
2013-08-22 05:52:15 +00:00
};
assert!(buf.eof());
2013-10-21 04:06:12 +00:00
debug!("Read message {:?}", ret);
2013-08-22 05:52:15 +00:00
ret
}
}
fn read_fields(buf: &mut MemReader) -> ~[(u8, ~str)] {
let mut fields = ~[];
2013-08-22 05:52:15 +00:00
loop {
2013-10-29 05:35:52 +00:00
let ty = buf.read_u8();
2013-08-22 05:52:15 +00:00
if ty == 0 {
break;
}
fields.push((ty, buf.read_string()));
2013-08-22 05:52:15 +00:00
}
2013-08-23 05:24:14 +00:00
fields
}
fn read_data_row(buf: &mut MemReader) -> BackendMessage {
2013-10-29 05:35:52 +00:00
let len = buf.read_be_i16() as uint;
2013-08-23 05:24:14 +00:00
let mut values = vec::with_capacity(len);
do len.times() {
2013-10-29 05:35:52 +00:00
let val = match buf.read_be_i32() {
2013-08-23 05:24:14 +00:00
-1 => None,
len => Some(buf.read_bytes(len as uint))
};
values.push(val);
}
DataRow { row: values }
2013-08-22 05:52:15 +00:00
}
fn read_auth_message(buf: &mut MemReader) -> BackendMessage {
2013-10-29 05:35:52 +00:00
match buf.read_be_i32() {
2013-08-22 05:52:15 +00:00
0 => AuthenticationOk,
2013-09-12 05:02:32 +00:00
2 => AuthenticationKerberosV5,
3 => AuthenticationCleartextPassword,
5 => AuthenticationMD5Password { salt: buf.read_bytes(4) },
2013-09-12 05:02:32 +00:00
6 => AuthenticationSCMCredential,
7 => AuthenticationGSS,
9 => AuthenticationSSPI,
2013-10-21 04:06:12 +00:00
val => fail!("Invalid authentication identifier `{}`", val)
2013-08-22 05:52:15 +00:00
}
}
2013-08-22 06:41:26 +00:00
fn read_parameter_description(buf: &mut MemReader) -> BackendMessage {
2013-10-29 05:35:52 +00:00
let len = buf.read_be_i16() as uint;
2013-08-22 06:41:26 +00:00
let mut types = vec::with_capacity(len);
do len.times() {
2013-10-29 05:35:52 +00:00
types.push(buf.read_be_i32());
2013-08-22 06:41:26 +00:00
}
ParameterDescription { types: types }
2013-08-22 06:41:26 +00:00
}
fn read_row_description(buf: &mut MemReader) -> BackendMessage {
2013-10-29 05:35:52 +00:00
let len = buf.read_be_i16() as uint;
2013-08-22 06:41:26 +00:00
let mut types = vec::with_capacity(len);
do len.times() {
types.push(RowDescriptionEntry {
name: buf.read_string(),
2013-10-29 05:35:52 +00:00
table_oid: buf.read_be_i32(),
column_id: buf.read_be_i16(),
type_oid: buf.read_be_i32(),
type_size: buf.read_be_i16(),
type_modifier: buf.read_be_i32(),
format: buf.read_be_i16()
2013-08-22 06:41:26 +00:00
});
}
RowDescription { descriptions: types }
2013-08-22 06:41:26 +00:00
}