sqlitepipe 0.2.1

A simple tool for piping the output of a command into sqlite databases.
Documentation
//! Defines the structure and types for database columns used in dynamic table management.

use std::cell::OnceCell;

use crate::sanitizing::SanitizedIdentifier;

/// Represents the nature of the data stored within a column.
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum ColumnType {
    /// A standard column with a fixed, predefined value.
    Raw,
    /// A column intended to store large binary data, often sourced from a stream.
    Blob,
    /// A dynamic column where the value is populated from a specific line of input.
    Line,
}

/// A representation of a database column, including its name, type, and optional value.
#[derive(Debug)]
pub struct Column {
    /// The original, unsanitized name of the column.
    name: String,
    /// A cached, SQL-safe version of the column name.
    sanitized_name: OnceCell<SanitizedIdentifier>,
    /// The category of data this column holds.
    column_type: ColumnType,
    /// The actual data value, if applicable.
    value: Option<String>,
    /// Should this column be treated as json
    json: bool,
}

impl Column {
    /// Creates a new column of type [`ColumnType::Raw`] with a fixed key and value.
    pub fn raw_column(key: impl ToString, value: impl ToString) -> Column {
        Column {
            name: key.to_string(),
            sanitized_name: OnceCell::new(),
            column_type: ColumnType::Raw,
            value: Some(value.to_string()),
            json: false,
        }
    }

    /// Creates a new column of type [`ColumnType::Blob`] with no initial value.
    pub fn blob_column(key: impl ToString) -> Column {
        Column {
            name: key.to_string(),
            sanitized_name: OnceCell::new(),
            column_type: ColumnType::Blob,
            value: None,
            json: false,
        }
    }

    /// Creates a new column of type [`ColumnType::Line`] intended to be populated during line-by-line processing.
    pub fn line_column(key: impl ToString) -> Column {
        Column {
            name: key.to_string(),
            sanitized_name: OnceCell::new(),
            column_type: ColumnType::Line,
            value: None,
            json: false,
        }
    }

    pub fn set_json(mut self, json: bool) -> Self {
        self.json = json;
        self
    }

    /// Returns the raw value of the column.
    ///
    /// # Panics
    /// Panics if called on a column that does not have a value (e.g., Blob or Line types).
    pub fn raw_value(&self) -> &str {
        self.value
            .as_ref()
            .expect("raw_value called on non raw value")
    }

    /// Returns the column value if present, otherwise returns the provided `line`.
    pub fn value_or_line<'a>(&'a self, line: &'a str) -> &'a str {
        self.value.as_ref().map(|v| v.as_str()).unwrap_or(line)
    }

    /// Returns the optional value as a string slice.
    pub fn value(&self) -> Option<&str> {
        self.value.as_ref().map(|v| v.as_str())
    }

    /// Returns the cached, SQL-sanitized version of the column name.
    pub fn sanitized_name(&self) -> &SanitizedIdentifier {
        &self
            .sanitized_name
            .get_or_init(|| SanitizedIdentifier::new(&self.name))
    }

    /// Returns the unsanitized name of the column.
    pub fn name(&self) -> &str {
        &self.name
    }

    /// Returns the [`ColumnType`] of this column.
    pub fn column_type(&self) -> ColumnType {
        self.column_type
    }

    pub fn is_json(&self) -> bool {
        self.json
    }
}