pak_db/query/
mod.rs

1#![doc = include_str!("../../docs/queries.md")]
2
3pub mod pql;
4
5use std::{ops::{BitAnd, BitOr}, rc::Rc, sync::Arc};
6use ordermap::OrderSet;
7
8use crate::{error::PakResult, pointer::PakPointer};
9use super::{value::PakValue, Pak};
10
11//==============================================================================================
12//        Pak Query
13//==============================================================================================
14
15pub trait PakQueryExpression {
16    fn execute(&self, pak : &Pak) -> PakResult<OrderSet<PakPointer>>;
17}
18
19impl PakQueryExpression for Box<dyn PakQueryExpression> {
20    fn execute(&self, pak : &Pak) -> PakResult<OrderSet<PakPointer>> {
21        self.as_ref().execute(pak)
22    }
23}
24
25impl PakQueryExpression for Rc<dyn PakQueryExpression> {
26    fn execute(&self, pak : &Pak) -> PakResult<OrderSet<PakPointer>> {
27        Rc::as_ref(&self).execute(pak)
28    }
29}
30
31impl PakQueryExpression for Arc<dyn PakQueryExpression> {
32    fn execute(&self, pak : &Pak) -> PakResult<OrderSet<PakPointer>> {
33        Arc::as_ref(&self).execute(pak)
34    }
35}
36
37impl <T> PakQueryExpression for Box<T> where T : PakQueryExpression {
38    fn execute(&self, pak : &Pak) -> PakResult<OrderSet<PakPointer>> {
39        self.as_ref().execute(pak)
40    }
41}
42
43impl <T> PakQueryExpression for Rc<T> where T : PakQueryExpression  {
44    fn execute(&self, pak : &Pak) -> PakResult<OrderSet<PakPointer>> {
45        Rc::as_ref(&self).execute(pak)
46    }
47}
48
49impl <T> PakQueryExpression for Arc<T> where T : PakQueryExpression {
50    fn execute(&self, pak : &Pak) -> PakResult<OrderSet<PakPointer>> {
51        Arc::as_ref(&self).execute(pak)
52    }
53}
54
55//==============================================================================================
56//        PakQueryUnion
57//==============================================================================================
58
59pub struct PakQueryUnion(Box<dyn PakQueryExpression>, Box<dyn PakQueryExpression>);
60
61impl PakQueryExpression for PakQueryUnion {
62    fn execute(&self, pak : &Pak) -> PakResult<OrderSet<PakPointer>> {
63        let results_a = self.0.execute(pak)?;
64        let results_b = self.1.execute(pak)?;
65        let results = results_a.into_iter().chain(results_b.into_iter()).collect::<OrderSet<_>>();
66        Ok(results)
67    }
68}
69
70impl PakQueryUnion {
71    pub fn new(first : impl PakQueryExpression + 'static, second : impl PakQueryExpression + 'static) -> Self {
72        PakQueryUnion(Box::new(first), Box::new(second))
73    } 
74}
75
76impl<B> BitOr<B> for PakQueryUnion where B : PakQueryExpression + 'static {
77    type Output = Self;
78
79    fn bitor(self, other: B) -> Self::Output {
80        PakQueryUnion(Box::new(self), Box::new(other))
81    }
82}
83
84impl <B> BitOr<B> for PakQueryIntersection where B : PakQueryExpression + 'static {
85    type Output = PakQueryUnion;
86
87    fn bitor(self, other: B) -> Self::Output {
88        PakQueryUnion(Box::new(self), Box::new(other))
89    }
90}
91
92impl <B> BitOr<B> for PakQuery where B : PakQueryExpression + 'static {
93    type Output = PakQueryUnion;
94
95    fn bitor(self, other: B) -> Self::Output {
96        PakQueryUnion(Box::new(self), Box::new(other))
97    }
98}
99
100//==============================================================================================
101//        Pak Query Intersection
102//==============================================================================================
103
104pub struct PakQueryIntersection(Box::<dyn PakQueryExpression>, Box::<dyn PakQueryExpression>);
105
106impl PakQueryIntersection {
107    pub fn new(first : impl PakQueryExpression + 'static, second : impl PakQueryExpression + 'static) -> Self {
108        PakQueryIntersection(Box::new(first), Box::new(second))
109    } 
110}
111
112impl PakQueryExpression for PakQueryIntersection {
113    fn execute(&self, pak : &Pak) -> PakResult<OrderSet<PakPointer>> {
114        let results_a = self.0.execute(pak)?;
115        let results_b = self.1.execute(pak)?;
116        Ok(results_a.into_iter().filter(|e| results_b.contains(e)).collect())
117    }
118}
119
120impl <B> BitAnd<B> for PakQuery where B : PakQueryExpression + 'static {
121    type Output = PakQueryIntersection;
122
123    fn bitand(self, rhs: B) -> Self::Output {
124        PakQueryIntersection(Box::new(self), Box::new(rhs))
125    }
126}
127
128impl <B> BitAnd<B> for PakQueryUnion where B : PakQueryExpression + 'static {
129    type Output = PakQueryIntersection;
130
131    fn bitand(self, rhs: B) -> Self::Output {
132        PakQueryIntersection(Box::new(self), Box::new(rhs))
133    }
134}
135
136impl <B> BitAnd<B> for PakQueryIntersection where B : PakQueryExpression + 'static {
137    type Output = PakQueryIntersection;
138
139    fn bitand(self, rhs: B) -> Self::Output {
140        PakQueryIntersection(Box::new(self), Box::new(rhs))
141    }
142}
143
144
145//==============================================================================================
146//        Pak Query Expression
147//==============================================================================================
148
149pub enum PakQuery {
150    Equal(String, PakValue),
151    GreaterThan(String, PakValue),
152    LessThan(String, PakValue),
153    GreaterThanEqual(String, PakValue),
154    LessThanEqual(String, PakValue),
155    Contains(String, PakValue)
156}
157
158impl PakQuery {
159    pub fn equals(key : &str, value : impl Into<PakValue>) -> Self {
160        PakQuery::Equal(key.to_string(), value.into())
161    }
162
163    pub fn greater_than(key : &str, value : impl Into<PakValue>) -> Self {
164        PakQuery::GreaterThan(key.to_string(), value.into())
165    }
166
167    pub fn less_than(key : &str, value : impl Into<PakValue>) -> Self {
168        PakQuery::LessThan(key.to_string(), value.into())
169    }
170    
171    pub fn greater_than_or_equal(key : &str, value : impl Into<PakValue>) -> Self {
172        PakQuery::GreaterThanEqual(key.to_string(), value.into())
173    }
174    
175    pub fn less_than_or_equal(key : &str, value : impl Into<PakValue>) -> Self {
176        PakQuery::LessThanEqual(key.to_string(), value.into())
177    }
178    
179    pub fn contains(key : &str, value : impl Into<PakValue>) -> Self {
180        PakQuery::Contains(key.to_string(), value.into())
181    }
182}
183
184pub fn equals(key : &str, value : impl Into<PakValue>) -> PakQuery {
185    PakQuery::Equal(key.to_string(), value.into())
186}
187
188pub fn greater_than(key : &str, value : impl Into<PakValue>) -> PakQuery {
189    PakQuery::GreaterThan(key.to_string(), value.into())
190}
191
192pub fn less_than(key : &str, value : impl Into<PakValue>) -> PakQuery {
193    PakQuery::LessThan(key.to_string(), value.into())
194}
195
196pub fn greater_than_equal(key : &str, value : impl Into<PakValue>) -> PakQuery {
197    PakQuery::GreaterThanEqual(key.to_string(), value.into())
198}
199
200pub fn less_than_equal(key : &str, value : impl Into<PakValue>) -> PakQuery {
201    PakQuery::LessThanEqual(key.to_string(), value.into())
202}
203
204impl PakQueryExpression for PakQuery {
205    fn execute(&self, pak : &Pak) -> PakResult<OrderSet<PakPointer>> {
206        match self {
207            PakQuery::Equal(key, pak_value) => {
208                let tree = pak.get_tree(key)?;
209                tree.get(pak_value)
210            },
211            PakQuery::GreaterThan(key, pak_value) => {
212                let tree = pak.get_tree(key)?;
213                tree.get_greater(pak_value)
214            },
215            PakQuery::LessThan(key, pak_value) => {
216                let tree = pak.get_tree(key)?;
217                tree.get_less(pak_value)
218            },
219            PakQuery::GreaterThanEqual(key, pak_value) => {
220                let tree = pak.get_tree(key)?;
221                tree.get_greater_eq(pak_value)
222            },
223            PakQuery::LessThanEqual(key, pak_value) => {
224                let tree = pak.get_tree(key)?;
225                tree.get_less_eq(pak_value)
226            },
227            PakQuery::Contains(key, pak_value) => {
228                let tree = pak.get_tree(key)?;
229                tree.get_contains(pak_value)
230            }
231        }
232    }
233}