diff --git a/data-store/src/main/java/org/lucares/pdb/datastore/internal/QueryCompletionIndex.java b/data-store/src/main/java/org/lucares/pdb/datastore/internal/QueryCompletionIndex.java index dad5bc0..c3bba05 100644 --- a/data-store/src/main/java/org/lucares/pdb/datastore/internal/QueryCompletionIndex.java +++ b/data-store/src/main/java/org/lucares/pdb/datastore/internal/QueryCompletionIndex.java @@ -5,6 +5,7 @@ import java.nio.file.Path; import java.util.List; import java.util.SortedSet; import java.util.TreeSet; +import java.util.concurrent.atomic.AtomicBoolean; import org.lucares.collections.LongList; import org.lucares.pdb.api.DateTimeRange; @@ -250,6 +251,8 @@ public class QueryCompletionIndex implements AutoCloseable { public SortedSet find(final DateTimeRange dateRange, final String property, final String value, final String field) { final Tag tag = new Tag(property, value); + Preconditions.checkGreaterOrEqual(tag.getKey(), 0, "The property '{0}' is unkown", property); + Preconditions.checkGreaterOrEqual(tag.getValue(), 0, "The value '{0}' is unkown", value); return find(dateRange, tag, field); } @@ -310,4 +313,15 @@ public class QueryCompletionIndex implements AutoCloseable { }); return result; } + + public boolean hasField(final DateTimeRange dateRange, final String field) { + final AtomicBoolean found = new AtomicBoolean(false); + final PartitionIdSource partitionIdSource = new DatePartitioner(dateRange); + fieldIndex.visitValues(partitionIdSource, "", (k, v) -> { + if (k.equals(field)) { + found.set(true); + } + }); + return found.get(); + } } diff --git a/data-store/src/main/java/org/lucares/pdb/datastore/lang/FindValuesForQueryCompletion.java b/data-store/src/main/java/org/lucares/pdb/datastore/lang/FindValuesForQueryCompletion.java index 098d880..be45a12 100644 --- a/data-store/src/main/java/org/lucares/pdb/datastore/lang/FindValuesForQueryCompletion.java +++ b/data-store/src/main/java/org/lucares/pdb/datastore/lang/FindValuesForQueryCompletion.java @@ -42,10 +42,22 @@ public class FindValuesForQueryCompletion extends ExpressionVisitor visit(final Property property) { final long start = System.nanoTime(); + final TreeSet result = new TreeSet<>(); + final String fieldA = property.getProperty(); final String valueA = property.getValue().getValue(); - final SortedSet result = index.find(dateTimeRange, fieldA, valueA, field); + final boolean hasField = index.hasField(dateTimeRange, fieldA); + if (hasField) { + final SortedSet allValuesForField = index.findAllValuesForField(dateTimeRange, fieldA); + final SortedSet valuesA = GloblikePattern.filterValues(allValuesForField, valueA, TreeSet::new); + + for (final String v : valuesA) { + final SortedSet tmp = index.find(dateTimeRange, fieldA, v, field); + result.addAll(tmp); + } + } + METRIC_AND_CARET_LOGGER.debug("{}: {}ms", property, (System.nanoTime() - start) / 1_000_000.0); return result; } diff --git a/data-store/src/main/java/org/lucares/pdb/datastore/lang/GloblikePattern.java b/data-store/src/main/java/org/lucares/pdb/datastore/lang/GloblikePattern.java index c75c377..72a9321 100644 --- a/data-store/src/main/java/org/lucares/pdb/datastore/lang/GloblikePattern.java +++ b/data-store/src/main/java/org/lucares/pdb/datastore/lang/GloblikePattern.java @@ -12,6 +12,10 @@ public class GloblikePattern { private static final Logger LOGGER = LoggerFactory.getLogger(GloblikePattern.class); + enum FilterMode { + KEEP_EQUAL + } + static Pattern globlikeToRegex(final String globPattern) { // a character that cannot be in the globPattern final String dotPlaceholder = "\ue003"; // fourth character in the private use area @@ -43,7 +47,7 @@ public class GloblikePattern { for (final String value : availableValues) { final Matcher matcher = pattern.matcher(value); - if (matcher.find() && !value.equals(valuePattern)) { + if (matcher.find()) { result.add(value); } } diff --git a/data-store/src/main/java/org/lucares/pdb/datastore/lang/NewProposerParser.java b/data-store/src/main/java/org/lucares/pdb/datastore/lang/NewProposerParser.java index 799296c..203ff0c 100644 --- a/data-store/src/main/java/org/lucares/pdb/datastore/lang/NewProposerParser.java +++ b/data-store/src/main/java/org/lucares/pdb/datastore/lang/NewProposerParser.java @@ -170,8 +170,7 @@ public class NewProposerParser implements QueryConstants { final SortedSet candidateValuesCutAtDots = cutAtDots(candidateValues, queryWithCaretMarker); // translate the candidate values to proposals - final List proposals = generateProposals(queryWithCaretMarker, expression, - candidateValuesCutAtDots); + final List proposals = generateProposals(queryWithCaretMarker, candidateValuesCutAtDots); return proposals; } catch (final SyntaxException e) { @@ -186,7 +185,7 @@ public class NewProposerParser implements QueryConstants { return grouper.group(candidateValues, queryWithCaretMarker); } - private List generateProposals(final String queryWithCaretMarker, final Expression expression, + private List generateProposals(final String queryWithCaretMarker, final SortedSet candidateValues) { final List proposals = new ArrayList<>(); diff --git a/data-store/src/test/java/org/lucares/pdb/datastore/internal/DataStoreTest.java b/data-store/src/test/java/org/lucares/pdb/datastore/internal/DataStoreTest.java index 9f78b5e..ae8dde9 100644 --- a/data-store/src/test/java/org/lucares/pdb/datastore/internal/DataStoreTest.java +++ b/data-store/src/test/java/org/lucares/pdb/datastore/internal/DataStoreTest.java @@ -165,6 +165,12 @@ public class DataStoreTest { result.add(new Object[] { "!(type=dog and name=|) and !type=cat", "name", Arrays.asList("Jennifer", "Jenny", "Tim") }); + // not existing field + result.add(new Object[] { "name=| and XYZ=Tim", "name", Arrays.asList() }); + + // not existing value + result.add(new Object[] { "name=| and type=XYZ", "name", Arrays.asList() }); + return result.iterator(); } diff --git a/data-store/src/test/java/org/lucares/pdb/datastore/internal/ProposerTest.java b/data-store/src/test/java/org/lucares/pdb/datastore/internal/ProposerTest.java index 8de4286..587358f 100644 --- a/data-store/src/test/java/org/lucares/pdb/datastore/internal/ProposerTest.java +++ b/data-store/src/test/java/org/lucares/pdb/datastore/internal/ProposerTest.java @@ -88,6 +88,7 @@ public class ProposerTest { public void testPrefixOfValue() throws Exception { assertProposals("name =Tim", 9, // + new Proposal("Tim", "name =Tim", true, "name =Tim", 9), new Proposal("Timothy", "name =Timothy", true, "name =Timothy", 13)); assertProposals("name =Je", 8, // @@ -116,6 +117,7 @@ public class ProposerTest { new Proposal("Jenny", "name = (Timothy, Jenny)", true, "name = (Timothy, Jenny)", 22)); assertProposals("name = (Tim)", 11, // + new Proposal("Tim", "name = (Tim)", true, "name = (Tim)", 11), new Proposal("Timothy", "name = (Timothy)", true, "name = (Timothy)", 15)); /*