use std::collections::{HashMap, HashSet};
use std::sync::{LazyLock, Mutex, PoisonError};
use ruststream_sqlx_dialect::{Param, Statement};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Stmt {
pub sql: &'static str,
pub params: &'static [Param],
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
pub struct Prepared {
pub fifo_guard: Option<Stmt>,
pub claim: Option<Stmt>,
pub fetch: Option<Stmt>,
pub ack: Option<Stmt>,
pub retry: Option<Stmt>,
pub retry_after: Option<Stmt>,
pub discard: Option<Stmt>,
pub dead_letter: Option<Stmt>,
pub dead_letter_then: Option<Stmt>,
pub extend: Option<Stmt>,
pub stamp: Option<Stmt>,
pub lock: Option<Stmt>,
pub unlock: Option<Stmt>,
pub take: Option<Stmt>,
pub take_then: Option<Stmt>,
pub stamps: bool,
pub transactional: bool,
pub begin_work: Option<&'static str>,
pub savepoint: Option<Savepoint>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Savepoint {
pub set: &'static str,
pub rollback_to: &'static str,
}
static STATEMENTS: LazyLock<Mutex<HashMap<&'static str, &'static [Param]>>> =
LazyLock::new(Mutex::default);
static NAMES: LazyLock<Mutex<HashSet<&'static str>>> = LazyLock::new(Mutex::default);
pub(crate) fn intern(statement: &Statement) -> Stmt {
let mut interned = STATEMENTS.lock().unwrap_or_else(PoisonError::into_inner);
if let Some((&sql, ¶ms)) = interned.get_key_value(statement.sql()) {
return Stmt { sql, params };
}
let sql: &'static str = Box::leak(statement.sql().into());
let params: &'static [Param] = Box::leak(statement.params().into());
interned.insert(sql, params);
drop(interned);
Stmt { sql, params }
}
pub(crate) fn intern_name(name: &str) -> &'static str {
let mut interned = NAMES.lock().unwrap_or_else(PoisonError::into_inner);
if let Some(&name) = interned.get(name) {
return name;
}
let name: &'static str = Box::leak(name.into());
interned.insert(name);
drop(interned);
name
}
impl Prepared {
pub(crate) fn statements(&self) -> impl Iterator<Item = Stmt> {
[
self.fifo_guard,
self.claim,
self.fetch,
self.ack,
self.retry,
self.retry_after,
self.discard,
self.dead_letter,
self.dead_letter_then,
self.extend,
self.stamp,
self.lock,
self.unlock,
self.take,
self.take_then,
]
.into_iter()
.flatten()
}
}