use std::fmt;
use std::cell::Cell;
use std::borrow::Cow;
use crate::Result;
use crate::ErrorLevel;
use crate::row::Row;
use crate::wrapstring::{WrapString, IntoWrapString};
use crate::value::Value;
#[allow(clippy::type_complexity)]
pub(crate) trait ConcatsqlConn {
fn execute_inner<'a>(&self, query: Cow<'a, str>, params: &[Value<'a>], error_level: &crate::ErrorLevel) -> Result<()>;
fn iterate_inner<'a>(&self, query: Cow<'a, str>, params: &[Value<'a>], error_level: &crate::ErrorLevel,
callback: &mut dyn FnMut(&[(&str, Option<&str>)]) -> bool) -> Result<()>;
fn rows_inner<'a, 'r>(&self, query: Cow<'a, str>, params: &[Value<'a>], error_level: &crate::ErrorLevel)
-> Result<Vec<Row<'r>>>;
fn close(&self);
fn kind(&self) -> ConnKind;
}
#[doc(hidden)]
pub enum ConnKind {
#[cfg(feature = "sqlite")] SQLite,
#[cfg(feature = "mysql")] MySQL,
#[cfg(feature = "postgres")] PostgreSQL,
}
pub struct Connection {
pub(crate) conn: Box<dyn ConcatsqlConn>,
pub(crate) error_level: Cell<ErrorLevel>,
}
unsafe impl Send for Connection {}
unsafe impl Sync for Connection {}
impl PartialEq for Connection {
fn eq(&self, other: &Self) -> bool {
std::ptr::eq(&self.conn, &other.conn)
}
}
impl fmt::Debug for Connection {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Connection")
.field("conn", &(&self.conn as *const _))
.field("error_level", &self.error_level.get())
.finish()
}
}
impl<'a> Connection {
#[inline]
pub fn execute<T: IntoWrapString<'a>>(&self, query: T) -> Result<()> {
self.conn.execute_inner(query.compile(self.conn.kind()), query.params(), &self.error_level.get())
}
#[inline]
pub fn iterate<T: IntoWrapString<'a>, F>(&self, query: T, mut callback: F) -> Result<()>
where
F: FnMut(&[(&str, Option<&str>)]) -> bool,
{
self.conn.iterate_inner(query.compile(self.conn.kind()), query.params(), &self.error_level.get(), &mut callback)
}
#[inline]
pub fn rows<'r, T: IntoWrapString<'a>>(&self, query: T) -> Result<Vec<Row<'r>>> {
self.conn.rows_inner(query.compile(self.conn.kind()), query.params(), &self.error_level.get())
}
pub fn error_level(&self, level: ErrorLevel) {
self.error_level.set(level);
}
}
impl Drop for Connection {
fn drop(&mut self) {
self.conn.close();
}
}
pub unsafe fn without_escape<T: ?Sized + ToString>(query: &T) -> WrapString {
WrapString::new(query)
}