mtgjson_sdk/queries/
sets.rs1use std::collections::HashMap;
4
5use serde_json::Value;
6
7use crate::error::Result;
8use crate::sql_builder::SqlBuilder;
9
10#[derive(Debug, Clone, Default)]
16pub struct SearchSetsParams {
17 pub name: Option<String>,
18 pub set_type: Option<String>,
19 pub block: Option<String>,
20 pub release_year: Option<i32>,
21 pub limit: Option<usize>,
22 pub offset: Option<usize>,
23}
24
25pub struct SetQuery<'a> {
31 conn: &'a crate::connection::Connection,
32}
33
34impl<'a> SetQuery<'a> {
35 pub fn new(conn: &'a crate::connection::Connection) -> Self {
37 Self { conn }
38 }
39
40 pub fn get(&self, code: &str) -> Result<Option<Value>> {
42 self.conn.ensure_views(&["sets"])?;
43
44 let upper = code.to_uppercase();
45 let (sql, params) = SqlBuilder::new("sets")
46 .where_eq("code", &upper)
47 .limit(1)
48 .build();
49
50 let rows = self.conn.execute(&sql, ¶ms)?;
51 Ok(rows.into_iter().next().map(|r| serde_json::to_value(r).unwrap_or(Value::Null)))
52 }
53
54 pub fn list(
59 &self,
60 set_type: Option<&str>,
61 name: Option<&str>,
62 limit: Option<usize>,
63 offset: Option<usize>,
64 ) -> Result<Vec<Value>> {
65 self.conn.ensure_views(&["sets"])?;
66
67 let mut qb = SqlBuilder::new("sets");
68 qb.order_by(&["releaseDate DESC"]);
69
70 if let Some(st) = set_type {
71 qb.where_eq("type", st);
72 }
73
74 if let Some(n) = name {
75 qb.where_like("name", &format!("%{}%", n));
76 }
77
78 if let Some(l) = limit {
79 qb.limit(l);
80 }
81 if let Some(o) = offset {
82 qb.offset(o);
83 }
84
85 let (sql, params) = qb.build();
86 let rows = self.conn.execute(&sql, ¶ms)?;
87 Ok(rows_to_values(rows))
88 }
89
90 pub fn search(&self, params: &SearchSetsParams) -> Result<Vec<Value>> {
97 self.conn.ensure_views(&["sets"])?;
98
99 let mut qb = SqlBuilder::new("sets");
100 qb.order_by(&["releaseDate DESC"]);
101
102 if let Some(ref name) = params.name {
103 qb.where_like("name", &format!("%{}%", name));
104 }
105
106 if let Some(ref st) = params.set_type {
107 qb.where_eq("type", st);
108 }
109
110 if let Some(ref block) = params.block {
111 qb.where_eq("block", block);
112 }
113
114 if let Some(year) = params.release_year {
115 qb.where_clause(
116 "EXTRACT(YEAR FROM CAST(releaseDate AS DATE)) = ?",
117 &[&year.to_string()],
118 );
119 }
120
121 let limit = params.limit.unwrap_or(100);
122 let offset = params.offset.unwrap_or(0);
123 qb.limit(limit);
124 qb.offset(offset);
125
126 let (sql, sql_params) = qb.build();
127 let rows = self.conn.execute(&sql, &sql_params)?;
128 Ok(rows_to_values(rows))
129 }
130
131 pub fn get_financial_summary(
145 &self,
146 set_code: &str,
147 provider: Option<&str>,
148 currency: Option<&str>,
149 finish: Option<&str>,
150 price_type: Option<&str>,
151 ) -> Result<HashMap<String, Value>> {
152 self.conn.ensure_views(&["cards", "all_prices_today"])?;
153
154 let upper = set_code.to_uppercase();
155 let provider = provider.unwrap_or("tcgplayer");
156 let currency = currency.unwrap_or("USD");
157 let finish = finish.unwrap_or("normal");
158 let price_type = price_type.unwrap_or("retail");
159
160 let sql = r#"
161 SELECT
162 COUNT(DISTINCT c.uuid) AS card_count,
163 COALESCE(SUM(p.price), 0) AS total_value,
164 COALESCE(AVG(p.price), 0) AS avg_value,
165 COALESCE(MIN(p.price), 0) AS min_value,
166 COALESCE(MAX(p.price), 0) AS max_value,
167 MAX(p.date) AS date
168 FROM cards c
169 JOIN all_prices_today p ON c.uuid = p.uuid
170 WHERE c.setCode = ?
171 AND p.provider = ?
172 AND p.currency = ?
173 AND p.finish = ?
174 AND p.price_type = ?
175 "#;
176
177 let rows = self.conn.execute(
178 sql,
179 &[
180 upper,
181 provider.to_string(),
182 currency.to_string(),
183 finish.to_string(),
184 price_type.to_string(),
185 ],
186 )?;
187
188 if let Some(row) = rows.into_iter().next() {
189 Ok(row)
190 } else {
191 Ok(HashMap::new())
192 }
193 }
194
195 pub fn count(&self, set_type: Option<&str>) -> Result<i64> {
197 self.conn.ensure_views(&["sets"])?;
198
199 let mut qb = SqlBuilder::new("sets");
200 qb.select(&["COUNT(*) AS cnt"]);
201
202 if let Some(st) = set_type {
203 qb.where_eq("type", st);
204 }
205
206 let (sql, params) = qb.build();
207 let rows = self.conn.execute(&sql, ¶ms)?;
208
209 let cnt = rows
210 .first()
211 .and_then(|r| r.get("cnt"))
212 .and_then(|v| v.as_i64())
213 .unwrap_or(0);
214
215 Ok(cnt)
216 }
217}
218
219fn rows_to_values(rows: Vec<HashMap<String, Value>>) -> Vec<Value> {
224 rows.into_iter()
225 .map(|r| serde_json::to_value(r).unwrap_or(Value::Null))
226 .collect()
227}