@@ -100,6 +100,7 @@ use error::{DnsError,
100
100
PgConnectDbError ,
101
101
PgConnectStreamError ,
102
102
PgDbError ,
103
+ PgInvalidColumn ,
103
104
PgStreamDesynchronized ,
104
105
PgStreamError ,
105
106
PgWrongParamCount ,
@@ -1332,24 +1333,30 @@ impl<'stmt> Iterator<PostgresRow<'stmt>> for PostgresResult<'stmt> {
1332
1333
}
1333
1334
1334
1335
/// 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
- /// ```
1348
1336
pub struct PostgresRow < ' stmt > {
1349
1337
priv stmt : & ' stmt PostgresStatement < ' stmt > ,
1350
1338
priv data : Vec < Option < ~[ u8 ] > >
1351
1339
}
1352
1340
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
+
1353
1360
impl < ' stmt > Container for PostgresRow < ' stmt > {
1354
1361
#[ inline]
1355
1362
fn len ( & self ) -> uint {
@@ -1358,47 +1365,74 @@ impl<'stmt> Container for PostgresRow<'stmt> {
1358
1365
}
1359
1366
1360
1367
impl < ' 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
+ /// ```
1361
1389
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
+ }
1364
1394
}
1365
1395
}
1366
1396
1367
1397
/// 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 > ;
1375
1402
}
1376
1403
1377
1404
impl RowIndex for uint {
1378
1405
#[ 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
+ }
1382
1413
}
1383
1414
}
1384
1415
1385
1416
// This is a convenience as the 1 in get[1] resolves to int :(
1386
1417
impl RowIndex for int {
1387
1418
#[ 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)
1391
1425
}
1392
1426
}
1393
1427
1394
1428
impl < ' a > RowIndex for & ' a str {
1395
- fn idx ( & self , stmt : & PostgresStatement ) -> uint {
1429
+ fn idx ( & self , stmt : & PostgresStatement ) -> Option < uint > {
1396
1430
for ( i, desc) in stmt. result_descriptions ( ) . iter ( ) . enumerate ( ) {
1397
1431
if desc. name . as_slice ( ) == * self {
1398
- return i ;
1432
+ return Some ( i ) ;
1399
1433
}
1400
1434
}
1401
- fail ! ( "there is no column with name {}" , * self ) ;
1435
+ None
1402
1436
}
1403
1437
}
1404
1438
0 commit comments