use super::QueryFragment;
use std::any::{Any, TypeId};
pub trait QueryId {
type QueryId: Any;
const HAS_STATIC_QUERY_ID: bool = true;
#[doc(hidden)]
const IS_WINDOW_FUNCTION: bool = false;
fn query_id() -> Option<TypeId> {
if Self::HAS_STATIC_QUERY_ID {
Some(TypeId::of::<Self::QueryId>())
} else {
None
}
}
}
#[doc(inline)]
pub use diesel_derives::QueryId;
impl QueryId for () {
type QueryId = ();
const HAS_STATIC_QUERY_ID: bool = true;
}
impl<T: QueryId + ?Sized> QueryId for Box<T> {
type QueryId = T::QueryId;
const HAS_STATIC_QUERY_ID: bool = T::HAS_STATIC_QUERY_ID;
const IS_WINDOW_FUNCTION: bool = T::IS_WINDOW_FUNCTION;
}
impl<T: QueryId + ?Sized> QueryId for &T {
type QueryId = T::QueryId;
const HAS_STATIC_QUERY_ID: bool = T::HAS_STATIC_QUERY_ID;
const IS_WINDOW_FUNCTION: bool = T::IS_WINDOW_FUNCTION;
}
impl<DB> QueryId for dyn QueryFragment<DB> {
type QueryId = ();
const HAS_STATIC_QUERY_ID: bool = false;
}
#[cfg(test)]
#[allow(unused_parens)] mod tests {
use std::any::TypeId;
use super::QueryId;
use crate::prelude::*;
table! {
users {
id -> Integer,
name -> VarChar,
}
}
fn query_id<T: QueryId>(_: T) -> Option<TypeId> {
T::query_id()
}
#[diesel_test_helper::test]
fn queries_with_no_dynamic_elements_have_a_static_id() {
use self::users::dsl::*;
assert!(query_id(users).is_some());
assert!(query_id(users.select(name)).is_some());
assert!(query_id(users.filter(name.eq("Sean"))).is_some());
}
#[diesel_test_helper::test]
fn queries_with_different_types_have_different_ids() {
let id1 = query_id(users::table.select(users::name));
let id2 = query_id(users::table.select(users::id));
assert_ne!(id1, id2);
}
#[diesel_test_helper::test]
fn bind_params_use_only_sql_type_for_query_id() {
use self::users::dsl::*;
let id1 = query_id(users.filter(name.eq("Sean")));
let id2 = query_id(users.filter(name.eq("Tess".to_string())));
assert_eq!(id1, id2);
}
#[diesel_test_helper::test]
#[cfg(feature = "postgres")]
fn boxed_queries_do_not_have_static_query_id() {
use crate::pg::Pg;
assert!(query_id(users::table.into_boxed::<Pg>()).is_none());
}
}