diff options
Diffstat (limited to 'container-search/src/main/java/com/yahoo')
14 files changed, 131 insertions, 203 deletions
diff --git a/container-search/src/main/java/com/yahoo/prelude/fastsearch/FastHit.java b/container-search/src/main/java/com/yahoo/prelude/fastsearch/FastHit.java index 68ca8385b8a..23cdff15ad9 100644 --- a/container-search/src/main/java/com/yahoo/prelude/fastsearch/FastHit.java +++ b/container-search/src/main/java/com/yahoo/prelude/fastsearch/FastHit.java @@ -4,6 +4,7 @@ package com.yahoo.prelude.fastsearch; import com.yahoo.data.access.ObjectTraverser; import com.yahoo.document.GlobalId; import com.yahoo.net.URI; +import com.yahoo.search.dispatch.LeanHit; import com.yahoo.search.query.Sorting; import com.yahoo.search.result.FeatureData; import com.yahoo.search.result.Hit; @@ -11,7 +12,6 @@ import com.yahoo.search.result.Relevance; import com.yahoo.data.access.Inspector; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -31,18 +31,18 @@ import java.util.function.BiConsumer; */ public class FastHit extends Hit { - private static final byte [] emptyGID = new byte[GlobalId.LENGTH]; + private static final byte[] emptyGID = new byte[GlobalId.LENGTH]; /** The index of the content node this hit originated at */ - private int distributionKey = 0; + private int distributionKey; /** The local identifier of the content store for this hit on the node it originated at */ - private int partId; + private final int partId; /** The global id of this document in the backend node which produced it */ - private byte [] globalId; + private byte[] globalId; private transient byte[] sortData = null; - // TODO I suspect this one can be dropped. + // TODO: I suspect this one can be dropped. private transient Sorting sortDataSorting = null; /** @@ -129,16 +129,6 @@ public class FastHit extends Hit { public int getPartId() { return partId; } - /** - * Sets the part id number, which specifies the node where this hit is - * found. The row count is used to decode the part id into a column and a - * row number: the number of n least significant bits required to hold the - * highest row number are the row bits, the rest are column bits. - * - * Note: Remove partId when all dispatching happens from the container dispatcher, not fdispatch - */ - public void setPartId(int partId) { this.partId = partId; } - /** Returns the index of the node this hit originated at */ public int getDistributionKey() { return distributionKey; } @@ -167,17 +157,7 @@ public class FastHit extends Hit { if (!left.hasSortData(sorting) || !right.hasSortData(sorting)) { return 0; // cannot sort } - int i = Arrays.mismatch(left.sortData, right.sortData); - if (i < 0) { - return 0; - } - int max = Integer.min(left.sortData.length, right.sortData.length); - if (i >= max) { - return left.sortData.length - right.sortData.length; - } - int vl = (int) left.sortData[i] & 0xFF; - int vr = (int) right.sortData[i] & 0xFF; - return vl - vr; + return LeanHit.compareData(left.sortData, right.sortData); } /** For internal use */ @@ -188,11 +168,6 @@ public class FastHit extends Hit { summaries.add(0, new SummaryData(this, docsumDef, value, 1 + summaries.size())); } - /** Returns the raw summary data available in this as an unmodifiable list */ - public List<SummaryData> summaryData() { - return Collections.unmodifiableList(summaries); - } - /** * Returns values for the features listed in * <a href="https://docs.vespa.ai/en/reference/schema-reference.html#summary-features">summary-features</a> diff --git a/container-search/src/main/java/com/yahoo/prelude/fastsearch/SortDataHitSorter.java b/container-search/src/main/java/com/yahoo/prelude/fastsearch/SortDataHitSorter.java index 6067f85df9b..722e7155dc8 100644 --- a/container-search/src/main/java/com/yahoo/prelude/fastsearch/SortDataHitSorter.java +++ b/container-search/src/main/java/com/yahoo/prelude/fastsearch/SortDataHitSorter.java @@ -5,7 +5,6 @@ import com.yahoo.search.query.Sorting; import com.yahoo.search.result.Hit; import com.yahoo.search.result.HitGroup; -import java.util.Collections; import java.util.Comparator; import java.util.List; @@ -18,15 +17,14 @@ public class SortDataHitSorter { return; } var fallbackComparator = fallbackOrderer.getComparator(); - Collections.sort(hits, getComparator(sorting, fallbackComparator)); + hits.sort(getComparator(sorting, fallbackComparator)); } public static boolean isSortable(Hit hit, Sorting sorting) { if (sorting == null) { return false; } - if (hit instanceof FastHit) { - var fhit = (FastHit) hit; + if (hit instanceof FastHit fhit) { return fhit.hasSortData(sorting); } else { return false; @@ -42,20 +40,14 @@ public class SortDataHitSorter { } private static int compareTwo(Hit left, Hit right, Sorting sorting) { - if (left == null || right == null || !(left instanceof FastHit) || !(right instanceof FastHit)) { - return 0; - } - FastHit fl = (FastHit) left; - FastHit fr = (FastHit) right; + if (!(left instanceof FastHit fl) || !(right instanceof FastHit fr)) return 0; return FastHit.compareSortData(fl, fr, sorting); } private static int compareWithFallback(Hit left, Hit right, Sorting sorting, Comparator<Hit> fallback) { - if (left == null || right == null || !(left instanceof FastHit) || !(right instanceof FastHit)) { + if (!(left instanceof FastHit fl) || !(right instanceof FastHit fr)) { return fallback.compare(left, right); } - FastHit fl = (FastHit) left; - FastHit fr = (FastHit) right; if (fl.hasSortData(sorting) && fr.hasSortData(sorting)) { return FastHit.compareSortData(fl, fr, sorting); } else { diff --git a/container-search/src/main/java/com/yahoo/prelude/query/RegExpItem.java b/container-search/src/main/java/com/yahoo/prelude/query/RegExpItem.java index 29cf7803d61..79fbeb99119 100644 --- a/container-search/src/main/java/com/yahoo/prelude/query/RegExpItem.java +++ b/container-search/src/main/java/com/yahoo/prelude/query/RegExpItem.java @@ -2,6 +2,7 @@ package com.yahoo.prelude.query; import java.nio.ByteBuffer; +import java.util.Objects; import java.util.regex.Pattern; /** @@ -70,43 +71,26 @@ public class RegExpItem extends TermItem { putString(getIndexedString(), buffer); } + public Pattern getRegexp() { return regexp; } + @Override public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("RegExpItem [expression=").append(expression).append("]"); - return builder.toString(); + return "RegExpItem [expression=" + expression + "]"; } @Override public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + ((expression == null) ? 0 : expression.hashCode()); - return result; + return Objects.hash(super.hashCode(), expression); } @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - RegExpItem other = (RegExpItem) obj; - if (expression == null) { - if (other.expression != null) { - return false; - } - } else if (!expression.equals(other.expression)) { - return false; - } - return true; - } + public boolean equals(Object o) { + if (this == o) return true; + if ( ! super.equals(o)) return false; + if (getClass() != o.getClass()) return false; - public Pattern getRegexp() { return regexp; } + RegExpItem other = (RegExpItem)o; + return Objects.equals(this.expression, other.expression); + } } diff --git a/container-search/src/main/java/com/yahoo/prelude/searcher/ValidateSortingSearcher.java b/container-search/src/main/java/com/yahoo/prelude/searcher/ValidateSortingSearcher.java index 9f875347ccc..47125d198e1 100644 --- a/container-search/src/main/java/com/yahoo/prelude/searcher/ValidateSortingSearcher.java +++ b/container-search/src/main/java/com/yahoo/prelude/searcher/ValidateSortingSearcher.java @@ -155,8 +155,7 @@ public class ValidateSortingSearcher extends Searcher { } } } - if (f.getSorter() instanceof Sorting.UcaSorter) { - Sorting.UcaSorter sorter = (Sorting.UcaSorter) f.getSorter(); + if (f.getSorter() instanceof Sorting.UcaSorter sorter) { String locale = sorter.getLocale(); if (locale == null || locale.isEmpty()) { diff --git a/container-search/src/main/java/com/yahoo/search/dispatch/InterleavedSearchInvoker.java b/container-search/src/main/java/com/yahoo/search/dispatch/InterleavedSearchInvoker.java index b4f04da5986..39be91cf3e8 100644 --- a/container-search/src/main/java/com/yahoo/search/dispatch/InterleavedSearchInvoker.java +++ b/container-search/src/main/java/com/yahoo/search/dispatch/InterleavedSearchInvoker.java @@ -210,17 +210,17 @@ public class InterleavedSearchInvoker extends SearchInvoker implements ResponseM indexPartial++; } } - while ((indexCurrent < current.size()) && (merged.size() < needed)) { - LeanHit currentHit = current.get(indexCurrent++); - merged.add(currentHit); - } - while ((indexPartial < partial.size()) && (merged.size() < needed)) { - LeanHit incomingHit = partial.get(indexPartial++); - merged.add(incomingHit); - } + appendRemainingIfNeeded(merged, needed, current, indexCurrent); + appendRemainingIfNeeded(merged, needed, partial, indexPartial); return merged; } + private void appendRemainingIfNeeded(List<LeanHit> merged, int needed, List<LeanHit> hits, int index) { + while ((index < hits.size()) && (merged.size() < needed)) { + merged.add(hits.get(index++)); + } + } + private void ejectInvoker(SearchInvoker invoker) { invokers.remove(invoker); invoker.release(); diff --git a/container-search/src/main/java/com/yahoo/search/dispatch/LeanHit.java b/container-search/src/main/java/com/yahoo/search/dispatch/LeanHit.java index bd0415fa449..f80cebe90c4 100644 --- a/container-search/src/main/java/com/yahoo/search/dispatch/LeanHit.java +++ b/container-search/src/main/java/com/yahoo/search/dispatch/LeanHit.java @@ -51,7 +51,7 @@ public class LeanHit implements Comparable<LeanHit> { return (res != 0) ? res : compareData(gid, o.gid); } - private static int compareData(byte[] left, byte[] right) { + public static int compareData(byte[] left, byte[] right) { int i = Arrays.mismatch(left, right); if (i < 0) { return 0; diff --git a/container-search/src/main/java/com/yahoo/search/handler/Json2SingleLevelMap.java b/container-search/src/main/java/com/yahoo/search/handler/Json2SingleLevelMap.java index bf0272f4f66..7dd1772a53e 100644 --- a/container-search/src/main/java/com/yahoo/search/handler/Json2SingleLevelMap.java +++ b/container-search/src/main/java/com/yahoo/search/handler/Json2SingleLevelMap.java @@ -22,9 +22,11 @@ import java.util.Map; * @author baldersheim */ class Json2SingleLevelMap { + private static final ObjectMapper jsonMapper = new ObjectMapper().configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true); private final byte [] buf; private final JsonParser parser; + Json2SingleLevelMap(InputStream data) { try { buf = data.readAllBytes(); @@ -33,6 +35,7 @@ class Json2SingleLevelMap { throw new RuntimeException("Problem reading POSTed data", e); } } + Map<String, String> parse() { try { Map<String, String> map = new HashMap<>(); @@ -47,16 +50,17 @@ class Json2SingleLevelMap { throw new RuntimeException("Problem reading POSTed data", e); } } + void parse(Map<String, String> map, String parent) throws IOException { for (parser.nextToken(); parser.getCurrentToken() != JsonToken.END_OBJECT; parser.nextToken()) { String fieldName = parent + parser.getCurrentName(); JsonToken token = parser.nextToken(); if ((token == JsonToken.VALUE_STRING) || - (token == JsonToken.VALUE_NUMBER_FLOAT) || - (token == JsonToken.VALUE_NUMBER_INT) || - (token == JsonToken.VALUE_TRUE) || - (token == JsonToken.VALUE_FALSE) || - (token == JsonToken.VALUE_NULL)) { + (token == JsonToken.VALUE_NUMBER_FLOAT) || + (token == JsonToken.VALUE_NUMBER_INT) || + (token == JsonToken.VALUE_TRUE) || + (token == JsonToken.VALUE_FALSE) || + (token == JsonToken.VALUE_NULL)) { map.put(fieldName, parser.getText()); } else if (token == JsonToken.START_ARRAY) { map.put(fieldName, skipChildren(parser, buf)); @@ -71,6 +75,7 @@ class Json2SingleLevelMap { } } } + private String skipChildren(JsonParser parser, byte [] input) throws IOException { JsonLocation start = parser.getCurrentLocation(); parser.skipChildren(); @@ -78,4 +83,5 @@ class Json2SingleLevelMap { int offset = (int)start.getByteOffset() - 1; return new String(input, offset, (int)(end.getByteOffset() - offset), StandardCharsets.UTF_8); } + } diff --git a/container-search/src/main/java/com/yahoo/search/query/Sorting.java b/container-search/src/main/java/com/yahoo/search/query/Sorting.java index 6b07b5ef1d5..63bc48ff804 100644 --- a/container-search/src/main/java/com/yahoo/search/query/Sorting.java +++ b/container-search/src/main/java/com/yahoo/search/query/Sorting.java @@ -6,7 +6,6 @@ import com.ibm.icu.util.ULocale; import com.yahoo.prelude.IndexFacts; import com.yahoo.processing.IllegalInputException; import com.yahoo.search.Query; -import com.yahoo.search.searchchain.Execution; import com.yahoo.text.Utf8; import java.nio.ByteBuffer; @@ -161,6 +160,7 @@ public class Sorting implements Cloneable { */ public List<FieldOrder> fieldOrders() { return fieldOrders; } + @Override public Sorting clone() { return new Sorting(this.fieldOrders); } @@ -173,16 +173,13 @@ public class Sorting implements Cloneable { @Override public boolean equals(Object o) { if (o == this) return true; - if( ! (o instanceof Sorting)) return false; - - Sorting ss = (Sorting) o; + if( ! (o instanceof Sorting ss)) return false; return fieldOrders.equals(ss.fieldOrders); } public int encode(ByteBuffer buffer) { int usedBytes = 0; byte[] nameBuffer; - buffer.position(); byte space = '.'; for (FieldOrder fieldOrder : fieldOrders) { if (space == ' ') { @@ -231,10 +228,10 @@ public class Sorting implements Cloneable { @Override public boolean equals(Object other) { - if (!(other instanceof AttributeSorter)) { + if (!(other instanceof AttributeSorter sorter)) { return false; } - return ((AttributeSorter) other).fieldName.equals(fieldName); + return sorter.fieldName.equals(fieldName); } @Override @@ -305,15 +302,14 @@ public class Sorting implements Cloneable { public UcaSorter(String fieldName) { super(fieldName); } static private int strength2Collator(Strength strength) { - switch (strength) { - case PRIMARY: return Collator.PRIMARY; - case SECONDARY: return Collator.SECONDARY; - case TERTIARY: return Collator.TERTIARY; - case QUATERNARY: return Collator.QUATERNARY; - case IDENTICAL: return Collator.IDENTICAL; - case UNDEFINED: return Collator.PRIMARY; - } - return Collator.PRIMARY; + return switch (strength) { + case PRIMARY -> Collator.PRIMARY; + case SECONDARY -> Collator.SECONDARY; + case TERTIARY -> Collator.TERTIARY; + case QUATERNARY -> Collator.QUATERNARY; + case IDENTICAL -> Collator.IDENTICAL; + case UNDEFINED -> Collator.PRIMARY; + }; } public void setLocale(String locale, Strength strength) { @@ -323,15 +319,15 @@ public class Sorting implements Cloneable { try { uloc = new ULocale(locale); } catch (Throwable e) { - throw new RuntimeException("ULocale("+locale+") failed with exception " + e.toString()); + throw new IllegalArgumentException("ULocale '" + locale + "' failed", e); } try { collator = Collator.getInstance(uloc); if (collator == null) { - throw new RuntimeException("No collator available for: " + locale); + throw new IllegalArgumentException("No collator available for locale '" + locale + "'"); } } catch (Throwable e) { - throw new RuntimeException("Collator.getInstance(ULocale("+locale+")) failed with exception " + e.toString()); + throw new RuntimeException("Collator.getInstance(ULocale(" + locale + ")) failed", e); } collator.setStrength(strength2Collator(strength)); // collator.setDecomposition(Collator.CANONICAL_DECOMPOSITION); @@ -343,19 +339,22 @@ public class Sorting implements Cloneable { public String getDecomposition() { return (collator.getDecomposition() == Collator.CANONICAL_DECOMPOSITION) ? "CANONICAL_DECOMPOSITION" : "NO_DECOMPOSITION"; } @Override - public String toSerialForm() { return "uca(" + getName() + ',' + locale + ',' + ((strength != Strength.UNDEFINED) ? strength.toString() : "PRIMARY") + ')'; } + public String toSerialForm() { + return "uca(" + getName() + ',' + locale + ',' + + ((strength != Strength.UNDEFINED) ? strength.toString() : "PRIMARY") + ')'; + } @Override public int hashCode() { return 1 + 3*locale.hashCode() + 5*strength.hashCode() + 7*super.hashCode(); } @Override public boolean equals(Object other) { - if (!(other instanceof UcaSorter)) { - return false; - } + if (this == other) return true; + if (!(other instanceof UcaSorter)) return false; return super.equals(other) && locale.equals(((UcaSorter)other).locale) && (strength == ((UcaSorter)other).strength); } + @Override public UcaSorter clone() { UcaSorter clone = (UcaSorter)super.clone(); if (locale != null) { @@ -365,6 +364,7 @@ public class Sorting implements Cloneable { } @SuppressWarnings({ "rawtypes", "unchecked" }) + @Override public int compare(Comparable a, Comparable b) { if ((a instanceof String) && (b instanceof String)) { return collator.compare((String)a, (String) b); diff --git a/container-search/src/main/java/com/yahoo/search/querytransform/NGramSearcher.java b/container-search/src/main/java/com/yahoo/search/querytransform/NGramSearcher.java index afd25132510..bcdc84c1808 100644 --- a/container-search/src/main/java/com/yahoo/search/querytransform/NGramSearcher.java +++ b/container-search/src/main/java/com/yahoo/search/querytransform/NGramSearcher.java @@ -69,8 +69,7 @@ public class NGramSearcher extends Searcher { private boolean rewriteToNGramMatching(Item item, int indexInParent, IndexFacts.Session indexFacts, Query query) { boolean rewritten = false; - if (item instanceof SegmentItem) { // handle CJK segmented terms which should be grams instead - SegmentItem segments = (SegmentItem)item; + if (item instanceof SegmentItem segments) { // handle CJK segmented terms which should be grams instead Index index = indexFacts.getIndex(segments.getIndexName()); if (index.isNGram()) { Item grams = splitToGrams(segments, toLowerCase(segments.getRawWord()), index.getGramSize(), query); @@ -78,13 +77,11 @@ public class NGramSearcher extends Searcher { rewritten = true; } } - else if (item instanceof CompositeItem) { - CompositeItem composite = (CompositeItem)item; + else if (item instanceof CompositeItem composite) { for (int i=0; i<composite.getItemCount(); i++) rewritten = rewriteToNGramMatching(composite.getItem(i), i, indexFacts, query) || rewritten; } - else if (item instanceof TermItem) { - TermItem term = (TermItem)item; + else if (item instanceof TermItem term) { Index index = indexFacts.getIndex(term.getIndexName()); if (index.isNGram()) { Item grams = splitToGrams(term,term.stringValue(), index.getGramSize(), query); @@ -149,11 +146,10 @@ public class NGramSearcher extends Searcher { } private void replaceItemByGrams(Item item, Item grams, int indexInParent) { - if (!(grams instanceof CompositeItem) || !(item.getParent() instanceof PhraseItem)) { // usually, simply replace + if (!(grams instanceof CompositeItem) || !(item.getParent() instanceof PhraseItem phraseParent)) { // usually, simply replace item.getParent().setItem(indexInParent, grams); } else { // but if the parent is a phrase, we cannot add the AND to it, so add each gram to the phrase - PhraseItem phraseParent = (PhraseItem)item.getParent(); phraseParent.removeItem(indexInParent); int addedTerms = 0; for (Iterator<Item> i = ((CompositeItem)grams).getItemIterator(); i.hasNext(); ) { diff --git a/container-search/src/main/java/com/yahoo/search/result/FieldComparator.java b/container-search/src/main/java/com/yahoo/search/result/FieldComparator.java index 0259dd66dbe..7f392d43753 100644 --- a/container-search/src/main/java/com/yahoo/search/result/FieldComparator.java +++ b/container-search/src/main/java/com/yahoo/search/result/FieldComparator.java @@ -17,7 +17,7 @@ import java.util.Comparator; public class FieldComparator extends ChainableComparator { /** The definition of sorting order */ - private Sorting sorting; + private final Sorting sorting; /** Creates a field comparator using a sort order and having no chained comparator */ public FieldComparator(Sorting sorting) { @@ -32,7 +32,7 @@ public class FieldComparator extends ChainableComparator { /** Creates a comparator given a sorting, or returns null if the given sorting is null */ public static FieldComparator create(Sorting sorting) { - if (sorting==null) return null; + if (sorting == null) return null; return new FieldComparator(sorting); } @@ -41,7 +41,7 @@ public class FieldComparator extends ChainableComparator { * stored in hit fields.0 * <p> * When one of the hits has the requested property and the other - * has not, the the hit containing the property precedes the one + * has not, the hit containing the property precedes the one * that does not. * <p> * There is no locale based sorting here, as the backend does @@ -78,19 +78,14 @@ public class FieldComparator extends ChainableComparator { } Inspector sub = top.field(key); if (sub.valid()) { - switch (sub.type()) { - case EMPTY: - return null; - case BOOL: - return (sub.asBool() ? Boolean.TRUE : Boolean.FALSE); - case LONG: - return sub.asLong(); - case DOUBLE: - return sub.asDouble(); - case STRING: - return sub.asString(); - } - return sub.toString(); + return switch (sub.type()) { + case EMPTY -> null; + case BOOL -> (sub.asBool() ? Boolean.TRUE : Boolean.FALSE); + case LONG -> sub.asLong(); + case DOUBLE -> sub.asDouble(); + case STRING -> sub.asString(); + default -> sub.toString(); + }; } } // fallback value @@ -115,15 +110,14 @@ public class FieldComparator extends ChainableComparator { @SuppressWarnings("rawtypes") private int compareValues(Object first, Object second, Sorting.AttributeSorter s) { - if (first == null) { - if (second == null) return 0; - return -1; - } else if (second == null) { + if (first == null) + return second == null ? 0 : -1; + else if (second == null) return 1; - } + if (first.getClass().isInstance(second) && first instanceof Comparable) { // We now know: - // second is of a type which is a subclass of first's type + // Second is of a type which is a subclass of first's type // They both implement Comparable return s.compare((Comparable)first, (Comparable)second); } else { @@ -133,14 +127,7 @@ public class FieldComparator extends ChainableComparator { @Override public String toString() { - StringBuilder b = new StringBuilder(); - b.append("FieldComparator:"); - if (sorting == null) { - b.append(" null"); - } else { - b.append(sorting.toString()); - } - return b.toString(); + return "FieldComparator:" + (sorting == null ? " null" : sorting.toString()); } } diff --git a/container-search/src/main/java/com/yahoo/search/searchchain/AsyncExecution.java b/container-search/src/main/java/com/yahoo/search/searchchain/AsyncExecution.java index adab4d59ec0..205c65a6256 100644 --- a/container-search/src/main/java/com/yahoo/search/searchchain/AsyncExecution.java +++ b/container-search/src/main/java/com/yahoo/search/searchchain/AsyncExecution.java @@ -67,7 +67,7 @@ public class AsyncExecution { * Creates an async execution. * * @param chain the chain to execute - * @param context the the context of this + * @param context the context of this */ public AsyncExecution(Chain<? extends Searcher> chain, Execution.Context context) { this(context, chain); diff --git a/container-search/src/main/java/com/yahoo/search/yql/ProgramParser.java b/container-search/src/main/java/com/yahoo/search/yql/ProgramParser.java index 5258087eb44..32880f9b1a8 100644 --- a/container-search/src/main/java/com/yahoo/search/yql/ProgramParser.java +++ b/container-search/src/main/java/com/yahoo/search/yql/ProgramParser.java @@ -277,29 +277,28 @@ final class ProgramParser { switch (getParseTreeIndex(sourceNode)) { // ALL_SOURCE and MULTI_SOURCE are how FROM SOURCES // *|source_name,... are parsed - case yqlplusParser.RULE_select_source_all: - Location location = toLocation(scope, sourceNode.getChild(2)); + case yqlplusParser.RULE_select_source_all -> { + Location location = toLocation(scope, sourceNode.getChild(2)); source = OperatorNode.create(location, SequenceOperator.ALL); source.putAnnotation("alias", "row"); scope.defineDataSource(location, "row"); - break; - case yqlplusParser.RULE_select_source_multi: - Source_listContext multiSourceContext = ((Select_source_multiContext) sourceNode).source_list(); + } + case yqlplusParser.RULE_select_source_multi -> { + Source_listContext multiSourceContext = ((Select_source_multiContext) sourceNode).source_list(); source = readMultiSource(scope, multiSourceContext); source.putAnnotation("alias", "row"); scope.defineDataSource(toLocation(scope, multiSourceContext), "row"); - break; - case yqlplusParser.RULE_select_source_from: - source = convertSource((ParserRuleContext) sourceNode.getChild(1), scope); - break; } - } else { - source = OperatorNode.create(SequenceOperator.EMPTY); + case yqlplusParser.RULE_select_source_from -> + source = convertSource((ParserRuleContext) sourceNode.getChild(1), scope); } + } else { + source = OperatorNode.create(SequenceOperator.EMPTY); + } - for (int i = 1; i < node.getChildCount(); ++i) { - ParseTree child = node.getChild(i); - switch (getParseTreeIndex(child)) { + for (int i = 1; i < node.getChildCount(); ++i) { + ParseTree child = node.getChild(i); + switch (getParseTreeIndex(child)) { case yqlplusParser.RULE_select_field_spec: if (getParseTreeIndex(child.getChild(0)) == yqlplusParser.RULE_project_spec) { proj = readProjection(((Project_specContext) child.getChild(0)).field_def(), scope); @@ -311,7 +310,7 @@ final class ProgramParser { case yqlplusParser.RULE_orderby: // OrderbyContext orderby() List<Orderby_fieldContext> orderFieds = ((OrderbyContext) child) - .orderby_fields().orderby_field(); + .orderby_fields().orderby_field(); orderby = Lists.newArrayListWithExpectedSize(orderFieds.size()); for (var field: orderFieds) { orderby.add(convertSortKey(field, scope)); @@ -326,8 +325,8 @@ final class ProgramParser { case yqlplusParser.RULE_timeout: timeout = convertExpr(((TimeoutContext) child).fixed_or_parameter(), scope); break; - } } + } // now assemble the logical plan OperatorNode<SequenceOperator> result = source; // filter @@ -415,8 +414,7 @@ final class ProgramParser { private OperatorNode<SequenceOperator> convertQuery(ParseTree node, Scope scope) { if (node instanceof Select_statementContext) { return convertSelect(node, scope.getRoot()); - } else if (node instanceof Source_statementContext) { // for pipe - Source_statementContext sourceStatementContext = (Source_statementContext)node; + } else if (node instanceof Source_statementContext sourceStatementContext) { // for pipe return convertPipe(sourceStatementContext.query_statement(), sourceStatementContext.pipeline_step(), scope); } else { throw new IllegalArgumentException("Unexpected argument type to convertQueryStatement: " + node.toStringTree()); @@ -469,47 +467,44 @@ final class ProgramParser { dataSourceNode = (ParserRuleContext)dataSourceNode.getChild(1); } } - switch (getParseTreeIndex(dataSourceNode)) { - case yqlplusParser.RULE_call_source: { - List<String> names = readName(dataSourceNode.getChild(Namespaced_nameContext.class, 0)); - alias = assignAlias(names.get(names.size() - 1), aliasContext, scope); - List<OperatorNode<ExpressionOperator>> arguments = ImmutableList.of(); - ArgumentsContext argumentsContext = dataSourceNode.getRuleContext(ArgumentsContext.class,0); - if ( argumentsContext != null) { - List<ArgumentContext> argumentContexts = argumentsContext.argument(); - arguments = Lists.newArrayListWithExpectedSize(argumentContexts.size()); - for (ArgumentContext argumentContext:argumentContexts) { - arguments.add(convertExpr(argumentContext, scope)); - } - } - if (names.size() == 1 && scope.isVariable(names.get(0))) { - String ident = names.get(0); - if (arguments.size() > 0) { - throw new ProgramCompileException(toLocation(scope, argumentsContext), "Invalid call-with-arguments on local source '%s'", ident); - } - result = OperatorNode.create(toLocation(scope, dataSourceNode), SequenceOperator.EVALUATE, OperatorNode.create(toLocation(scope, dataSourceNode), ExpressionOperator.VARREF, ident)); + switch (getParseTreeIndex(dataSourceNode)) { + case yqlplusParser.RULE_call_source -> { + List<String> names = readName(dataSourceNode.getChild(Namespaced_nameContext.class, 0)); + alias = assignAlias(names.get(names.size() - 1), aliasContext, scope); + List<OperatorNode<ExpressionOperator>> arguments = ImmutableList.of(); + ArgumentsContext argumentsContext = dataSourceNode.getRuleContext(ArgumentsContext.class, 0); + if (argumentsContext != null) { + List<ArgumentContext> argumentContexts = argumentsContext.argument(); + arguments = Lists.newArrayListWithExpectedSize(argumentContexts.size()); + for (ArgumentContext argumentContext : argumentContexts) { + arguments.add(convertExpr(argumentContext, scope)); + } + } + if (names.size() == 1 && scope.isVariable(names.get(0))) { + String ident = names.get(0); + if (arguments.size() > 0) { + throw new ProgramCompileException(toLocation(scope, argumentsContext), "Invalid call-with-arguments on local source '%s'", ident); + } + result = OperatorNode.create(toLocation(scope, dataSourceNode), SequenceOperator.EVALUATE, OperatorNode.create(toLocation(scope, dataSourceNode), ExpressionOperator.VARREF, ident)); } else { - result = OperatorNode.create(toLocation(scope, dataSourceNode), SequenceOperator.SCAN, scope.resolvePath(names), arguments); + result = OperatorNode.create(toLocation(scope, dataSourceNode), SequenceOperator.SCAN, scope.resolvePath(names), arguments); } - break; } - case yqlplusParser.RULE_sequence_source: { - IdentContext identContext = dataSourceNode.getRuleContext(IdentContext.class,0); + case yqlplusParser.RULE_sequence_source -> { + IdentContext identContext = dataSourceNode.getRuleContext(IdentContext.class, 0); String ident = identContext.getText(); if (!scope.isVariable(ident)) { throw new ProgramCompileException(toLocation(scope, identContext), "Unknown variable reference '%s'", ident); } alias = assignAlias(ident, aliasContext, scope); result = OperatorNode.create(toLocation(scope, dataSourceNode), SequenceOperator.EVALUATE, OperatorNode.create(toLocation(scope, dataSourceNode), ExpressionOperator.VARREF, ident)); - break; } - case yqlplusParser.RULE_source_statement: { + case yqlplusParser.RULE_source_statement -> { alias = assignAlias(null, dataSourceNode, scope); result = convertQuery(dataSourceNode, scope); - break; } - default: - throw new IllegalArgumentException("Unexpected argument type to convertSource: " + dataSourceNode.getText()); + default -> + throw new IllegalArgumentException("Unexpected argument type to convertSource: " + dataSourceNode.getText()); } result.putAnnotation("alias", alias); return result; @@ -522,10 +517,7 @@ final class ProgramParser { List<OperatorNode<StatementOperator>> stmts = Lists.newArrayList(); int output = 0; for (ParseTree node : program.children) { - if (!(node instanceof ParserRuleContext)) { - continue; - } - ParserRuleContext ruleContext = (ParserRuleContext) node; + if (!(node instanceof ParserRuleContext ruleContext)) continue; if (ruleContext.getRuleIndex() != yqlplusParser.RULE_statement) throw new ProgramCompileException("Unknown program element: " + node.getText()); diff --git a/container-search/src/main/java/com/yahoo/search/yql/VespaSerializer.java b/container-search/src/main/java/com/yahoo/search/yql/VespaSerializer.java index cab989d4466..4b035e0ccc5 100644 --- a/container-search/src/main/java/com/yahoo/search/yql/VespaSerializer.java +++ b/container-search/src/main/java/com/yahoo/search/yql/VespaSerializer.java @@ -121,7 +121,6 @@ import com.yahoo.search.query.QueryTree; public class VespaSerializer { // TODO: Refactor, too much copy/paste - private static abstract class Serializer<ITEM extends Item> { abstract void onExit(StringBuilder destination, ITEM item); diff --git a/container-search/src/main/java/com/yahoo/search/yql/YqlParser.java b/container-search/src/main/java/com/yahoo/search/yql/YqlParser.java index 5670e8a7dfd..3a1927983d2 100644 --- a/container-search/src/main/java/com/yahoo/search/yql/YqlParser.java +++ b/container-search/src/main/java/com/yahoo/search/yql/YqlParser.java @@ -90,11 +90,9 @@ import com.yahoo.search.query.parser.ParserFactory; /** * The YQL query language. * - * <p> * This class <em>must</em> be kept in lockstep with {@link VespaSerializer}. * Adding anything here will usually require a corresponding addition in * VespaSerializer. - * </p> * * @author Steinar Knutsen * @author Stian Kristoffersen |