real_time_sqlx/queries/
serialize.rs

1//! Deserialize database queries from JSON
2
3use serde::{Deserialize, Serialize};
4use serde_json::Number;
5
6use crate::error::DeserializeError;
7
8/// Query final constraint value (ie "native" types)
9/// Prevents recursive lists of values
10#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
11#[serde(untagged)]
12pub enum FinalType {
13    Number(Number),
14    String(String),
15    Bool(bool),
16    Null,
17}
18
19/// For binding values to queries, JSON values must be converted to native types
20/// in order to avoid cases such as double quotes enclosed strings.
21impl TryFrom<serde_json::Value> for FinalType {
22    type Error = DeserializeError;
23
24    fn try_from(value: serde_json::Value) -> Result<Self, Self::Error> {
25        match value {
26            serde_json::Value::Number(n) => Ok(FinalType::Number(n)),
27            serde_json::Value::String(s) => Ok(FinalType::String(s)),
28            serde_json::Value::Bool(b) => Ok(FinalType::Bool(b)),
29            serde_json::Value::Null => Ok(FinalType::Null),
30            value => Err(DeserializeError::IncompatibleValue(value)),
31        }
32    }
33}
34
35/// Query constraint value
36#[derive(Debug, Clone, Serialize, Deserialize)]
37#[serde(untagged)]
38pub enum ConstraintValue {
39    Final(FinalType),
40    List(Vec<FinalType>),
41}
42
43/// Constraint operator
44#[derive(Debug, Clone, Serialize, Deserialize)]
45pub enum Operator {
46    #[serde(rename = "=")]
47    Equal,
48    #[serde(rename = "<")]
49    LessThan,
50    #[serde(rename = ">")]
51    GreaterThan,
52    #[serde(rename = "<=")]
53    LessThanOrEqual,
54    #[serde(rename = ">=")]
55    GreaterThanOrEqual,
56    #[serde(rename = "!=")]
57    NotEqual,
58    #[serde(rename = "in")]
59    In,
60    #[serde(rename = "like")]
61    Like,
62    #[serde(rename = "ilike")]
63    ILike,
64}
65
66/// Query constraint
67#[derive(Debug, Clone, Serialize, Deserialize)]
68pub struct Constraint {
69    pub column: String,
70    pub operator: Operator,
71    pub value: ConstraintValue,
72}
73
74/// Query condition (contains constraints)
75#[derive(Debug, Clone, Serialize, Deserialize)]
76#[serde(tag = "type")]
77pub enum Condition {
78    #[serde(rename = "and")]
79    And { conditions: Vec<Condition> },
80    #[serde(rename = "or")]
81    Or { conditions: Vec<Condition> },
82    #[serde(rename = "single")]
83    Single { constraint: Constraint },
84}
85
86/// Query return type (single row vs multiple rows)
87#[derive(Debug, Clone, Serialize, Deserialize)]
88pub enum ReturnType {
89    #[serde(rename = "single")]
90    Single,
91    #[serde(rename = "many")]
92    Many,
93}
94
95/// Column and order for sorting
96#[derive(Debug, Clone, Serialize, Deserialize)]
97#[serde(tag = "order", content = "column")]
98pub enum OrderBy {
99    #[serde(rename = "asc")]
100    Asc(String),
101    #[serde(rename = "desc")]
102    Desc(String),
103}
104
105/// Pagination options
106#[derive(Debug, Clone, Serialize, Deserialize)]
107pub struct PaginateOptions {
108    #[serde(rename = "perPage")]
109    pub per_page: u64,
110    pub offset: Option<u64>,
111    #[serde(rename = "orderBy")]
112    pub order_by: Option<OrderBy>,
113}
114
115/// Final serialized query tree
116#[derive(Debug, Clone, Serialize, Deserialize)]
117pub struct QueryTree {
118    #[serde(rename = "return")]
119    pub return_type: ReturnType,
120    pub table: String,
121    pub condition: Option<Condition>,
122    pub paginate: Option<PaginateOptions>,
123}
124
125/// Returned query data
126#[derive(Debug, Clone, Serialize, Deserialize)]
127#[serde(tag = "type", content = "data")]
128pub enum QueryData<D> {
129    #[serde(rename = "single")]
130    Single(Option<D>),
131    #[serde(rename = "many")]
132    Many(Vec<D>),
133}
134
135/// Helper implementations for unwrapping query data
136impl<D> QueryData<D> {
137    pub fn unwrap_single(self) -> D {
138        match self {
139            QueryData::Single(Some(data)) => data,
140            QueryData::Single(None) => panic!("No data found"),
141            QueryData::Many(_) => panic!("Expected single row, found multiple rows"),
142        }
143    }
144
145    pub fn unwrap_optional_single(self) -> Option<D> {
146        match self {
147            QueryData::Single(data) => data,
148            QueryData::Many(_) => panic!("Expected single row, found multiple rows"),
149        }
150    }
151
152    pub fn unwrap_many(self) -> Vec<D> {
153        match self {
154            QueryData::Single(_) => panic!("Expected multiple rows, found single row"),
155            QueryData::Many(data) => data,
156        }
157    }
158}