use std::sync::Arc;
use crate::query::row::{FieldDescription, Row};
#[derive(Debug, Clone, PartialEq, Eq, Default)]
#[non_exhaustive]
pub struct CommandTag {
tag: String,
}
impl CommandTag {
pub fn new(tag: String) -> Self {
Self { tag }
}
pub fn as_str(&self) -> &str {
&self.tag
}
pub fn rows_affected(&self) -> Option<u64> {
let parts: Vec<&str> = self.tag.split_whitespace().collect();
match parts.as_slice() {
["INSERT", _, n] => n.parse().ok(),
["UPDATE", n] => n.parse().ok(),
["DELETE", n] => n.parse().ok(),
["SELECT", n] => n.parse().ok(),
["MOVE", n] => n.parse().ok(),
["FETCH", n] => n.parse().ok(),
["COPY", n] => n.parse().ok(),
_ => None,
}
}
}
#[derive(Debug, Clone)]
#[non_exhaustive]
pub struct QueryResult {
rows: Vec<Row>,
command_tag: CommandTag,
columns: Arc<Vec<FieldDescription>>,
}
impl QueryResult {
pub(crate) fn new(
rows: Vec<Row>,
command_tag: CommandTag,
columns: Arc<Vec<FieldDescription>>,
) -> Self {
Self {
rows,
command_tag,
columns,
}
}
pub fn len(&self) -> usize {
self.rows.len()
}
pub fn is_empty(&self) -> bool {
self.rows.is_empty()
}
pub fn rows(&self) -> &[Row] {
&self.rows
}
pub fn into_rows(self) -> Vec<Row> {
self.rows
}
pub fn command_tag(&self) -> &CommandTag {
&self.command_tag
}
pub fn columns(&self) -> &[FieldDescription] {
&self.columns
}
pub fn rows_affected(&self) -> Option<u64> {
self.command_tag.rows_affected()
}
pub fn iter(&self) -> impl Iterator<Item = &Row> {
self.rows.iter()
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub struct ExecuteResult {
command_tag: CommandTag,
}
impl ExecuteResult {
pub(crate) fn new(command_tag: CommandTag) -> Self {
Self { command_tag }
}
pub fn command_tag(&self) -> &CommandTag {
&self.command_tag
}
pub fn rows_affected(&self) -> Option<u64> {
self.command_tag.rows_affected()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_command_tag_rows_affected() {
assert_eq!(CommandTag::new("SELECT 3".into()).rows_affected(), Some(3));
assert_eq!(
CommandTag::new("INSERT 0 1".into()).rows_affected(),
Some(1)
);
assert_eq!(CommandTag::new("UPDATE 4".into()).rows_affected(), Some(4));
assert_eq!(CommandTag::new("DELETE 0".into()).rows_affected(), Some(0));
assert_eq!(CommandTag::new("CREATE TABLE".into()).rows_affected(), None);
assert_eq!(CommandTag::new("".into()).rows_affected(), None);
}
#[test]
fn test_query_result_empty() {
let qr = QueryResult::new(
Vec::new(),
CommandTag::new("SELECT 0".into()),
Arc::new(Vec::new()),
);
assert!(qr.is_empty());
assert_eq!(qr.len(), 0);
assert_eq!(qr.rows_affected(), Some(0));
}
#[test]
fn test_execute_result_rows_affected() {
let er = ExecuteResult::new(CommandTag::new("UPDATE 5".into()));
assert_eq!(er.rows_affected(), Some(5));
}
}