nf_rated/data/
query_builder.rs1use super::ColumnFilter;
2
3const QUERY_HEAD: &str = "SELECT * FROM nf_imdb WHERE";
4const QUERY_TAIL: &str = "last_sync IS NOT NULL ORDER BY imdb_rating DESC;";
5
6pub const GENRE_COLUMN: &str = "genre";
7pub const TITLE_COLUMN: &str = "title";
8pub const CAST_COLUMN: &str = "cast";
9pub const LANGUAGE_COLUMN: &str = "language";
10pub const COUNTRY_COLUMN: &str = "country";
11pub const DIRECTOR_COLUMN: &str = "director";
12pub const PLOT_COLUMN: &str = "plot";
13
14pub enum ItemType {
15 Movie,
16 Series,
17 Both,
18}
19const MOVIE_ITEM_FILTER: &str = "\n AND type = 'movie'";
20const SHOW_ITEM_FILTER: &str = "\n AND type = 'series'";
21const BOTH_ITEM_FILTER: &str = "";
22
23fn get_item_filter(item_type: &ItemType) -> String {
24 match item_type {
25 ItemType::Movie => MOVIE_ITEM_FILTER.to_string(),
26 ItemType::Series => SHOW_ITEM_FILTER.to_string(),
27 ItemType::Both => BOTH_ITEM_FILTER.to_string(),
28 }
29}
30
31pub fn build_sorted_query(item_type: &ItemType) -> String {
32 let item_filter = get_item_filter(item_type).replace(" AND ", "");
33 let and = match item_type {
34 ItemType::Movie | ItemType::Series => "AND ",
35 ItemType::Both => "",
36 };
37 format!("{}{}\n {}{}", QUERY_HEAD, item_filter, and, QUERY_TAIL)
38}
39
40pub fn build_sorted_filtered_query(filters: Vec<ColumnFilter>, item_type: &ItemType) -> String {
41 let mut matched_before = false;
42 let resolved_filters: Vec<String> = filters
43 .iter()
44 .flat_map(|filter| {
45 let matches = filter.sql_fragments(matched_before);
46 matched_before = matched_before || matches.len() > 0;
47 matches
48 })
49 .collect();
50
51 let query_filter = resolved_filters.join("");
52 let item_filter = get_item_filter(item_type);
53
54 format!(
55 "{}{}{}\n AND {}",
56 QUERY_HEAD, query_filter, item_filter, QUERY_TAIL
57 )
58}
59
60#[cfg(test)]
61mod tests {
62 use super::*;
63 #[test]
64 fn query_genre_sci_not_adventure_drama() {
65 assert_eq!(
66 build_sorted_filtered_query(
67 vec![(GENRE_COLUMN, "sci !adventure drama").into()],
68 &ItemType::Both
69 ),
70 "SELECT * FROM nf_imdb WHERE
71 genre LIKE '%sci%'
72 AND NOT genre LIKE '%adventure%'
73 AND genre LIKE '%drama%'
74 AND last_sync IS NOT NULL ORDER BY imdb_rating DESC;"
75 )
76 }
77
78 #[test]
79 fn query_title_ship() {
80 assert_eq!(
81 build_sorted_filtered_query(vec![(TITLE_COLUMN, "ship").into()], &ItemType::Both),
82 "SELECT * FROM nf_imdb WHERE
83 title LIKE '%ship%'
84 AND last_sync IS NOT NULL ORDER BY imdb_rating DESC;"
85 )
86 }
87
88 #[test]
89 fn query_country_not_india() {
90 assert_eq!(
91 build_sorted_filtered_query(vec![(COUNTRY_COLUMN, "!india").into()], &ItemType::Both),
92 "SELECT * FROM nf_imdb WHERE
93 NOT country LIKE '%india%'
94 AND last_sync IS NOT NULL ORDER BY imdb_rating DESC;"
95 )
96 }
97
98 #[test]
99 fn query_title_ship_movies_only() {
100 assert_eq!(
101 build_sorted_filtered_query(vec![(TITLE_COLUMN, "ship").into()], &ItemType::Movie),
102 "SELECT * FROM nf_imdb WHERE
103 title LIKE '%ship%'
104 AND type = 'movie'
105 AND last_sync IS NOT NULL ORDER BY imdb_rating DESC;"
106 )
107 }
108
109 #[test]
110 fn query_title_ship_series_only() {
111 assert_eq!(
112 build_sorted_filtered_query(vec![(TITLE_COLUMN, "ship").into()], &ItemType::Series),
113 "SELECT * FROM nf_imdb WHERE
114 title LIKE '%ship%'
115 AND type = 'series'
116 AND last_sync IS NOT NULL ORDER BY imdb_rating DESC;"
117 )
118 }
119
120 #[test]
121 fn query_title_ship_genre_sci() {
122 assert_eq!(
123 build_sorted_filtered_query(
124 vec![(TITLE_COLUMN, "ship").into(), (GENRE_COLUMN, "sci").into()],
125 &ItemType::Both
126 ),
127 "SELECT * FROM nf_imdb WHERE
128 title LIKE '%ship%'
129 AND genre LIKE '%sci%'
130 AND last_sync IS NOT NULL ORDER BY imdb_rating DESC;"
131 )
132 }
133
134 #[test]
135 fn query_title_ship_genre_sci_cast_not_badactor() {
136 assert_eq!(
137 build_sorted_filtered_query(
138 vec![
139 (TITLE_COLUMN, "ship").into(),
140 (GENRE_COLUMN, "sci").into(),
141 (CAST_COLUMN, "!badactor").into(),
142 ],
143 &ItemType::Both
144 ),
145 "SELECT * FROM nf_imdb WHERE
146 title LIKE '%ship%'
147 AND genre LIKE '%sci%'
148 AND NOT `cast` LIKE '%badactor%'
149 AND last_sync IS NOT NULL ORDER BY imdb_rating DESC;"
150 )
151 }
152}