use std::sync::Arc; use bytes::Bytes; use sqlx_core::{ColumnIndex, Result, Row, TypeDecode}; use crate::protocol::backend::DataRow; use crate::{PgColumn, PgRawValue, Postgres}; /// A single result row from a query in PostgreSQL. #[allow(clippy::module_name_repetitions)] pub struct PgRow { values: Vec>, columns: Arc<[PgColumn]>, } impl PgRow { pub(crate) fn new(data: DataRow, columns: &Option>) -> Self { Self { values: data.values, columns: columns.as_ref().map(Arc::clone).unwrap_or_else(|| Arc::new([])), } } /// Returns `true` if the row contains only `NULL` values. pub fn is_null(&self) -> bool { self.values.iter().all(Option::is_some) } /// Returns the number of columns in the row. #[must_use] pub fn len(&self) -> usize { self.values.len() } /// Returns `true` if there are no columns in the row. #[must_use] pub fn is_empty(&self) -> bool { self.len() == 0 } /// Returns a reference to the columns in the row. #[must_use] pub fn columns(&self) -> &[PgColumn] { &self.columns } /// Returns the column at the index, if available. pub fn column>(&self, index: I) -> &PgColumn { Row::column(self, index) } /// Returns the column at the index, if available. pub fn try_column>(&self, index: I) -> Result<&PgColumn> { Ok(&self.columns[index.get(self)?]) } /// Returns the decoded value at the index. pub fn get<'r, T, I>(&'r self, index: I) -> T where I: ColumnIndex, T: TypeDecode<'r, Postgres>, { Row::get(self, index) } /// Returns the decoded value at the index. pub fn try_get<'r, T, I>(&'r self, index: I) -> Result where I: ColumnIndex, T: TypeDecode<'r, Postgres>, { Row::try_get(self, index) } /// Returns the raw representation of the value at the index. #[allow(clippy::needless_lifetimes)] pub fn get_raw<'r, I>(&'r self, index: I) -> PgRawValue<'r> where I: ColumnIndex, { Row::get_raw(self, index) } /// Returns the raw representation of the value at the index. #[allow(clippy::needless_lifetimes)] pub fn try_get_raw<'r, I>(&'r self, index: I) -> Result> where I: ColumnIndex, { let index = index.get(self)?; let value = &self.values[index]; let column = &self.columns[index]; Ok(PgRawValue::new(value, column.format, column.type_info)) } } impl Row for PgRow { type Database = Postgres; fn is_null(&self) -> bool { self.is_null() } fn len(&self) -> usize { self.len() } fn columns(&self) -> &[PgColumn] { self.columns() } fn try_column>(&self, index: I) -> Result<&PgColumn> { self.try_column(index) } fn column_name(&self, index: usize) -> Option<&str> { self.columns.get(index).map(PgColumn::name) } fn column_index(&self, name: &str) -> Option { self.columns.iter().position(|col| col.name() == name) } #[allow(clippy::needless_lifetimes)] fn try_get_raw<'r, I: ColumnIndex>(&'r self, index: I) -> Result> { self.try_get_raw(index) } }