mtgjson_sdk/queries/
sealed.rs1use std::collections::HashMap;
7
8use serde_json::Value;
9
10use crate::error::Result;
11use crate::sql_builder::SqlBuilder;
12
13pub struct SealedQuery<'a> {
19 conn: &'a crate::connection::Connection,
20}
21
22impl<'a> SealedQuery<'a> {
23 pub fn new(conn: &'a crate::connection::Connection) -> Self {
25 Self { conn }
26 }
27
28 fn has_sealed_column(&self) -> bool {
30 let sql = "SELECT sealedProduct FROM sets LIMIT 0";
32 self.conn.execute(sql, &[]).is_ok()
33 }
34
35 pub fn list(
39 &self,
40 set_code: Option<&str>,
41 category: Option<&str>,
42 limit: Option<usize>,
43 ) -> Result<Vec<Value>> {
44 self.conn.ensure_views(&["sets"])?;
45
46 if !self.has_sealed_column() {
47 return Ok(Vec::new());
48 }
49
50 let mut qb = SqlBuilder::new("sets");
51 qb.select(&["code", "name", "sealedProduct"]);
52
53 if let Some(sc) = set_code {
54 let upper = sc.to_uppercase();
55 qb.where_eq("code", &upper);
56 }
57
58 qb.where_clause("sealedProduct IS NOT NULL", &[]);
60
61 let (sql, params) = qb.build();
62 let rows = self.conn.execute(&sql, ¶ms)?;
63
64 let mut results: Vec<Value> = Vec::new();
67 let limit = limit.unwrap_or(100);
68
69 for row in rows {
70 let code = row
71 .get("code")
72 .and_then(|v| v.as_str())
73 .unwrap_or("")
74 .to_string();
75 let set_name = row
76 .get("name")
77 .and_then(|v| v.as_str())
78 .unwrap_or("")
79 .to_string();
80
81 if let Some(Value::Array(products)) = row.get("sealedProduct") {
82 for product in products {
83 let mut p = product.clone();
84 if let Value::Object(ref mut map) = p {
85 if let Some(cat) = category {
87 let product_cat = map
88 .get("category")
89 .and_then(|v| v.as_str())
90 .unwrap_or("");
91 if product_cat != cat {
92 continue;
93 }
94 }
95
96 map.insert("setCode".to_string(), Value::String(code.clone()));
97 map.insert("setName".to_string(), Value::String(set_name.clone()));
98 }
99 results.push(p);
100 if results.len() >= limit {
101 return Ok(results);
102 }
103 }
104 }
105 }
106
107 Ok(results)
108 }
109
110 pub fn get(&self, uuid: &str) -> Result<Option<Value>> {
115 self.conn.ensure_views(&["sets"])?;
116
117 if !self.has_sealed_column() {
118 return Ok(None);
119 }
120
121 let rows = self.conn.execute(
123 "SELECT code, name, sealedProduct FROM sets WHERE sealedProduct IS NOT NULL",
124 &[],
125 )?;
126
127 for row in rows {
128 let code = row
129 .get("code")
130 .and_then(|v| v.as_str())
131 .unwrap_or("")
132 .to_string();
133 let set_name = row
134 .get("name")
135 .and_then(|v| v.as_str())
136 .unwrap_or("")
137 .to_string();
138
139 if let Some(Value::Array(products)) = row.get("sealedProduct") {
140 for product in products {
141 let product_uuid = product
142 .get("uuid")
143 .and_then(|v| v.as_str())
144 .unwrap_or("");
145 if product_uuid == uuid {
146 let mut p = product.clone();
147 if let Value::Object(ref mut map) = p {
148 map.insert("setCode".to_string(), Value::String(code.clone()));
149 map.insert(
150 "setName".to_string(),
151 Value::String(set_name.clone()),
152 );
153 }
154 return Ok(Some(p));
155 }
156 }
157 }
158 }
159
160 Ok(None)
161 }
162}
163
164#[allow(dead_code)]
169fn rows_to_values(rows: Vec<HashMap<String, Value>>) -> Vec<Value> {
170 rows.into_iter()
171 .map(|r| serde_json::to_value(r).unwrap_or(Value::Null))
172 .collect()
173}