Skip to content

Commit 4bbc24e

Browse files
authored
Add get_most_recent_search_entries_in_history_metadata method to fetch search entries (#7104)
1 parent 8b9c82d commit 4bbc24e

File tree

4 files changed

+240
-1
lines changed

4 files changed

+240
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@
1919
- fix `count_by_origin` and `count_by_form_action_origin` with punicode origins
2020

2121
### Places
22+
- `places::storage::history_metadata::get_most_recent_search_entries()` was added to fetch the most recent search entries in history metadata. ([#7104](https://github.com/mozilla/application-services/pull/7104))
2223
- `places::storage::history_metadata::delete_all_metadata_for_search()` was added to delete the search terms in history metadata. ([#7101](https://github.com/mozilla/application-services/pull/7101))
2324

24-
2525
# v146.0 (_2025-11-10_)
2626

2727
## ✨ What's New ✨

components/places/src/ffi.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,14 @@ impl PlacesConnection {
213213
self.with_conn(|conn| history_metadata::get_most_recent(conn, limit))
214214
}
215215

216+
#[handle_error(crate::Error)]
217+
pub fn get_most_recent_search_entries_in_history_metadata(
218+
&self,
219+
limit: i32,
220+
) -> ApiResult<Vec<HistoryMetadata>> {
221+
self.with_conn(|conn| history_metadata::get_most_recent_search_entries(conn, limit))
222+
}
223+
216224
#[handle_error(crate::Error)]
217225
pub fn query_history_metadata(
218226
&self,

components/places/src/places.udl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ interface PlacesConnection {
6262
[Throws=PlacesApiError]
6363
sequence<HistoryMetadata> get_most_recent_history_metadata(i32 limit);
6464

65+
[Throws=PlacesApiError]
66+
sequence<HistoryMetadata> get_most_recent_search_entries_in_history_metadata(i32 limit);
67+
6568
[Throws=PlacesApiError]
6669
sequence<SearchResult> query_autocomplete(string search, i32 limit);
6770

components/places/src/storage/history_metadata.rs

Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,13 @@ lazy_static! {
443443
LIMIT :limit",
444444
common_select_sql = COMMON_METADATA_SELECT
445445
);
446+
static ref SEARCH_QUERY_SQL: String = format!(
447+
"{common_select_sql}
448+
WHERE search_term NOT NULL
449+
ORDER BY updated_at DESC
450+
LIMIT :limit",
451+
common_select_sql = COMMON_METADATA_SELECT
452+
);
446453
static ref QUERY_SQL: String = format!(
447454
"{common_select_sql}
448455
WHERE
@@ -507,6 +514,20 @@ pub fn get_most_recent(db: &PlacesDb, limit: i32) -> Result<Vec<HistoryMetadata>
507514
)
508515
}
509516

517+
// Returns the most recent history metadata entries where search term is not null (newest first),
518+
// limited by `limit`.
519+
//
520+
// Internally this uses [`SEARCH_QUERY_SQL`], ordered by descending `updated_at`.
521+
pub fn get_most_recent_search_entries(db: &PlacesDb, limit: i32) -> Result<Vec<HistoryMetadata>> {
522+
db.query_rows_and_then_cached(
523+
SEARCH_QUERY_SQL.as_str(),
524+
rusqlite::named_params! {
525+
":limit": limit,
526+
},
527+
HistoryMetadata::from_row,
528+
)
529+
}
530+
510531
pub fn get_highlights(
511532
db: &PlacesDb,
512533
weights: HistoryHighlightWeights,
@@ -1486,6 +1507,213 @@ mod tests {
14861507
assert_eq!(most_recents[2].url, "https://example.com/1");
14871508
}
14881509

1510+
#[test]
1511+
fn test_get_most_recent_search_entries_empty() {
1512+
let conn = PlacesDb::open_in_memory(ConnectionType::ReadWrite).expect("memory db");
1513+
let rows = get_most_recent_search_entries(&conn, 5).expect("query ok");
1514+
assert!(rows.is_empty());
1515+
}
1516+
1517+
#[test]
1518+
fn test_get_most_recent_search_entries_with_limits_and_same_observation() {
1519+
let conn = PlacesDb::open_in_memory(ConnectionType::ReadWrite).expect("memory db");
1520+
1521+
note_observation!(&conn,
1522+
url "http://mozilla.org/1/",
1523+
view_time None,
1524+
search_term Some("search_term_1"),
1525+
document_type None,
1526+
referrer_url None,
1527+
title None
1528+
);
1529+
1530+
bump_clock();
1531+
1532+
note_observation!(&conn,
1533+
url "http://mozilla.org/1/",
1534+
view_time None,
1535+
search_term Some("search_term_1"),
1536+
document_type None,
1537+
referrer_url None,
1538+
title None
1539+
);
1540+
1541+
bump_clock();
1542+
1543+
note_observation!(&conn,
1544+
url "http://mozilla.org/1/",
1545+
view_time None,
1546+
search_term Some("search_term_1"),
1547+
document_type None,
1548+
referrer_url None,
1549+
title None
1550+
);
1551+
1552+
// Limiting to 1 should return the most recent entry where search is not null.
1553+
let most_recents1 = get_most_recent_search_entries(&conn, 1).expect("query ok");
1554+
assert_eq!(most_recents1.len(), 1);
1555+
assert_eq!(most_recents1[0].url, "http://mozilla.org/1/");
1556+
1557+
// Limiting to 3 should also return one entry, since we only have one unique URL.
1558+
let most_recents2 = get_most_recent_search_entries(&conn, 3).expect("query ok");
1559+
assert_eq!(most_recents2.len(), 1);
1560+
assert_eq!(most_recents2[0].url, "http://mozilla.org/1/");
1561+
1562+
// Limiting to 10 should also return one entry, since we only have one unique URL.
1563+
let most_recents3 = get_most_recent_search_entries(&conn, 10).expect("query ok");
1564+
assert_eq!(most_recents3.len(), 1);
1565+
assert_eq!(most_recents3[0].url, "http://mozilla.org/1/");
1566+
}
1567+
1568+
#[test]
1569+
fn test_get_most_recent_search_entries_with_limits_and_different_observations() {
1570+
let conn = PlacesDb::open_in_memory(ConnectionType::ReadWrite).expect("memory db");
1571+
1572+
note_observation!(&conn,
1573+
url "http://mozilla.org/1/",
1574+
view_time None,
1575+
search_term Some("search_term_1"),
1576+
document_type None,
1577+
referrer_url None,
1578+
title None
1579+
);
1580+
1581+
bump_clock();
1582+
1583+
note_observation!(&conn,
1584+
url "http://mozilla.org/2/",
1585+
view_time Some(20),
1586+
search_term None,
1587+
document_type Some(DocumentType::Regular),
1588+
referrer_url None,
1589+
title None
1590+
);
1591+
1592+
bump_clock();
1593+
1594+
note_observation!(&conn,
1595+
url "http://mozilla.org/3/",
1596+
view_time None,
1597+
search_term Some("search_term_2"),
1598+
document_type None,
1599+
referrer_url None,
1600+
title None
1601+
);
1602+
1603+
bump_clock();
1604+
1605+
note_observation!(&conn,
1606+
url "http://mozilla.org/4/",
1607+
view_time None,
1608+
search_term Some("search_term_3"),
1609+
document_type None,
1610+
referrer_url None,
1611+
title None
1612+
);
1613+
1614+
// Limiting to 1 should return the most recent entry where search is not null.
1615+
let most_recents1 = get_most_recent_search_entries(&conn, 1).expect("query ok");
1616+
assert_eq!(most_recents1.len(), 1);
1617+
assert_eq!(most_recents1[0].url, "http://mozilla.org/4/");
1618+
1619+
// Limiting to 2 should return the two most recent entries.
1620+
let most_recents2 = get_most_recent_search_entries(&conn, 2).expect("query ok");
1621+
assert_eq!(most_recents2.len(), 2);
1622+
assert_eq!(most_recents2[0].url, "http://mozilla.org/4/");
1623+
assert_eq!(most_recents2[1].url, "http://mozilla.org/3/");
1624+
1625+
// Limiting to 10 should return all three entries, in the correct order.
1626+
let most_recents3 = get_most_recent_search_entries(&conn, 10).expect("query ok");
1627+
assert_eq!(most_recents3.len(), 3);
1628+
assert_eq!(most_recents3[0].url, "http://mozilla.org/4/");
1629+
assert_eq!(most_recents3[1].url, "http://mozilla.org/3/");
1630+
assert_eq!(most_recents3[2].url, "http://mozilla.org/1/");
1631+
}
1632+
1633+
#[test]
1634+
fn test_get_most_recent_search_entries_with_negative_limit_with_same_observation() {
1635+
let conn = PlacesDb::open_in_memory(ConnectionType::ReadWrite).expect("memory db");
1636+
1637+
note_observation!(&conn,
1638+
url "http://mozilla.org/1/",
1639+
view_time None,
1640+
search_term Some("search_term_1"),
1641+
document_type None,
1642+
referrer_url None,
1643+
title None
1644+
);
1645+
1646+
bump_clock();
1647+
1648+
note_observation!(&conn,
1649+
url "http://mozilla.org/1/",
1650+
view_time None,
1651+
search_term Some("search_term_1"),
1652+
document_type None,
1653+
referrer_url None,
1654+
title None
1655+
);
1656+
1657+
bump_clock();
1658+
1659+
note_observation!(&conn,
1660+
url "http://mozilla.org/1/",
1661+
view_time None,
1662+
search_term Some("search_term_1"),
1663+
document_type None,
1664+
referrer_url None,
1665+
title None
1666+
);
1667+
1668+
// Limiting to -1 should return all entries properly ordered.
1669+
let most_recents = get_most_recent_search_entries(&conn, -1).expect("query ok");
1670+
assert_eq!(most_recents.len(), 1);
1671+
assert_eq!(most_recents[0].url, "http://mozilla.org/1/");
1672+
}
1673+
1674+
#[test]
1675+
fn test_get_most_recent_search_entries_with_negative_limit_with_different_observations() {
1676+
let conn = PlacesDb::open_in_memory(ConnectionType::ReadWrite).expect("memory db");
1677+
1678+
note_observation!(&conn,
1679+
url "http://mozilla.org/1/",
1680+
view_time None,
1681+
search_term Some("search_term_1"),
1682+
document_type None,
1683+
referrer_url None,
1684+
title None
1685+
);
1686+
1687+
bump_clock();
1688+
1689+
note_observation!(&conn,
1690+
url "http://mozilla.org/2/",
1691+
view_time None,
1692+
search_term Some("search_term_2"),
1693+
document_type None,
1694+
referrer_url None,
1695+
title None
1696+
);
1697+
1698+
bump_clock();
1699+
1700+
note_observation!(&conn,
1701+
url "http://mozilla.org/3/",
1702+
view_time None,
1703+
search_term Some("search_term_3"),
1704+
document_type None,
1705+
referrer_url None,
1706+
title None
1707+
);
1708+
1709+
// Limiting to -1 should return all entries properly ordered.
1710+
let most_recents = get_most_recent_search_entries(&conn, -1).expect("query ok");
1711+
assert_eq!(most_recents.len(), 3);
1712+
assert_eq!(most_recents[0].url, "http://mozilla.org/3/");
1713+
assert_eq!(most_recents[1].url, "http://mozilla.org/2/");
1714+
assert_eq!(most_recents[2].url, "http://mozilla.org/1/");
1715+
}
1716+
14891717
#[test]
14901718
fn test_get_highlights() {
14911719
let conn = PlacesDb::open_in_memory(ConnectionType::ReadWrite).expect("memory db");

0 commit comments

Comments
 (0)