@@ -100,6 +100,7 @@ use error::{DnsError,
100100 PgConnectDbError ,
101101 PgConnectStreamError ,
102102 PgDbError ,
103+ PgInvalidColumn ,
103104 PgStreamDesynchronized ,
104105 PgStreamError ,
105106 PgWrongParamCount ,
@@ -1332,24 +1333,30 @@ impl<'stmt> Iterator<PostgresRow<'stmt>> for PostgresResult<'stmt> {
13321333}
13331334
13341335/// A single result row of a query.
1335- ///
1336- /// A value can be accessed by the name or index of its column, though access
1337- /// by index is more efficient. Rows are 1-indexed.
1338- ///
1339- /// ```rust,no_run
1340- /// # use postgres::{PostgresConnection, NoSsl};
1341- /// # let conn = PostgresConnection::connect("", &NoSsl).unwrap();
1342- /// # let stmt = conn.prepare("").unwrap();
1343- /// # let mut result = stmt.query([]).unwrap();
1344- /// # let row = result.next().unwrap();
1345- /// let foo: i32 = row[1];
1346- /// let bar: ~str = row["bar"];
1347- /// ```
13481336pub struct PostgresRow < ' stmt > {
13491337 priv stmt : & ' stmt PostgresStatement < ' stmt > ,
13501338 priv data : Vec < Option < ~[ u8 ] > >
13511339}
13521340
1341+ impl < ' stmt > PostgresRow < ' stmt > {
1342+ /// Retrieves the contents of a field of the row.
1343+ ///
1344+ /// A field can be accessed by the name or index of its column, though
1345+ /// access by index is more efficient. Rows are 1-indexed.
1346+ ///
1347+ /// Returns an `Error` value if the index does not reference a column or
1348+ /// the return type is not compatible with the Postgres type.
1349+ pub fn get < I : RowIndex , T : FromSql > ( & self , idx : I )
1350+ -> Result < T , PostgresError > {
1351+ let idx = match idx. idx ( self . stmt ) {
1352+ Some ( idx) => idx,
1353+ None => return Err ( PgInvalidColumn )
1354+ } ;
1355+ FromSql :: from_sql ( & self . stmt . result_desc . get ( idx) . ty ,
1356+ self . data . get ( idx) )
1357+ }
1358+ }
1359+
13531360impl < ' stmt > Container for PostgresRow < ' stmt > {
13541361 #[ inline]
13551362 fn len ( & self ) -> uint {
@@ -1358,47 +1365,74 @@ impl<'stmt> Container for PostgresRow<'stmt> {
13581365}
13591366
13601367impl < ' stmt , I : RowIndex , T : FromSql > Index < I , T > for PostgresRow < ' stmt > {
1368+ /// Retreives the contents of a field of the row.
1369+ ///
1370+ /// A field can be accessed by the name or index of its column, though
1371+ /// access by index is more efficient. Rows are 1-indexed.
1372+ ///
1373+ /// # Failure
1374+ ///
1375+ /// Fails if the index does not reference a column or the return type is
1376+ /// not compatible with the Postgres type.
1377+ ///
1378+ /// # Example
1379+ ///
1380+ /// ```rust,no_run
1381+ /// # use postgres::{PostgresConnection, NoSsl};
1382+ /// # let conn = PostgresConnection::connect("", &NoSsl).unwrap();
1383+ /// # let stmt = conn.prepare("").unwrap();
1384+ /// # let mut result = stmt.query([]).unwrap();
1385+ /// # let row = result.next().unwrap();
1386+ /// let foo: i32 = row[1];
1387+ /// let bar: ~str = row["bar"];
1388+ /// ```
13611389 fn index ( & self , idx : & I ) -> T {
1362- let idx = idx. idx ( self . stmt ) ;
1363- FromSql :: from_sql ( & self . stmt . result_desc . get ( idx) . ty , self . data . get ( idx) ) . unwrap ( )
1390+ match self . get ( idx. clone ( ) ) {
1391+ Ok ( ok) => ok,
1392+ Err ( err) => fail ! ( "error retrieving row: {}" , err)
1393+ }
13641394 }
13651395}
13661396
13671397/// A trait implemented by types that can index into columns of a row.
1368- pub trait RowIndex {
1369- /// Returns the index of the appropriate column.
1370- ///
1371- /// # Failure
1372- ///
1373- /// Fails if there is no corresponding column.
1374- fn idx ( & self , stmt : & PostgresStatement ) -> uint ;
1398+ pub trait RowIndex : Clone {
1399+ /// Returns the index of the appropriate column, or `None` if no such
1400+ /// column exists.
1401+ fn idx ( & self , stmt : & PostgresStatement ) -> Option < uint > ;
13751402}
13761403
13771404impl RowIndex for uint {
13781405 #[ inline]
1379- fn idx ( & self , _stmt : & PostgresStatement ) -> uint {
1380- assert ! ( * self != 0 , "out of bounds row access" ) ;
1381- * self - 1
1406+ fn idx ( & self , stmt : & PostgresStatement ) -> Option < uint > {
1407+ let idx = * self - 1 ;
1408+ if idx >= stmt. result_desc . len ( ) {
1409+ None
1410+ } else {
1411+ Some ( idx)
1412+ }
13821413 }
13831414}
13841415
13851416// This is a convenience as the 1 in get[1] resolves to int :(
13861417impl RowIndex for int {
13871418 #[ inline]
1388- fn idx ( & self , _stmt : & PostgresStatement ) -> uint {
1389- assert ! ( * self >= 1 , "out of bounds row access" ) ;
1390- ( * self - 1 ) as uint
1419+ fn idx ( & self , stmt : & PostgresStatement ) -> Option < uint > {
1420+ if * self < 0 {
1421+ return None ;
1422+ }
1423+
1424+ ( * self as uint ) . idx ( stmt)
13911425 }
13921426}
13931427
13941428impl < ' a > RowIndex for & ' a str {
1395- fn idx ( & self , stmt : & PostgresStatement ) -> uint {
1429+ fn idx ( & self , stmt : & PostgresStatement ) -> Option < uint > {
13961430 for ( i, desc) in stmt. result_descriptions ( ) . iter ( ) . enumerate ( ) {
13971431 if desc. name . as_slice ( ) == * self {
1398- return i ;
1432+ return Some ( i ) ;
13991433 }
14001434 }
1401- fail ! ( "there is no column with name {}" , * self ) ;
1435+ None
14021436 }
14031437}
14041438
0 commit comments