#[cfg(not(feature = "std"))]
use crate::prelude::*;
use crate::values::PostgresValue;
use drizzle_core::ToSQL;
use drizzle_core::expr::{AggregateKind, Expr, ExprSources, NonNull, SQLExpr, Scalar};
use drizzle_core::scope::Arg;
use drizzle_core::sql::{SQL, SQLChunk};
use drizzle_types::postgres::types::{Any, Boolean};
use drizzle_types::{Array, Compatible, DataType, Placeholder};
#[diagnostic::on_unimplemented(
message = "PostgreSQL array operators cannot combine `{Self}` with `{Rhs}`",
label = "both operands must be arrays with compatible element types",
note = "pass a bound array with `PgArray(vec![...])`; a bare value is not an array"
)]
pub trait ArrayOperand<Rhs> {}
impl<T: DataType, U: DataType> ArrayOperand<Array<U>> for Array<T> where T: Compatible<U> {}
impl<T: DataType> ArrayOperand<Any> for Array<T> {}
impl<T: DataType> ArrayOperand<Placeholder> for Array<T> {}
impl<R> ArrayOperand<R> for Any {}
pub struct PgArray<T>(pub Vec<T>);
impl<'a, T> ToSQL<'a, PostgresValue<'a>> for PgArray<T>
where
T: Into<PostgresValue<'a>> + Clone,
{
fn to_sql(&self) -> SQL<'a, PostgresValue<'a>> {
let array: Vec<PostgresValue<'a>> = self.0.iter().map(|v| v.clone().into()).collect();
SQL::param(PostgresValue::Array(array))
}
}
impl<T> ExprSources for PgArray<T> {
type Sources = ();
}
impl<'a, T> Expr<'a, PostgresValue<'a>> for PgArray<T>
where
T: Expr<'a, PostgresValue<'a>> + Into<PostgresValue<'a>> + Clone,
{
type SQLType = Array<T::SQLType>;
type Nullable = NonNull;
type Aggregate = Scalar;
}
#[allow(clippy::type_complexity)]
pub fn array_contains<'a, L, R>(
left: L,
right: R,
) -> SQLExpr<
'a,
PostgresValue<'a>,
Boolean,
NonNull,
<L::Aggregate as AggregateKind>::Or<R::Aggregate>,
(Arg<L::Nullable, L::Sources>, Arg<R::Nullable, R::Sources>),
>
where
L: Expr<'a, PostgresValue<'a>>,
R: Expr<'a, PostgresValue<'a>>,
L::SQLType: ArrayOperand<R::SQLType>,
{
SQLExpr::new(
left.to_sql()
.push(SQLChunk::Raw("@>".into()))
.append(right.to_sql()),
)
}
#[allow(clippy::type_complexity)]
pub fn array_contained<'a, L, R>(
left: L,
right: R,
) -> SQLExpr<
'a,
PostgresValue<'a>,
Boolean,
NonNull,
<L::Aggregate as AggregateKind>::Or<R::Aggregate>,
(Arg<L::Nullable, L::Sources>, Arg<R::Nullable, R::Sources>),
>
where
L: Expr<'a, PostgresValue<'a>>,
R: Expr<'a, PostgresValue<'a>>,
L::SQLType: ArrayOperand<R::SQLType>,
{
SQLExpr::new(
left.to_sql()
.push(SQLChunk::Raw("<@".into()))
.append(right.to_sql()),
)
}
#[allow(clippy::type_complexity)]
pub fn array_overlaps<'a, L, R>(
left: L,
right: R,
) -> SQLExpr<
'a,
PostgresValue<'a>,
Boolean,
NonNull,
<L::Aggregate as AggregateKind>::Or<R::Aggregate>,
(Arg<L::Nullable, L::Sources>, Arg<R::Nullable, R::Sources>),
>
where
L: Expr<'a, PostgresValue<'a>>,
R: Expr<'a, PostgresValue<'a>>,
L::SQLType: ArrayOperand<R::SQLType>,
{
SQLExpr::new(
left.to_sql()
.push(SQLChunk::Raw("&&".into()))
.append(right.to_sql()),
)
}
pub trait ArrayExprExt<'a>: Expr<'a, PostgresValue<'a>> + Sized {
#[allow(clippy::type_complexity)]
fn array_contains<R>(
self,
other: R,
) -> SQLExpr<
'a,
PostgresValue<'a>,
Boolean,
NonNull,
<Self::Aggregate as AggregateKind>::Or<R::Aggregate>,
(
Arg<Self::Nullable, Self::Sources>,
Arg<R::Nullable, R::Sources>,
),
>
where
R: Expr<'a, PostgresValue<'a>>,
Self::SQLType: ArrayOperand<R::SQLType>,
{
array_contains(self, other)
}
#[allow(clippy::type_complexity)]
fn array_contained<R>(
self,
other: R,
) -> SQLExpr<
'a,
PostgresValue<'a>,
Boolean,
NonNull,
<Self::Aggregate as AggregateKind>::Or<R::Aggregate>,
(
Arg<Self::Nullable, Self::Sources>,
Arg<R::Nullable, R::Sources>,
),
>
where
R: Expr<'a, PostgresValue<'a>>,
Self::SQLType: ArrayOperand<R::SQLType>,
{
array_contained(self, other)
}
#[allow(clippy::type_complexity)]
fn array_overlaps<R>(
self,
other: R,
) -> SQLExpr<
'a,
PostgresValue<'a>,
Boolean,
NonNull,
<Self::Aggregate as AggregateKind>::Or<R::Aggregate>,
(
Arg<Self::Nullable, Self::Sources>,
Arg<R::Nullable, R::Sources>,
),
>
where
R: Expr<'a, PostgresValue<'a>>,
Self::SQLType: ArrayOperand<R::SQLType>,
{
array_overlaps(self, other)
}
}
impl<'a, E: Expr<'a, PostgresValue<'a>>> ArrayExprExt<'a> for E {}