From 80dc1d236c68bb43c4673491d8fb2ea45b22c1be Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Sun, 22 Mar 2015 12:11:13 +1100 Subject: [PATCH] Normalise keywords to lowercase when searching for crates. Currently keyword search is case-sensitive, but this is often unhelpful, as they are heuristic classification tools, not hard guarantees. It's not particularly helpful to search for ["fft"](https://crates.io/keywords/fft) and not get the crates tagged ["FFT"](https://crates.io/keywords/FFT). Closes #100. --- src/bin/migrate.rs | 8 ++++++++ src/krate.rs | 2 +- src/tests/krate.rs | 10 +++++++--- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/bin/migrate.rs b/src/bin/migrate.rs index e1d2789b96b..f783d9984ef 100644 --- a/src/bin/migrate.rs +++ b/src/bin/migrate.rs @@ -440,6 +440,14 @@ fn migrations() -> Vec { ON crates (lower(name))", &[])); Ok(()) }), + Migration::new(20150320174400, |tx| { + try!(tx.execute("CREATE INDEX index_keywords_lower_keyword ON keywords (lower(keyword))", + &[])); + Ok(()) + }, |tx| { + try!(tx.execute("DROP INDEX index_keywords_lower_keyword", &[])); + Ok(()) + }), ]; // NOTE: Generate a new id via `date +"%Y%m%d%H%M%S"` diff --git a/src/krate.rs b/src/krate.rs index 903c2de5053..b5afa1157e1 100644 --- a/src/krate.rs +++ b/src/krate.rs @@ -463,7 +463,7 @@ pub fn index(req: &mut Request) -> CargoResult { ON crates.id = crates_keywords.crate_id INNER JOIN keywords ON crates_keywords.keyword_id = keywords.id - WHERE keywords.keyword = $1"; + WHERE lower(keywords.keyword) = lower($1)"; (format!("SELECT crates.* {} {} LIMIT $2 OFFSET $3", base, sort_sql), format!("SELECT COUNT(crates.*) {}", base)) }) diff --git a/src/tests/krate.rs b/src/tests/krate.rs index 18867770fd6..c56d67c2106 100644 --- a/src/tests/krate.rs +++ b/src/tests/krate.rs @@ -68,7 +68,9 @@ fn index_queries() { krate.readme = Some("readme".to_string()); krate.description = Some("description".to_string()); ::mock_crate(&mut req, krate); - ::mock_crate(&mut req, ::krate("BAR")); + let mut krate2 = ::krate("BAR"); + krate2.keywords.push("KW1".to_string()); + ::mock_crate(&mut req, krate2); let mut response = ok_resp!(middle.call(req.with_query("q=baz"))); assert_eq!(::json::(&mut response).meta.total, 0); @@ -77,7 +79,7 @@ fn index_queries() { let mut response = ok_resp!(middle.call(req.with_query("q=foo"))); assert_eq!(::json::(&mut response).meta.total, 1); let mut response = ok_resp!(middle.call(req.with_query("q=kw1"))); - assert_eq!(::json::(&mut response).meta.total, 1); + assert_eq!(::json::(&mut response).meta.total, 2); let mut response = ok_resp!(middle.call(req.with_query("q=readme"))); assert_eq!(::json::(&mut response).meta.total, 1); let mut response = ok_resp!(middle.call(req.with_query("q=description"))); @@ -99,7 +101,9 @@ fn index_queries() { assert_eq!(::json::(&mut response).crates.len(), 0); let mut response = ok_resp!(middle.call(req.with_query("keyword=kw1"))); - assert_eq!(::json::(&mut response).crates.len(), 1); + assert_eq!(::json::(&mut response).crates.len(), 2); + let mut response = ok_resp!(middle.call(req.with_query("keyword=KW1"))); + assert_eq!(::json::(&mut response).crates.len(), 2); let mut response = ok_resp!(middle.call(req.with_query("keyword=kw2"))); assert_eq!(::json::(&mut response).crates.len(), 0); }