sqlitepipe 0.2.0

A simple tool for piping the output of a command into sqlite databases.
Documentation
//! Utilities for sanitizing SQL identifiers to prevent injection and syntax errors.

use std::fmt::Display;

/// A wrapper for strings that have been formatted as safe SQL identifiers (e.g., "column_name").
#[derive(Debug, PartialEq, Eq)]
pub struct SanitizedIdentifier(String);

/// Escapes double quotes within a string to make it safe for use inside a quoted SQL identifier.
pub fn sanitize_sql_string(s: &str) -> String {
    s.replace('"', "\"\"")
}

impl SanitizedIdentifier {
    /// Wraps a string in double quotes and escapes internal quotes.
    pub fn new(s: impl AsRef<str>) -> SanitizedIdentifier {
        SanitizedIdentifier(format!("\"{}\"", sanitize_sql_string(s.as_ref())))
    }

    /// Returns the internal sanitized string.
    pub fn as_str(&self) -> &str {
        &self.0
    }
}

impl AsRef<str> for SanitizedIdentifier {
    fn as_ref(&self) -> &str {
        self.as_str()
    }
}

impl Display for SanitizedIdentifier {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.as_str())
    }
}

/// A trait for types that can be converted into a [`SanitizedIdentifier`].
pub trait SqlSanitize {
    type Sanitized;

    /// Converts the type into its SQL-sanitized identifier form.
    fn to_sql_sanitized_string(&self) -> Self::Sanitized;
}

impl SqlSanitize for String {
    type Sanitized = SanitizedIdentifier;

    fn to_sql_sanitized_string(&self) -> Self::Sanitized {
        SanitizedIdentifier::new(self)
    }
}

impl SqlSanitize for &str {
    type Sanitized = SanitizedIdentifier;

    fn to_sql_sanitized_string(&self) -> Self::Sanitized {
        SanitizedIdentifier::new(self)
    }
}