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>> + ToSQL<'a, SQLiteValue<'a>>,
{
left.to_sql()
.append(SQL::raw(format!("->>'{}' = ", field)))
.append(value.to_sql())
}
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>> + ToSQL<'a, SQLiteValue<'a>>,
{
left.to_sql()
.append(SQL::raw(format!("->>'{}' != ", field)))
.append(value.to_sql())
}
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>> + ToSQL<'a, SQLiteValue<'a>>,
{
SQL::raw("json_extract(")
.append(left.to_sql())
.append(SQL::raw(format!(", '{}') = ", path)))
.append(value.to_sql())
}
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!(", '{}') IS NOT NULL", path)))
}
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!(", '{}') IS NULL", path)))
}
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>> + ToSQL<'a, SQLiteValue<'a>>,
{
SQL::raw("EXISTS(SELECT 1 FROM json_each(")
.append(left.to_sql())
.append(SQL::raw(format!(", '{}') WHERE value = ", path)))
.append(value.to_sql())
.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!(", '{}') IS NOT NULL", full_path)))
}
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>> + ToSQL<'a, SQLiteValue<'a>>,
{
SQL::raw("instr(lower(json_extract(")
.append(left.to_sql())
.append(SQL::raw(format!(", '{}')), lower(", path)))
.append(value.to_sql())
.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>> + ToSQL<'a, SQLiteValue<'a>>,
{
SQL::raw("CAST(json_extract(")
.append(left.to_sql())
.append(SQL::raw(format!(", '{}') AS NUMERIC) > ", path)))
.append(value.to_sql())
}
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)))
}