Skip to content

Commit 02fdb06

Browse files
committed
Support citext and oid types
This ended up involving some pretty major refactors and fixed a bug where passing extension types as parameters to `execute` broke. Closes rust-postgres#56
1 parent 0562063 commit 02fdb06

5 files changed

Lines changed: 238 additions & 118 deletions

File tree

.travis/setup.sql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
CREATE ROLE pass_user PASSWORD 'password' LOGIN;
22
CREATE ROLE md5_user PASSWORD 'password' LOGIN;
33
CREATE EXTENSION hstore;
4+
CREATE EXTENSION citext;

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,10 @@ types. The driver currently supports the following conversions:
179179
<td>i32</td>
180180
<td>INT, SERIAL</td>
181181
</tr>
182+
<tr>
183+
<td>u32</td>
184+
<td>OID</td>
185+
</tr>
182186
<tr>
183187
<td>i64</td>
184188
<td>BIGINT, BIGSERIAL</td>
@@ -193,7 +197,7 @@ types. The driver currently supports the following conversions:
193197
</tr>
194198
<tr>
195199
<td>str/String</td>
196-
<td>VARCHAR, CHAR(n), TEXT</td>
200+
<td>VARCHAR, CHAR(n), TEXT, CITEXT</td>
197201
</tr>
198202
<tr>
199203
<td>[u8]/Vec&lt;u8&gt;</td>

src/lib.rs

Lines changed: 50 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ mod util;
9797
pub mod types;
9898

9999
const CANARY: u32 = 0xdeadbeef;
100+
const TYPENAME_QUERY: &'static str = "t";
100101

101102
/// A type alias of the result returned by many methods.
102103
pub type Result<T> = result::Result<T, Error>;
@@ -441,6 +442,13 @@ impl InnerConnection {
441442
}
442443
}
443444

445+
match conn.raw_prepare(TYPENAME_QUERY, "SELECT typname FROM pg_type WHERE oid = $1") {
446+
Ok(..) => {}
447+
Err(Error::IoError(e)) => return Err(ConnectError::IoError(e)),
448+
Err(Error::DbError(e)) => return Err(ConnectError::DbError(e)),
449+
_ => unreachable!()
450+
}
451+
444452
Ok(conn)
445453
}
446454

@@ -580,10 +588,10 @@ impl InnerConnection {
580588
try!(self.wait_for_ready());
581589

582590
// now that the connection is ready again, get unknown type names,
583-
// but not if stmt_name is "" since that'll blow away the statement
584-
// and we don't care about result values anyway
591+
try!(self.set_type_names(param_types.iter_mut()));
592+
// An empty statement name means we're calling execute, so we don't
593+
// care about result types
585594
if stmt_name != "" {
586-
try!(self.set_type_names(param_types.iter_mut()));
587595
try!(self.set_type_names(result_desc.iter_mut().map(|d| &mut d.ty)));
588596
}
589597

@@ -665,9 +673,45 @@ impl InnerConnection {
665673
if let Some(name) = self.unknown_types.get(&oid) {
666674
return Ok(name.clone());
667675
}
668-
let name = try!(self.quick_query(&*format!("SELECT typname FROM pg_type WHERE oid={}",
669-
oid)))
670-
.into_iter().next().unwrap().into_iter().next().unwrap().unwrap();
676+
// Ew @ doing this manually :(
677+
try!(self.write_messages(&[
678+
Bind {
679+
portal: "",
680+
statement: TYPENAME_QUERY,
681+
formats: &[1],
682+
values: &[try!(oid.to_sql(&Type::Oid))],
683+
result_formats: &[1]
684+
},
685+
Execute {
686+
portal: "",
687+
max_rows: 0,
688+
},
689+
Sync]));
690+
match try!(self.read_message()) {
691+
BindComplete => {}
692+
ErrorResponse { fields } => {
693+
try!(self.wait_for_ready());
694+
return DbError::new(fields);
695+
}
696+
_ => bad_response!(self)
697+
}
698+
let name: String = match try!(self.read_message()) {
699+
DataRow { row } => try!(FromSql::from_sql(&Type::Name, &row[0])),
700+
ErrorResponse { fields } => {
701+
try!(self.wait_for_ready());
702+
return DbError::new(fields);
703+
}
704+
_ => bad_response!(self)
705+
};
706+
match try!(self.read_message()) {
707+
CommandComplete { .. } => {}
708+
ErrorResponse { fields } => {
709+
try!(self.wait_for_ready());
710+
return DbError::new(fields);
711+
}
712+
_ => bad_response!(self)
713+
}
714+
try!(self.wait_for_ready());
671715
self.unknown_types.insert(oid, name.clone());
672716
Ok(name)
673717
}

0 commit comments

Comments
 (0)