use crate::{AsValue, QueryResult, Value, ValueOwned};
use std::{
borrow::Cow,
fmt::{self, Debug, Formatter},
iter,
sync::Arc,
vec,
};
#[derive(Default, Clone, Copy, Debug)]
pub struct RowsAffected {
pub rows_affected: Option<u64>,
pub last_affected_id: Option<i64>,
}
impl Extend<RowsAffected> for RowsAffected {
fn extend<T: IntoIterator<Item = RowsAffected>>(&mut self, iter: T) {
for elem in iter {
if self.rows_affected.is_some() || elem.rows_affected.is_some() {
self.rows_affected = Some(
self.rows_affected.unwrap_or_default() + elem.rows_affected.unwrap_or_default(),
);
}
if elem.last_affected_id.is_some() {
self.last_affected_id = elem.last_affected_id;
}
}
}
}
pub type RowLabels = Arc<[String]>;
pub type RowValues = Vec<ValueOwned>;
pub trait Row: Debug + Send + Sync {
fn labels(&self) -> &[String];
fn len(&self) -> usize;
fn value(&self, index: usize) -> Option<Cow<'_, Value<'_>>>;
fn is_empty(&self) -> bool {
self.len() == 0
}
fn get_column(&self, name: &str) -> Option<Cow<'_, Value<'_>>> {
self.labels()
.iter()
.position(|label| label == name)
.and_then(|index| self.value(index))
}
fn values(&self) -> impl Iterator<Item = Cow<'_, Value<'_>>> {
(0..self.len()).map_while(|index| self.value(index))
}
fn iter(&self) -> impl Iterator<Item = (&str, Cow<'_, Value<'_>>)> {
iter::zip(self.labels().iter().map(String::as_str), self.values())
}
fn into_values(self) -> impl Iterator<Item = ValueOwned>
where
Self: Sized,
{
let row = self;
let mut index = 0;
iter::from_fn(move || {
let value = row.value(index)?.as_value().into_owned();
index += 1;
Some(value)
})
}
fn into_owned(self) -> RowOwned
where
Self: Sized,
{
RowOwned::new(
self.labels().into(),
self.values()
.map(|value| value.into_owned().into_owned())
.collect(),
)
}
}
impl<R: Row + ?Sized> Row for &R {
#[inline(always)]
fn labels(&self) -> &[String] {
(**self).labels()
}
#[inline(always)]
fn len(&self) -> usize {
(**self).len()
}
#[inline(always)]
fn value(&self, index: usize) -> Option<Cow<'_, Value<'_>>> {
(**self).value(index)
}
#[inline(always)]
fn is_empty(&self) -> bool {
(**self).is_empty()
}
#[inline(always)]
fn get_column(&self, name: &str) -> Option<Cow<'_, Value<'_>>> {
(**self).get_column(name)
}
#[inline(always)]
fn values(&self) -> impl Iterator<Item = Cow<'_, Value<'_>>> {
(**self).values()
}
#[inline(always)]
fn iter(&self) -> impl Iterator<Item = (&str, Cow<'_, Value<'_>>)> {
(**self).iter()
}
}
#[derive(Clone, Default)]
pub struct RowOwned {
pub labels: RowLabels,
pub values: RowValues,
}
impl RowOwned {
pub fn new(labels: RowLabels, values: RowValues) -> Self {
Self {
labels,
values: values.into(),
}
}
}
impl Debug for RowOwned {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("RowOwned")
.field("labels", &self.labels)
.field("len", &self.values.len())
.finish()
}
}
impl IntoIterator for RowOwned {
type Item = ValueOwned;
type IntoIter = vec::IntoIter<ValueOwned>;
#[inline(always)]
fn into_iter(self) -> Self::IntoIter {
self.values.into_iter()
}
}
impl Row for RowOwned {
#[inline(always)]
fn labels(&self) -> &[String] {
&self.labels
}
#[inline(always)]
fn len(&self) -> usize {
self.values.len()
}
#[inline(always)]
fn value(&self, index: usize) -> Option<Cow<'_, Value<'_>>> {
self.values.get(index).map(Cow::Borrowed)
}
fn into_values(self) -> impl Iterator<Item = ValueOwned> {
self.values.into_iter()
}
#[inline(always)]
fn into_owned(self) -> RowOwned {
self
}
}
impl<R: Row> From<R> for QueryResult<R> {
fn from(value: R) -> Self {
QueryResult::Row(value)
}
}
impl<R> From<RowsAffected> for QueryResult<R> {
fn from(value: RowsAffected) -> Self {
QueryResult::Affected(value)
}
}