qail_core/ast/cmd/
mod.rs

1use crate::ast::{
2    Action, Cage, CageKind, Condition, Distance, Expr, GroupByMode, IndexDef, Join, LockMode,
3    LogicalOp, Operator, OverridingKind, SampleMethod, SetOp, TableConstraint, Value,
4};
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
8pub struct Qail {
9    pub action: Action,
10    pub table: String,
11    pub columns: Vec<Expr>,
12    #[serde(default)]
13    pub joins: Vec<Join>,
14    pub cages: Vec<Cage>,
15    #[serde(default)]
16    pub distinct: bool,
17    #[serde(default)]
18    pub index_def: Option<IndexDef>,
19    #[serde(default)]
20    pub table_constraints: Vec<TableConstraint>,
21    #[serde(default)]
22    pub set_ops: Vec<(SetOp, Box<Qail>)>,
23    #[serde(default)]
24    pub having: Vec<Condition>,
25    #[serde(default)]
26    pub group_by_mode: GroupByMode,
27    #[serde(default)]
28    pub ctes: Vec<CTEDef>,
29    #[serde(default)]
30    pub distinct_on: Vec<Expr>,
31    #[serde(default)]
32    pub returning: Option<Vec<Expr>>,
33    #[serde(default)]
34    pub on_conflict: Option<OnConflict>,
35    #[serde(default)]
36    pub source_query: Option<Box<Qail>>,
37    #[serde(default)]
38    pub channel: Option<String>,
39    #[serde(default)]
40    pub payload: Option<String>,
41    #[serde(default)]
42    pub savepoint_name: Option<String>,
43    #[serde(default)]
44    pub from_tables: Vec<String>,
45    #[serde(default)]
46    pub using_tables: Vec<String>,
47    #[serde(default)]
48    pub lock_mode: Option<LockMode>,
49    #[serde(default)]
50    pub fetch: Option<(u64, bool)>,
51    #[serde(default)]
52    pub default_values: bool,
53    #[serde(default)]
54    pub overriding: Option<OverridingKind>,
55    #[serde(default)]
56    pub sample: Option<(SampleMethod, f64, Option<u64>)>,
57    #[serde(default)]
58    pub only_table: bool,
59    // Vector database fields (Qdrant)
60    /// Vector embedding for similarity search
61    #[serde(default)]
62    pub vector: Option<Vec<f32>>,
63    /// Minimum similarity score threshold
64    #[serde(default)]
65    pub score_threshold: Option<f32>,
66    /// Named vector field (for collections with multiple vectors)
67    #[serde(default)]
68    pub vector_name: Option<String>,
69    /// Whether to return vectors in search results
70    #[serde(default)]
71    pub with_vector: bool,
72    /// Vector dimensions (e.g., 1536)
73    #[serde(default)]
74    pub vector_size: Option<u64>,
75    /// Distance metric (Cosine, Euclid, Dot)
76    #[serde(default)]
77    pub distance: Option<Distance>,
78    /// Storage optimized for disk (mmap)
79    #[serde(default)]
80    pub on_disk: Option<bool>,
81    // PostgreSQL procedural objects
82    /// Function definition (CREATE FUNCTION)
83    #[serde(default)]
84    pub function_def: Option<crate::ast::FunctionDef>,
85    /// Trigger definition (CREATE TRIGGER)
86    #[serde(default)]
87    pub trigger_def: Option<crate::ast::TriggerDef>,
88    // Redis fields
89    /// Raw binary value for Redis SET
90    #[serde(default)]
91    pub raw_value: Option<Vec<u8>>,
92    /// TTL in seconds for Redis operations
93    #[serde(default)]
94    pub redis_ttl: Option<i64>,
95    /// SET condition (NX = only if not exists, XX = only if exists)
96    #[serde(default)]
97    pub redis_set_condition: Option<String>,
98}
99
100#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
101pub struct CTEDef {
102    pub name: String,
103    pub recursive: bool,
104    pub columns: Vec<String>,
105    pub base_query: Box<Qail>,
106    pub recursive_query: Option<Box<Qail>>,
107    pub source_table: Option<String>,
108}
109
110#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
111pub struct OnConflict {
112    pub columns: Vec<String>,
113    pub action: ConflictAction,
114}
115
116#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
117pub enum ConflictAction {
118    DoNothing,
119    DoUpdate {
120        assignments: Vec<(String, Expr)>,
121    },
122}
123
124impl Default for OnConflict {
125    fn default() -> Self {
126        Self {
127            columns: vec![],
128            action: ConflictAction::DoNothing,
129        }
130    }
131}
132
133impl Default for Qail {
134    fn default() -> Self {
135        Self {
136            action: Action::Get,
137            table: String::new(),
138            columns: vec![],
139            joins: vec![],
140            cages: vec![],
141            distinct: false,
142            index_def: None,
143            table_constraints: vec![],
144            set_ops: vec![],
145            having: vec![],
146            group_by_mode: GroupByMode::Simple,
147            ctes: vec![],
148            distinct_on: vec![],
149            returning: None,
150            on_conflict: None,
151            source_query: None,
152            channel: None,
153            payload: None,
154            savepoint_name: None,
155            from_tables: vec![],
156            using_tables: vec![],
157            lock_mode: None,
158            fetch: None,
159            default_values: false,
160            overriding: None,
161            sample: None,
162            only_table: false,
163            // Vector database fields
164            vector: None,
165            score_threshold: None,
166            vector_name: None,
167            with_vector: false,
168            vector_size: None,
169            distance: None,
170            on_disk: None,
171            // Procedural objects
172            function_def: None,
173            trigger_def: None,
174            // Redis fields
175            raw_value: None,
176            redis_ttl: None,
177            redis_set_condition: None,
178        }
179    }
180}
181
182// Submodules with builder methods
183mod advanced;
184mod constructors;
185mod cte;
186mod query;
187mod vector;
188
189// Deprecated methods kept in main module for backward compatibility
190impl Qail {
191    #[deprecated(since = "0.11.0", note = "Use .columns([...]) instead")]
192    pub fn hook(mut self, cols: &[&str]) -> Self {
193        self.columns = cols.iter().map(|c| Expr::Named(c.to_string())).collect();
194        self
195    }
196
197    #[deprecated(since = "0.11.0", note = "Use .filter(column, Operator::Eq, value) or .where_eq(column, value) instead")]
198    pub fn cage(mut self, column: &str, value: impl Into<Value>) -> Self {
199        self.cages.push(Cage {
200            kind: CageKind::Filter,
201            conditions: vec![Condition {
202                left: Expr::Named(column.to_string()),
203                op: Operator::Eq,
204                value: value.into(),
205                is_array_unnest: false,
206            }],
207            logical_op: LogicalOp::And,
208        });
209        self
210    }
211}