forked from
slices.network/slices
Highly ambitious ATProtocol AppView service and sdks
1//! Database query parameter types.
2//!
3//! This module contains types used for building dynamic SQL queries,
4//! including WHERE conditions, sorting, and filtering.
5
6use serde::{Deserialize, Serialize};
7use serde_json::Value;
8use std::collections::HashMap;
9
10/// Represents a single condition in a WHERE clause.
11///
12/// Supports multiple types of operations:
13/// - `eq`: Exact match (field = value)
14/// - `in_values`: Array membership (field IN (...))
15/// - `contains`: Pattern matching (field ILIKE '%value%')
16/// - `fuzzy`: Fuzzy text matching (field % value)
17/// - `gt`: Greater than (field > value)
18/// - `gte`: Greater than or equal (field >= value)
19/// - `lt`: Less than (field < value)
20/// - `lte`: Less than or equal (field <= value)
21#[derive(Debug, Clone, Serialize, Deserialize)]
22#[serde(rename_all = "camelCase")]
23pub struct WhereCondition {
24 pub eq: Option<Value>,
25 #[serde(rename = "in")]
26 pub in_values: Option<Vec<Value>>,
27 pub contains: Option<String>,
28 pub fuzzy: Option<String>,
29 pub gt: Option<Value>,
30 pub gte: Option<Value>,
31 pub lt: Option<Value>,
32 pub lte: Option<Value>,
33}
34
35/// Represents a complete WHERE clause with AND/OR conditions.
36///
37/// Supports both flat conditions (legacy) and nested and/or arrays (new).
38/// The main conditions map is combined with AND logic.
39/// The or_conditions map (if present) is combined with OR logic
40/// and the entire OR group is ANDed with the main conditions.
41///
42/// New nested format supports arbitrarily nestable and/or:
43/// ```json
44/// {
45/// "and": [
46/// {
47/// "or": [
48/// { "artist": { "contains": "pearl jam" } },
49/// { "genre": { "contains": "rock" } }
50/// ]
51/// },
52/// {
53/// "and": [
54/// { "uri": { "contains": "app.bsky" } },
55/// { "uri": { "contains": "post" } }
56/// ]
57/// },
58/// { "year": { "gte": 2000 } }
59/// ]
60/// }
61/// ```
62#[derive(Debug, Clone, Serialize, Deserialize)]
63#[serde(rename_all = "camelCase")]
64pub struct WhereClause {
65 #[serde(flatten)]
66 pub conditions: HashMap<String, WhereCondition>,
67
68 #[serde(rename = "$or")]
69 pub or_conditions: Option<HashMap<String, WhereCondition>>,
70
71 /// Nested AND conditions - array of WhereClause objects all ANDed together
72 #[serde(rename = "and", skip_serializing_if = "Option::is_none")]
73 pub and: Option<Vec<WhereClause>>,
74
75 /// Nested OR conditions - array of WhereClause objects all ORed together
76 #[serde(rename = "or", skip_serializing_if = "Option::is_none")]
77 pub or: Option<Vec<WhereClause>>,
78}
79
80/// Represents a field to sort by with direction.
81///
82/// Used for multi-field sorting in queries.
83#[derive(Debug, Clone, Serialize, Deserialize)]
84#[serde(rename_all = "camelCase")]
85pub struct SortField {
86 pub field: String,
87 pub direction: String,
88}