@@ -133,6 +133,67 @@ pub use super::wit::pg4::Connection;
133133/// ```
134134pub use super :: wit:: pg4:: RowSet ;
135135
136+ impl RowSet {
137+ /// Get all the rows for this query result
138+ pub fn rows ( & self ) -> impl Iterator < Item = Row < ' _ > > {
139+ self . rows . iter ( ) . map ( |r| Row {
140+ columns : self . columns . as_slice ( ) ,
141+ result : r,
142+ } )
143+ }
144+ }
145+
146+ /// A database row result.
147+ ///
148+ /// There are two representations of a SQLite row in the SDK. This type is useful for
149+ /// addressing elements by column name, and is obtained from the [RowSet::rows()] function.
150+ /// The [DbValue] vector representation is obtained from the [field@RowSet::rows] field, and provides
151+ /// index-based lookup or low-level access to row values via a vector.
152+ pub struct Row < ' a > {
153+ columns : & ' a [ super :: wit:: pg4:: Column ] ,
154+ result : & ' a [ DbValue ] ,
155+ }
156+
157+ impl Row < ' _ > {
158+ /// Get a value by its column name. The value is converted to the target type as per the
159+ /// conversion table shown in the module documentation.
160+ ///
161+ /// This function returns None for both no such column _and_ failed conversion. You should use
162+ /// it only if you do not need to address errors (that is, if you know that conversion should
163+ /// never fail). If your code does not know the type in advance, use the raw [field@RowSet::rows] vector
164+ /// instead of the `Row` wrapper to access the underlying [DbValue] enum: this will allow you to
165+ /// determine the type and process it accordingly.
166+ ///
167+ /// Additionally, this function performs a name lookup each time it is called. If you are iterating
168+ /// over a large number of rows, it's more efficient to use column indexes, either calculated or
169+ /// statically known from the column order in the SQL.
170+ ///
171+ /// # Examples
172+ ///
173+ /// ```no_run
174+ /// use spin_sdk::pg4::{Connection, DbValue};
175+ ///
176+ /// # fn main() -> anyhow::Result<()> {
177+ /// # let user_id = 0;
178+ /// let db = Connection::open("host=localhost user=postgres password=my_password dbname=mydb")?;
179+ /// let query_result = db.query(
180+ /// "SELECT * FROM users WHERE id = $1",
181+ /// &[user_id.into()]
182+ /// )?;
183+ /// let user_row = query_result.rows().next().unwrap();
184+ ///
185+ /// let name = user_row.get::<String>("name").unwrap();
186+ /// let age = user_row.get::<i16>("age").unwrap();
187+ /// # Ok(())
188+ /// # }
189+ /// ```
190+ pub fn get < T : Decode > ( & self , column : & str ) -> Option < T > {
191+ let i = self . columns . iter ( ) . position ( |c| c. name == column) ?;
192+ let db_value = self . result . get ( i) ?;
193+ Decode :: decode ( db_value) . ok ( )
194+ }
195+ }
196+
136197#[ doc( inline) ]
137198pub use super :: wit:: pg4:: { Error as PgError , * } ;
138199
0 commit comments