mtgjson_sdk/queries/
tokens.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 SearchTokensParams {
17 pub name: Option<String>,
18 pub set_code: Option<String>,
19 pub colors: Option<Vec<String>>,
20 pub types: Option<String>,
21 pub artist: Option<String>,
22 pub limit: Option<usize>,
23 pub offset: Option<usize>,
24}
25
26pub struct TokenQuery<'a> {
32 conn: &'a crate::connection::Connection,
33}
34
35impl<'a> TokenQuery<'a> {
36 pub fn new(conn: &'a crate::connection::Connection) -> Self {
38 Self { conn }
39 }
40
41 pub fn get_by_uuid(&self, uuid: &str) -> Result<Option<Value>> {
43 self.conn.ensure_views(&["tokens"])?;
44
45 let (sql, params) = SqlBuilder::new("tokens")
46 .where_eq("uuid", uuid)
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 get_by_uuids(&self, uuids: &[&str]) -> Result<Vec<Value>> {
56 self.conn.ensure_views(&["tokens"])?;
57
58 let (sql, params) = SqlBuilder::new("tokens")
59 .where_in("uuid", uuids)
60 .build();
61
62 let rows = self.conn.execute(&sql, ¶ms)?;
63 Ok(rows_to_values(rows))
64 }
65
66 pub fn get_by_name(&self, name: &str, set_code: Option<&str>) -> Result<Vec<Value>> {
68 self.conn.ensure_views(&["tokens"])?;
69
70 let mut qb = SqlBuilder::new("tokens");
71 qb.where_eq("name", name);
72
73 if let Some(sc) = set_code {
74 qb.where_eq("setCode", sc);
75 }
76
77 let (sql, params) = qb.build();
78 let rows = self.conn.execute(&sql, ¶ms)?;
79 Ok(rows_to_values(rows))
80 }
81
82 pub fn search(&self, params: &SearchTokensParams) -> Result<Vec<Value>> {
84 self.conn.ensure_views(&["tokens"])?;
85
86 let mut qb = SqlBuilder::new("tokens");
87
88 if let Some(ref name) = params.name {
89 if name.contains('%') {
90 qb.where_like("tokens.name", name);
91 } else {
92 qb.where_eq("tokens.name", name);
93 }
94 }
95
96 if let Some(ref sc) = params.set_code {
97 qb.where_eq("tokens.setCode", sc);
98 }
99
100 if let Some(ref colors) = params.colors {
101 for color in colors {
102 qb.where_clause(
103 "list_contains(tokens.colors, ?)",
104 &[color.as_str()],
105 );
106 }
107 }
108
109 if let Some(ref types) = params.types {
110 qb.where_like("tokens.type", &format!("%{}%", types));
111 }
112
113 if let Some(ref artist) = params.artist {
114 qb.where_like("tokens.artist", &format!("%{}%", artist));
115 }
116
117 let limit = params.limit.unwrap_or(100);
118 let offset = params.offset.unwrap_or(0);
119 qb.limit(limit);
120 qb.offset(offset);
121
122 let (sql, sql_params) = qb.build();
123 let rows = self.conn.execute(&sql, &sql_params)?;
124 Ok(rows_to_values(rows))
125 }
126
127 pub fn for_set(&self, set_code: &str) -> Result<Vec<Value>> {
129 self.conn.ensure_views(&["tokens"])?;
130
131 let (sql, params) = SqlBuilder::new("tokens")
132 .where_eq("setCode", set_code)
133 .build();
134
135 let rows = self.conn.execute(&sql, ¶ms)?;
136 Ok(rows_to_values(rows))
137 }
138
139 pub fn count(&self, filters: &HashMap<String, String>) -> Result<i64> {
141 self.conn.ensure_views(&["tokens"])?;
142
143 let mut qb = SqlBuilder::new("tokens");
144 qb.select(&["COUNT(*) AS cnt"]);
145
146 for (col, val) in filters {
147 qb.where_eq(col, val);
148 }
149
150 let (sql, params) = qb.build();
151 let rows = self.conn.execute(&sql, ¶ms)?;
152
153 let cnt = rows
154 .first()
155 .and_then(|r| r.get("cnt"))
156 .and_then(|v| v.as_i64())
157 .unwrap_or(0);
158
159 Ok(cnt)
160 }
161}
162
163fn rows_to_values(rows: Vec<HashMap<String, Value>>) -> Vec<Value> {
168 rows.into_iter()
169 .map(|r| serde_json::to_value(r).unwrap_or(Value::Null))
170 .collect()
171}