From 8044097fd252271beead0229f354eb85e77e4f4a Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Tue, 26 Sep 2017 14:30:56 +0200 Subject: [PATCH] Support for multi-word full text queries. (cherry picked from commit 5fe57aa) --- .../repo/sql/QueryInterpreter2Test.java | 34 +++++++++++++++++++ .../restriction/FullTextRestriction.java | 31 ++++++++++++++--- 2 files changed, 60 insertions(+), 5 deletions(-) diff --git a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java index 48c51d43a51..65a4a6d694e 100644 --- a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java +++ b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java @@ -3654,6 +3654,40 @@ public void test940FullTextSimple() throws Exception { } } + @Test + public void test945FullTextMulti() throws Exception { + Session session = open(); + + try { + ObjectQuery query = QueryBuilder.queryFor(UserType.class, prismContext) + .fullText("\t\nPeter\t\tMravec\t") + .build(); + + String real = getInterpretedQuery2(session, UserType.class, query); + String expected = "select\n" + + " u.oid,\n" + + " u.fullObject,\n" + + " u.stringsCount,\n" + + " u.longsCount,\n" + + " u.datesCount,\n" + + " u.referencesCount,\n" + + " u.polysCount,\n" + + " u.booleansCount\n" + + "from\n" + + " RUser u\n" + + " left join u.textInfoItems t\n" + + " left join u.textInfoItems t2\n" + + "where\n" + + " (\n" + + " t.text like :text and\n" + + " t2.text like :text2\n" + + " )"; + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + @Test public void testAdHoc100ProcessStartTimestamp() throws Exception { Session session = open(); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/FullTextRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/FullTextRestriction.java index 304d7c8cc0a..f4773519cbf 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/FullTextRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/FullTextRestriction.java @@ -25,6 +25,13 @@ import org.apache.commons.lang3.StringUtils; import org.hibernate.criterion.MatchMode; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import static java.util.stream.Collectors.toList; + /** * @author mederly */ @@ -37,16 +44,30 @@ public FullTextRestriction(InterpretationContext context, FullTextFilter filter, @Override public Condition interpret() throws QueryException { - String textInfoItemsAlias = getItemPathResolver().addTextInfoJoin(getBaseHqlEntity().getHqlPath()); - String textPath = textInfoItemsAlias + "." + RObjectTextInfo.F_TEXT; - // TODO implement multiple values if (filter.getValues().size() != 1) { throw new QueryException("FullText filter currently supports only a single string"); } String text = filter.getValues().iterator().next(); String normalized = getContext().getPrismContext().getDefaultPolyStringNormalizer().normalize(text); - normalized = StringUtils.normalizeSpace(normalized); - return getContext().getHibernateQuery().createLike(textPath, normalized, MatchMode.ANYWHERE, false); + String[] words = StringUtils.split(normalized); + if (words.length == 0) { + throw new QueryException("No words to query for using full-text search filter"); + } + List conditions = new ArrayList<>(words.length); + for (String word : words) { + conditions.add(createWordQuery(word)); + } + if (conditions.size() == 1) { + return conditions.get(0); + } else { + return getContext().getHibernateQuery().createAnd(conditions); + } } + + private Condition createWordQuery(String word) throws QueryException { + String textInfoItemsAlias = getItemPathResolver().addTextInfoJoin(getBaseHqlEntity().getHqlPath()); + String textPath = textInfoItemsAlias + "." + RObjectTextInfo.F_TEXT; + return getContext().getHibernateQuery().createLike(textPath, word, MatchMode.ANYWHERE, false); + } }