#[cfg(not(feature = "std"))]
use crate::prelude::*;
use crate::values::SQLiteValue;
use drizzle_core::{SQL, ToSQL};
pub fn json<'a>(value: impl ToSQL<'a, SQLiteValue<'a>>) -> SQL<'a, SQLiteValue<'a>> {
SQL::func("json", value.to_sql())
}
pub fn jsonb<'a>(value: impl ToSQL<'a, SQLiteValue<'a>>) -> SQL<'a, SQLiteValue<'a>> {
SQL::func("jsonb", value.to_sql())
}
pub fn json_eq<'a, L, R>(left: L, field: &'a str, value: R) -> SQL<'a, SQLiteValue<'a>>
where
L: ToSQL<'a, SQLiteValue<'a>>,
R: Into<SQLiteValue<'a>>,
{
left.to_sql()
.append(SQL::raw(format!("->>'{field}' = ")))
.append(SQL::param(value.into()))
}
pub fn json_ne<'a, L, R>(left: L, field: &'a str, value: R) -> SQL<'a, SQLiteValue<'a>>
where
L: ToSQL<'a, SQLiteValue<'a>>,
R: Into<SQLiteValue<'a>>,
{
left.to_sql()
.append(SQL::raw(format!("->>'{field}' != ")))
.append(SQL::param(value.into()))
}
pub fn json_contains<'a, L, R>(left: L, path: &'a str, value: R) -> SQL<'a, SQLiteValue<'a>>
where
L: ToSQL<'a, SQLiteValue<'a>>,
R: Into<SQLiteValue<'a>>,
{
SQL::raw("json_extract(")
.append(left.to_sql())
.append(SQL::raw(format!(", '{path}') = ")))
.append(SQL::param(value.into()))
}
pub fn json_exists<'a, L>(left: L, path: &'a str) -> SQL<'a, SQLiteValue<'a>>
where
L: ToSQL<'a, SQLiteValue<'a>>,
{
SQL::raw("json_type(")
.append(left.to_sql())
.append(SQL::raw(format!(", '{path}') IS NOT NULL")))
}
pub fn json_not_exists<'a, L>(left: L, path: &'a str) -> SQL<'a, SQLiteValue<'a>>
where
L: ToSQL<'a, SQLiteValue<'a>>,
{
SQL::raw("json_type(")
.append(left.to_sql())
.append(SQL::raw(format!(", '{path}') IS NULL")))
}
pub fn json_array_contains<'a, L, R>(left: L, path: &'a str, value: R) -> SQL<'a, SQLiteValue<'a>>
where
L: ToSQL<'a, SQLiteValue<'a>>,
R: Into<SQLiteValue<'a>>,
{
SQL::raw("EXISTS(SELECT 1 FROM json_each(")
.append(left.to_sql())
.append(SQL::raw(format!(", '{path}') WHERE value = ")))
.append(SQL::param(value.into()))
.append(SQL::raw(")"))
}
pub fn json_object_contains_key<'a, L>(
left: L,
path: &'a str,
key: &'a str,
) -> SQL<'a, SQLiteValue<'a>>
where
L: ToSQL<'a, SQLiteValue<'a>>,
{
let full_path = if path.ends_with('$') || path.is_empty() {
format!("$.{key}")
} else {
format!("{path}.{key}")
};
SQL::raw("json_type(")
.append(left.to_sql())
.append(SQL::raw(format!(", '{full_path}') IS NOT NULL")))
}
pub fn json_text_contains<'a, L, R>(left: L, path: &'a str, value: R) -> SQL<'a, SQLiteValue<'a>>
where
L: ToSQL<'a, SQLiteValue<'a>>,
R: Into<SQLiteValue<'a>>,
{
SQL::raw("instr(lower(json_extract(")
.append(left.to_sql())
.append(SQL::raw(format!(", '{path}')), lower(")))
.append(SQL::param(value.into()))
.append(SQL::raw(")) > 0"))
}
pub fn json_gt<'a, L, R>(left: L, path: &'a str, value: R) -> SQL<'a, SQLiteValue<'a>>
where
L: ToSQL<'a, SQLiteValue<'a>>,
R: Into<SQLiteValue<'a>>,
{
SQL::raw("CAST(json_extract(")
.append(left.to_sql())
.append(SQL::raw(format!(", '{path}') AS NUMERIC) > ")))
.append(SQL::param(value.into()))
}
pub fn json_extract<'a, L>(left: L, path: impl AsRef<str>) -> SQL<'a, SQLiteValue<'a>>
where
L: ToSQL<'a, SQLiteValue<'a>>,
{
left.to_sql()
.append(SQL::raw(format!("->>'{}'", path.as_ref())))
}
pub fn json_extract_text<'a, L>(left: L, path: &'a str) -> SQL<'a, SQLiteValue<'a>>
where
L: ToSQL<'a, SQLiteValue<'a>>,
{
left.to_sql().append(SQL::raw(format!("->'{path}'")))
}