Skip to content

Commit 2b617e6

Browse files
committed
Beginnings of Bind support
1 parent 1f12728 commit 2b617e6

3 files changed

Lines changed: 88 additions & 14 deletions

File tree

src/lib.rs

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,7 @@ pub struct PostgresConnection {
1818

1919
impl Drop for PostgresConnection {
2020
fn drop(&self) {
21-
do io_error::cond.trap(|_| { }).inside {
22-
do self.stream.with_mut_ref |s| {
23-
s.write_message(&Terminate);
24-
}
25-
}
21+
self.write_message(&Terminate);
2622
}
2723
}
2824

@@ -111,7 +107,8 @@ impl PostgresConnection {
111107
PostgresStatement {
112108
conn: self,
113109
name: stmt_name,
114-
num_params: num_params
110+
num_params: num_params,
111+
next_portal_id: Cell::new(0)
115112
}
116113
}
117114
@@ -126,9 +123,44 @@ impl PostgresConnection {
126123
pub struct PostgresStatement<'self> {
127124
priv conn: &'self PostgresConnection,
128125
priv name: ~str,
129-
priv num_params: uint
126+
priv num_params: uint,
127+
priv next_portal_id: Cell<uint>
128+
}
129+
130+
#[unsafe_destructor]
131+
impl<'self> Drop for PostgresStatement<'self> {
132+
fn drop(&self) {
133+
self.conn.write_message(&Close('S' as u8, self.name.as_slice()));
134+
self.conn.write_message(&Sync);
135+
self.conn.read_message(); // CloseComplete or ErrorResponse
136+
self.conn.wait_for_ready();
137+
}
130138
}
131139
132140
impl<'self> PostgresStatement<'self> {
141+
pub fn num_params(&self) -> uint {
142+
self.num_params
143+
}
144+
145+
pub fn query(&self) {
146+
let id = self.next_portal_id.take();
147+
let portal_name = ifmt!("{:s}_portal_{}", self.name.as_slice(), id);
148+
self.next_portal_id.put_back(id + 1);
133149
150+
let formats = [];
151+
let values = [];
152+
let result_formats = [];
153+
154+
self.conn.write_message(&Bind(portal_name, self.name.as_slice(),
155+
formats, values, result_formats));
156+
self.conn.write_message(&Sync);
157+
158+
match self.conn.read_message() {
159+
BindComplete => (),
160+
ErrorResponse(ref data) => fail!("Error: %?", data),
161+
resp => fail!("Bad response: %?", resp)
162+
}
163+
164+
self.conn.wait_for_ready();
165+
}
134166
}

src/message.rs

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ pub static PROTOCOL_VERSION: i32 = 0x0003_0000;
1212
pub enum BackendMessage {
1313
AuthenticationOk,
1414
BackendKeyData(i32, i32),
15+
BindComplete,
16+
CloseComplete,
1517
ErrorResponse(HashMap<u8, ~str>),
1618
NoData,
1719
ParameterDescription(~[i32]),
@@ -32,6 +34,10 @@ pub struct RowDescriptionEntry {
3234
}
3335

3436
pub enum FrontendMessage<'self> {
37+
/// portal, stmt, formats, values, result formats
38+
Bind(&'self str, &'self str, &'self [i16], &'self [Option<&'self [u8]>],
39+
&'self [i16]),
40+
Close(u8, &'self str),
3541
Describe(u8, &'self str),
3642
/// name, query, parameter types
3743
Parse(&'self str, &'self str, &'self [i32]),
@@ -63,23 +69,56 @@ impl<W: Writer> WriteMessage for W {
6369
let mut ident = None;
6470

6571
match *message {
66-
Describe(variant, ref name) => {
72+
Bind(portal, stmt, formats, values, result_formats) => {
73+
ident = Some('B');
74+
buf.write_string(portal);
75+
buf.write_string(stmt);
76+
77+
buf.write_be_i16_(formats.len() as i16);
78+
for format in formats.iter() {
79+
buf.write_be_i16_(*format);
80+
}
81+
82+
buf.write_be_i16_(values.len() as i16);
83+
for value in values.iter() {
84+
match *value {
85+
None => {
86+
buf.write_be_i16_(-1);
87+
}
88+
Some(value) => {
89+
buf.write_be_i32_(value.len() as i32);
90+
buf.write(value);
91+
}
92+
}
93+
}
94+
95+
buf.write_be_i16_(result_formats.len() as i16);
96+
for format in result_formats.iter() {
97+
buf.write_be_i16_(*format);
98+
}
99+
}
100+
Close(variant, name) => {
101+
ident = Some('C');
102+
buf.write_u8_(variant);
103+
buf.write_string(name);
104+
}
105+
Describe(variant, name) => {
67106
ident = Some('D');
68107
buf.write_u8_(variant);
69-
buf.write_string(*name);
108+
buf.write_string(name);
70109
}
71-
Parse(ref name, ref query, ref param_types) => {
110+
Parse(name, query, param_types) => {
72111
ident = Some('P');
73-
buf.write_string(*name);
74-
buf.write_string(*query);
112+
buf.write_string(name);
113+
buf.write_string(query);
75114
buf.write_be_i16_(param_types.len() as i16);
76115
for ty in param_types.iter() {
77116
buf.write_be_i32_(*ty);
78117
}
79118
}
80-
Query(ref query) => {
119+
Query(query) => {
81120
ident = Some('Q');
82-
buf.write_string(*query);
121+
buf.write_string(query);
83122
}
84123
StartupMessage(ref params) => {
85124
buf.write_be_i32_(PROTOCOL_VERSION);
@@ -144,6 +183,8 @@ impl<R: Reader> ReadMessage for R {
144183

145184
let ret = match ident as char {
146185
'1' => ParseComplete,
186+
'2' => BindComplete,
187+
'3' => CloseComplete,
147188
'E' => read_error_message(&mut buf),
148189
'K' => BackendKeyData(buf.read_be_i32_(), buf.read_be_i32_()),
149190
'n' => NoData,

src/test.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ fn test_connect() {
88
"postgres");
99

1010
let stmt = conn.prepare("CREATE TABLE foo (id BIGINT PRIMARY KEY)");
11+
stmt.query();
1112
}

0 commit comments

Comments
 (0)