Skip to content

Commit f2ea6b9

Browse files
authored
store: Fix fulltextsearch space handling (#3048)
1 parent 753cee7 commit f2ea6b9

File tree

4 files changed

+32
-4
lines changed

4 files changed

+32
-4
lines changed

NEWS.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# NEWS
22

3+
## Unreleased
4+
- Gracefully handle syntax errors on fulltext search. Specifically provides information about common use case
5+
where whitespace characters were part of the terms.
6+
37
## 0.25.0
48

59
### Api Version 0.0.6

graph/src/data/query/error.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ pub enum QueryExecutionError {
7777
Panic(String),
7878
EventStreamError,
7979
FulltextQueryRequiresFilter,
80+
FulltextQueryInvalidSyntax(String),
8081
DeploymentReverted,
8182
SubgraphManifestResolveError(Arc<SubgraphManifestResolveError>),
8283
InvalidSubgraphManifest,
@@ -113,6 +114,7 @@ impl QueryExecutionError {
113114
| Unimplemented(_)
114115
| CyclicalFragment(_)
115116
| UndefinedFragment(_)
117+
| FulltextQueryInvalidSyntax(_)
116118
| FulltextQueryRequiresFilter => true,
117119
NonNullError(_, _)
118120
| ListValueError(_, _)
@@ -273,6 +275,7 @@ impl fmt::Display for QueryExecutionError {
273275
Panic(msg) => write!(f, "panic processing query: {}", msg),
274276
EventStreamError => write!(f, "error in the subscription event stream"),
275277
FulltextQueryRequiresFilter => write!(f, "fulltext search queries can only use EntityFilter::Equal"),
278+
FulltextQueryInvalidSyntax(msg) => write!(f, "Invalid fulltext search query syntax. Error: {}. Hint: Search terms with spaces need to be enclosed in single quotes", msg),
276279
TooExpensive => write!(f, "query is too expensive"),
277280
Throttled => write!(f, "service is overloaded and can not run the query right now. Please try again in a few minutes"),
278281
DeploymentReverted => write!(f, "the chain was reorganized while executing the query"),

store/postgres/src/relational.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -658,12 +658,18 @@ impl Layout {
658658
}
659659
query.load::<EntityData>(conn)
660660
})
661-
.map_err(|e| {
662-
QueryExecutionError::ResolveEntitiesError(format!(
661+
.map_err(|e| match e {
662+
diesel::result::Error::DatabaseError(
663+
diesel::result::DatabaseErrorKind::__Unknown,
664+
ref info,
665+
) if info.message().starts_with("syntax error in tsquery") => {
666+
QueryExecutionError::FulltextQueryInvalidSyntax(info.message().to_string())
667+
}
668+
_ => QueryExecutionError::ResolveEntitiesError(format!(
663669
"{}, query = {:?}",
664670
e,
665671
debug_query(&query_clone).to_string()
666-
))
672+
)),
667673
})?;
668674
log_query_timing(logger, &query_clone, start.elapsed(), values.len());
669675
values

store/postgres/tests/relational.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use graph_store_postgres::layout_for_tests::SqlName;
1313
use hex_literal::hex;
1414
use lazy_static::lazy_static;
1515
use std::borrow::Cow;
16+
use std::panic;
1617
use std::str::FromStr;
1718
use std::sync::Arc;
1819
use std::thread::sleep;
@@ -889,6 +890,7 @@ impl<'a> QueryChecker<'a> {
889890
}
890891

891892
fn check(self, expected_entity_ids: Vec<&'static str>, query: EntityQuery) -> Self {
893+
let q = query.clone();
892894
let unordered = matches!(query.order, EntityOrder::Unordered);
893895
let entities = self
894896
.layout
@@ -921,7 +923,7 @@ impl<'a> QueryChecker<'a> {
921923
expected_entity_ids.sort();
922924
}
923925

924-
assert_eq!(entity_ids, expected_entity_ids);
926+
assert_eq!(entity_ids, expected_entity_ids, "{:?}", q);
925927
self
926928
}
927929
}
@@ -965,6 +967,19 @@ impl EasyOrder for EntityQuery {
965967
}
966968
}
967969

970+
#[test]
971+
#[should_panic(
972+
expected = "layout.query failed to execute query: FulltextQueryInvalidSyntax(\"syntax error in tsquery: \\\"Jono 'a\\\"\")"
973+
)]
974+
fn check_fulltext_search_syntax_error() {
975+
run_test(move |conn, layout| {
976+
QueryChecker::new(conn, layout).check(
977+
vec!["1"],
978+
user_query().filter(EntityFilter::Equal("userSearch".into(), "Jono 'a".into())),
979+
);
980+
});
981+
}
982+
968983
#[test]
969984
fn check_find() {
970985
run_test(move |conn, layout| {

0 commit comments

Comments
 (0)