diff options
80 files changed, 999 insertions, 694 deletions
diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/derived/AttributeFields.java b/config-model/src/main/java/com/yahoo/searchdefinition/derived/AttributeFields.java index 72ba6de7022..c7ca1a33ff2 100644 --- a/config-model/src/main/java/com/yahoo/searchdefinition/derived/AttributeFields.java +++ b/config-model/src/main/java/com/yahoo/searchdefinition/derived/AttributeFields.java @@ -2,8 +2,11 @@ package com.yahoo.searchdefinition.derived; import com.yahoo.config.subscription.ConfigInstanceUtil; +import com.yahoo.document.ArrayDataType; import com.yahoo.document.DataType; +import com.yahoo.document.Field; import com.yahoo.document.PositionDataType; +import com.yahoo.document.StructDataType; import com.yahoo.searchdefinition.Search; import com.yahoo.searchdefinition.document.Attribute; import com.yahoo.searchdefinition.document.ImmutableSDField; @@ -41,18 +44,53 @@ public class AttributeFields extends Derived implements AttributesConfig.Produce /** Derives everything from a field */ @Override protected void derive(ImmutableSDField field, Search search) { + boolean fieldIsArrayOfSimpleStruct = isArrayOfSimpleStruct(field); if (field.usesStructOrMap() && + !fieldIsArrayOfSimpleStruct && !field.getDataType().equals(PositionDataType.INSTANCE) && !field.getDataType().equals(DataType.getArray(PositionDataType.INSTANCE))) { return; // Ignore struct fields for indexed search (only implemented for streaming search) } if (field.isImportedField()) { deriveImportedAttributes(field); + } else if (fieldIsArrayOfSimpleStruct) { + deriveArrayOfSimpleStruct(field); } else { deriveAttributes(field); } } + private static boolean isArrayOfSimpleStruct(ImmutableSDField field) { + DataType fieldType = field.getDataType(); + if (fieldType instanceof ArrayDataType) { + ArrayDataType arrayType = (ArrayDataType)fieldType; + DataType nestedType = arrayType.getNestedType(); + if (nestedType instanceof StructDataType && + !(nestedType.equals(PositionDataType.INSTANCE))) { + StructDataType structType = (StructDataType)nestedType; + for (Field innerField : structType.getFields()) { + if (!isPrimitiveType(innerField.getDataType())) { + return false; + } + } + return true; + } else { + return false; + } + } else { + return false; + } + } + + private static boolean isPrimitiveType(DataType dataType) { + return dataType.equals(DataType.BYTE) || + dataType.equals(DataType.INT) || + dataType.equals(DataType.LONG) || + dataType.equals(DataType.FLOAT) || + dataType.equals(DataType.DOUBLE) || + dataType.equals(DataType.STRING); + } + /** Returns an attribute by name, or null if it doesn't exist */ public Attribute getAttribute(String attributeName) { return attributes.get(attributeName); @@ -98,6 +136,16 @@ public class AttributeFields extends Derived implements AttributesConfig.Produce } } + private void deriveArrayOfSimpleStruct(ImmutableSDField field) { + for (ImmutableSDField structField : field.getStructFields()) { + for (Attribute attribute : structField.getAttributes().values()) { + if (structField.getName().equals(attribute.getName())) { + attributes.put(attribute.getName(), attribute.convertToArray()); + } + } + } + } + /** Returns a read only attribute iterator */ public Iterator attributeIterator() { return attributes().iterator(); diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/document/Attribute.java b/config-model/src/main/java/com/yahoo/searchdefinition/document/Attribute.java index f932265cb93..81e44850e71 100644 --- a/config-model/src/main/java/com/yahoo/searchdefinition/document/Attribute.java +++ b/config-model/src/main/java/com/yahoo/searchdefinition/document/Attribute.java @@ -147,6 +147,12 @@ public final class Attribute implements Cloneable, Serializable { this.referenceDocumentType = referenceDocumentType; } + public Attribute convertToArray() { + Attribute result = clone(); + result.collectionType = CollectionType.ARRAY; + return result; + } + /** * <p>Returns whether this attribute should be included in the "attributeprefetch" summary * which is returned to the Qrs by prefetchAttributes, used by blending, uniquing etc. @@ -181,6 +187,7 @@ public final class Attribute implements Cloneable, Serializable { public long upperBound() { return upperBound; } public double densePostingListThreshold() { return densePostingListThreshold; } public Optional<TensorType> tensorType() { return tensorType; } + public Optional<StructuredDataType> referenceDocumentType() { return referenceDocumentType; } public Sorting getSorting() { return sorting; } diff --git a/config-model/src/test/derived/array_of_struct_attribute/attributes.cfg b/config-model/src/test/derived/array_of_struct_attribute/attributes.cfg new file mode 100644 index 00000000000..9e6b5cea55e --- /dev/null +++ b/config-model/src/test/derived/array_of_struct_attribute/attributes.cfg @@ -0,0 +1,40 @@ +attribute[].name "elem_array.name" +attribute[].datatype STRING +attribute[].collectiontype ARRAY +attribute[].removeifzero false +attribute[].createifnonexistent false +attribute[].fastsearch false +attribute[].huge false +attribute[].sortascending true +attribute[].sortfunction UCA +attribute[].sortstrength PRIMARY +attribute[].sortlocale "" +attribute[].enablebitvectors false +attribute[].enableonlybitvector false +attribute[].fastaccess false +attribute[].arity 8 +attribute[].lowerbound -9223372036854775808 +attribute[].upperbound 9223372036854775807 +attribute[].densepostinglistthreshold 0.4 +attribute[].tensortype "" +attribute[].imported false +attribute[].name "elem_array.weight" +attribute[].datatype INT32 +attribute[].collectiontype ARRAY +attribute[].removeifzero false +attribute[].createifnonexistent false +attribute[].fastsearch false +attribute[].huge false +attribute[].sortascending true +attribute[].sortfunction UCA +attribute[].sortstrength PRIMARY +attribute[].sortlocale "" +attribute[].enablebitvectors false +attribute[].enableonlybitvector false +attribute[].fastaccess false +attribute[].arity 8 +attribute[].lowerbound -9223372036854775808 +attribute[].upperbound 9223372036854775807 +attribute[].densepostinglistthreshold 0.4 +attribute[].tensortype "" +attribute[].imported false diff --git a/config-model/src/test/derived/array_of_struct_attribute/summary.cfg b/config-model/src/test/derived/array_of_struct_attribute/summary.cfg new file mode 100644 index 00000000000..c1679c57d1a --- /dev/null +++ b/config-model/src/test/derived/array_of_struct_attribute/summary.cfg @@ -0,0 +1,11 @@ +defaultsummaryid 252850086 +classes[].id 252850086 +classes[].name "default" +classes[].fields[].name "elem_array" +classes[].fields[].type "jsonstring" +classes[].fields[].name "rankfeatures" +classes[].fields[].type "featuredata" +classes[].fields[].name "summaryfeatures" +classes[].fields[].type "featuredata" +classes[].fields[].name "documentid" +classes[].fields[].type "longstring" diff --git a/config-model/src/test/derived/array_of_struct_attribute/summarymap.cfg b/config-model/src/test/derived/array_of_struct_attribute/summarymap.cfg new file mode 100644 index 00000000000..8956a146b74 --- /dev/null +++ b/config-model/src/test/derived/array_of_struct_attribute/summarymap.cfg @@ -0,0 +1,7 @@ +defaultoutputclass -1 +override[].field "rankfeatures" +override[].command "rankfeatures" +override[].arguments "" +override[].field "summaryfeatures" +override[].command "summaryfeatures" +override[].arguments "" diff --git a/config-model/src/test/derived/array_of_struct_attribute/test.sd b/config-model/src/test/derived/array_of_struct_attribute/test.sd new file mode 100644 index 00000000000..5b2d50cbdba --- /dev/null +++ b/config-model/src/test/derived/array_of_struct_attribute/test.sd @@ -0,0 +1,17 @@ +search test { + document test { + struct elem { + field name type string {} + field weight type int {} + } + field elem_array type array<elem> { + indexing: summary + struct-field name { + indexing: attribute + } + struct-field weight { + indexing: attribute + } + } + } +} diff --git a/config-model/src/test/java/com/yahoo/searchdefinition/AttributeSettingsTestCase.java b/config-model/src/test/java/com/yahoo/searchdefinition/AttributeSettingsTestCase.java index 95d5832b70d..4ee33abfc08 100644 --- a/config-model/src/test/java/com/yahoo/searchdefinition/AttributeSettingsTestCase.java +++ b/config-model/src/test/java/com/yahoo/searchdefinition/AttributeSettingsTestCase.java @@ -1,12 +1,16 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.searchdefinition; +import com.yahoo.document.StructDataType; import com.yahoo.searchdefinition.document.Attribute; import com.yahoo.searchdefinition.document.SDField; +import com.yahoo.searchdefinition.document.Sorting; import com.yahoo.searchdefinition.parser.ParseException; +import com.yahoo.tensor.TensorType; import org.junit.Test; import java.io.IOException; +import java.util.Optional; import static org.hamcrest.core.Is.is; import static org.junit.Assert.*; @@ -88,4 +92,48 @@ public class AttributeSettingsTestCase extends SearchDefinitionTestCase { assertTrue(attr.isFastAccess()); } + @Test + public void attribute_convert_to_array_copies_internal_state() { + StructDataType refType = new StructDataType("my_struct"); + Attribute single = new Attribute("foo", Attribute.Type.STRING, Attribute.CollectionType.SINGLE, + Optional.of(TensorType.fromSpec("tensor(x{})")), Optional.of(refType)); + single.setRemoveIfZero(true); + single.setCreateIfNonExistent(true); + single.setPrefetch(Boolean.TRUE); + single.setEnableBitVectors(true); + single.setEnableOnlyBitVector(true); + single.setFastSearch(true); + single.setHuge(true); + single.setFastAccess(true); + single.setPosition(true); + single.setArity(5); + single.setLowerBound(7); + single.setUpperBound(11); + single.setDensePostingListThreshold(13.3); + single.getSorting().setAscending(); + single.getAliases().add("foo"); + + Attribute array = single.convertToArray(); + assertEquals("foo", array.getName()); + assertEquals(Attribute.Type.STRING, array.getType()); + assertEquals(Attribute.CollectionType.ARRAY, array.getCollectionType()); + assertEquals(Optional.of(TensorType.fromSpec("tensor(x{})")), array.tensorType()); + assertSame(single.referenceDocumentType(), array.referenceDocumentType()); + assertTrue(array.isRemoveIfZero()); + assertTrue(array.isCreateIfNonExistent()); + assertTrue(array.isPrefetch()); + assertTrue(array.isEnabledBitVectors()); + assertTrue(array.isEnabledOnlyBitVector()); + assertTrue(array.isFastSearch()); + assertTrue(array.isHuge()); + assertTrue(array.isFastAccess()); + assertTrue(array.isPosition()); + assertEquals(5, array.arity()); + assertEquals(7, array.lowerBound()); + assertEquals(11, array.upperBound()); + assertEquals(13.3, array.densePostingListThreshold(), 0.00001); + assertSame(single.getSorting(), array.getSorting()); + assertSame(single.getAliases(), array.getAliases()); + } + } diff --git a/config-model/src/test/java/com/yahoo/searchdefinition/derived/AttributeListTestCase.java b/config-model/src/test/java/com/yahoo/searchdefinition/derived/AttributeListTestCase.java index 86f30ba3c11..990ebe7f993 100644 --- a/config-model/src/test/java/com/yahoo/searchdefinition/derived/AttributeListTestCase.java +++ b/config-model/src/test/java/com/yahoo/searchdefinition/derived/AttributeListTestCase.java @@ -11,6 +11,7 @@ import org.junit.Test; import java.io.IOException; import java.util.Iterator; +import static com.yahoo.config.model.test.TestUtil.joinLines; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -68,4 +69,36 @@ public class AttributeListTestCase extends SearchDefinitionTestCase { assertTrue(!attributes.hasNext()); } + @Test + public void array_of_struct_field_is_derived_into_array_attributes() throws IOException, ParseException { + Search search = SearchBuilder.buildFromFile("src/test/derived/array_of_struct_attribute/test.sd"); + Iterator<Attribute> attributes = new AttributeFields(search).attributeIterator(); + + assertAttribute("elem_array.name", Attribute.Type.STRING, Attribute.CollectionType.ARRAY, attributes.next()); + assertAttribute("elem_array.weight", Attribute.Type.INTEGER, Attribute.CollectionType.ARRAY, attributes.next()); + assertTrue(!attributes.hasNext()); + } + + private static void assertAttribute(String name, Attribute.Type type, Attribute.CollectionType collection, Attribute attr) { + assertEquals(name, attr.getName()); + assertEquals(type, attr.getType()); + assertEquals(collection, attr.getCollectionType()); + } + + @Test + public void only_zcurve_attribute_is_derived_from_array_of_position_field() throws ParseException { + Search search = SearchBuilder.createFromString( + joinLines("search test {", + " document test {", + " field pos_array type array<position> {", + " indexing: attribute", + " }", + " }", + "}")).getSearch(); + Iterator<Attribute> attributes = new AttributeFields(search).attributeIterator(); + + assertAttribute("pos_array_zcurve", Attribute.Type.LONG, Attribute.CollectionType.ARRAY, attributes.next()); + assertTrue(!attributes.hasNext()); + } + } diff --git a/config-model/src/test/java/com/yahoo/searchdefinition/derived/ExportingTestCase.java b/config-model/src/test/java/com/yahoo/searchdefinition/derived/ExportingTestCase.java index 4600f6ae4c6..dc2d3b7cea1 100644 --- a/config-model/src/test/java/com/yahoo/searchdefinition/derived/ExportingTestCase.java +++ b/config-model/src/test/java/com/yahoo/searchdefinition/derived/ExportingTestCase.java @@ -139,4 +139,9 @@ public class ExportingTestCase extends AbstractExportingTestCase { assertCorrectDeriving("tensor"); } + @Test + public void testArrayOfStructAttribute() throws IOException, ParseException { + assertCorrectDeriving("array_of_struct_attribute"); + } + } diff --git a/container-search/src/main/java/com/yahoo/prelude/query/SameElementItem.java b/container-search/src/main/java/com/yahoo/prelude/query/SameElementItem.java index e1b5842529f..70e9357e7cf 100644 --- a/container-search/src/main/java/com/yahoo/prelude/query/SameElementItem.java +++ b/container-search/src/main/java/com/yahoo/prelude/query/SameElementItem.java @@ -1,10 +1,10 @@ // Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.prelude.query; - import com.google.common.annotations.Beta; import com.yahoo.protect.Validator; +import java.nio.ByteBuffer; import java.util.Iterator; /** @@ -14,34 +14,30 @@ import java.util.Iterator; * @author baldersheim */ @Beta -public class SameElementItem extends CompositeIndexedItem { +public class SameElementItem extends CompositeItem { + + private final String fieldName; public SameElementItem(String commonPath) { - setIndexName(commonPath); + Validator.ensureNonEmpty("Field name", commonPath); + this.fieldName = commonPath; } @Override - public String getIndexedString() { - StringBuilder buf = new StringBuilder(); - - for (Iterator<Item> i = getItemIterator(); i.hasNext();) { - IndexedItem indexedItem = (IndexedItem) i.next(); - - buf.append(indexedItem.getIndexedString()); - if (i.hasNext()) { - buf.append(' '); - } - } - return buf.toString(); + protected void encodeThis(ByteBuffer buffer) { + super.encodeThis(buffer); + putString(fieldName, buffer); } + @Override protected void appendHeadingString(StringBuilder buffer) { } + @Override protected void appendBodyString(StringBuilder buffer) { - appendIndexString(buffer); + buffer.append(fieldName).append(':'); buffer.append('{'); for (Iterator<Item> i = getItemIterator(); i.hasNext();) { TermItem term = (TermItem) i.next(); - buffer.append(term.getIndexName()).append(':').append(term.getIndexedString()); + buffer.append(extractSubFieldName(term)).append(':').append(term.getIndexedString()); if (i.hasNext()) { buffer.append(' '); } @@ -50,16 +46,14 @@ public class SameElementItem extends CompositeIndexedItem { } @Override - public int getNumWords() { - return getItemCount(); - } - - @Override protected void adding(Item item) { Validator.ensureInstanceOf("Child item", item, TermItem.class); TermItem asTerm = (TermItem) item; Validator.ensureNonEmpty("Struct fieldname", asTerm.getIndexName()); Validator.ensureNonEmpty("Query term", asTerm.getIndexedString()); + Validator.ensure("Struct fieldname starts with '" + getFieldName() + ".'", + !asTerm.getIndexName().startsWith(fieldName+".")); + item.setIndexName(fieldName + '.' + asTerm.getIndexName()); } @Override public ItemType getItemType() { @@ -70,4 +64,8 @@ public class SameElementItem extends CompositeIndexedItem { public String getName() { return getItemType().toString(); } + public String getFieldName() { return fieldName; } + public String extractSubFieldName(TermItem full) { + return full.getIndexName().substring(getFieldName().length()+1); + } } diff --git a/container-search/src/main/java/com/yahoo/prelude/query/WeakAndItem.java b/container-search/src/main/java/com/yahoo/prelude/query/WeakAndItem.java index 0384dfdca12..708c48f0954 100644 --- a/container-search/src/main/java/com/yahoo/prelude/query/WeakAndItem.java +++ b/container-search/src/main/java/com/yahoo/prelude/query/WeakAndItem.java @@ -42,11 +42,7 @@ public final class WeakAndItem extends NonReducibleCompositeItem { **/ public WeakAndItem(String index, int N) { this.N = N; - if (index == null) { - this.index = ""; - } else { - this.index = index; - } + this.index = (index == null) ? "" : index; } public WeakAndItem(int N) { this("", N); @@ -54,12 +50,7 @@ public final class WeakAndItem extends NonReducibleCompositeItem { /** Sets the index name of all subitems of this */ public void setIndexName(String index) { - String toSet; - if (index == null) { - toSet = ""; - } else { - toSet = index; - } + String toSet = (index == null) ? "" : index; super.setIndexName(toSet); this.index = toSet; } 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 4c5dfaabed7..12aec81a5f8 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 @@ -594,26 +594,22 @@ public class VespaSerializer { static boolean serialize(StringBuilder destination, Item item, boolean includeField) { - SameElementItem phrase = (SameElementItem) item; - String annotations = leafAnnotations(phrase); + SameElementItem sameElement = (SameElementItem) item; if (includeField) { - destination.append(normalizeIndexName(phrase.getIndexName())).append(" contains "); - - } - if (annotations.length() > 0) { - destination.append("([{").append(annotations).append("}]"); + destination.append(normalizeIndexName(sameElement.getFieldName())).append(" contains "); } destination.append(SAME_ELEMENT).append('('); - for (int i = 0; i < phrase.getItemCount(); ++i) { + for (int i = 0; i < sameElement.getItemCount(); ++i) { if (i > 0) { destination.append(", "); } - Item current = phrase.getItem(i); + Item current = sameElement.getItem(i); if (current instanceof WordItem) { - new WordSerializer().serialize(destination, current); - + WordItem modified = (WordItem)current.clone(); + modified.setIndexName(sameElement.extractSubFieldName(modified)); + new WordSerializer().serialize(destination, modified); } else { throw new IllegalArgumentException( "Serializing of " + current.getClass().getSimpleName() @@ -621,9 +617,7 @@ public class VespaSerializer { } } destination.append(')'); - if (annotations.length() > 0) { - destination.append(')'); - } + return false; } 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 292bb6d0f5a..c6097b1bc73 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 @@ -542,7 +542,7 @@ public class YqlParser implements Parser { for (OperatorNode<ExpressionOperator> word : ast.<List<OperatorNode<ExpressionOperator>>> getArgument(1)) { sameElement.addItem(buildTermSearch(word)); } - return leafStyleSettings(ast, sameElement); + return sameElement; } @NonNull diff --git a/container-search/src/test/java/com/yahoo/prelude/query/test/SameElementItemTestCase.java b/container-search/src/test/java/com/yahoo/prelude/query/test/SameElementItemTestCase.java index ff3ca53319f..01c03fcd802 100644 --- a/container-search/src/test/java/com/yahoo/prelude/query/test/SameElementItemTestCase.java +++ b/container-search/src/test/java/com/yahoo/prelude/query/test/SameElementItemTestCase.java @@ -22,6 +22,19 @@ public class SameElementItemTestCase { s.addItem(new WordItem("b", "f1")); s.addItem(new WordItem("c")); } + @Test + public void requireAllowCommonPrefix() { + SameElementItem s = new SameElementItem("structa"); + s.addItem(new WordItem("b", "f1")); + s.addItem(new WordItem("c", "structaf2")); + assertEquals("structa:{f1:b structaf2:c}", s.toString()); + } + @Test(expected = IllegalArgumentException.class) + public void requireNoChildrenHasCommonPrefixWithDot() { + SameElementItem s = new SameElementItem("structa"); + s.addItem(new WordItem("b", "f1")); + s.addItem(new WordItem("c", "structa.f2")); + } @Test(expected = IllegalArgumentException.class) public void requireAllChildrenHaveNonEmptyTerm() { SameElementItem s = new SameElementItem("structa"); diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRepositoryMaintenance.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRepositoryMaintenance.java index 4497f55cb85..62e954afba3 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRepositoryMaintenance.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRepositoryMaintenance.java @@ -8,6 +8,7 @@ import com.yahoo.config.provision.Deployer; import com.yahoo.config.provision.Environment; import com.yahoo.config.provision.HostLivenessTracker; import com.yahoo.config.provision.Provisioner; +import com.yahoo.config.provision.SystemName; import com.yahoo.config.provision.Zone; import com.yahoo.jdisc.Metric; import com.yahoo.vespa.hosted.provision.NodeRepository; @@ -65,7 +66,7 @@ public class NodeRepositoryMaintenance extends AbstractComponent { HostLivenessTracker hostLivenessTracker, ServiceMonitor serviceMonitor, Zone zone, Clock clock, Orchestrator orchestrator, Metric metric, ConfigserverConfig configserverConfig) { - DefaultTimes defaults = new DefaultTimes(zone.environment()); + DefaultTimes defaults = new DefaultTimes(zone); jobControl = new JobControl(nodeRepository.database()); infrastructureVersions = new InfrastructureVersions(nodeRepository.database()); @@ -151,7 +152,7 @@ public class NodeRepositoryMaintenance extends AbstractComponent { private final NodeFailer.ThrottlePolicy throttlePolicy; - DefaultTimes(Environment environment) { + DefaultTimes(Zone zone) { failGrace = Duration.ofMinutes(60); periodicRedeployInterval = Duration.ofMinutes(30); operatorChangeRedeployInterval = Duration.ofMinutes(1); @@ -164,13 +165,14 @@ public class NodeRepositoryMaintenance extends AbstractComponent { infrastructureProvisionInterval = Duration.ofMinutes(3); throttlePolicy = NodeFailer.ThrottlePolicy.hosted; + Environment environment = zone.environment(); if (environment.isTest()) retiredExpiry = Duration.ofMinutes(1); // fast turnaround as test envs don't have persistent data else retiredExpiry = Duration.ofDays(4); // give up migrating data after 4 days - if (environment.equals(Environment.prod)) { + if (environment.equals(Environment.prod) && zone.system() == SystemName.main) { inactiveExpiry = Duration.ofHours(4); // enough time for the application owner to discover and redeploy retiredInterval = Duration.ofMinutes(29); dirtyExpiry = Duration.ofHours(2); // enough time to clean the node diff --git a/searchcore/src/tests/proton/documentdb/feedhandler/feedhandler_test.cpp b/searchcore/src/tests/proton/documentdb/feedhandler/feedhandler_test.cpp index 5c0edce0b94..153b1ae2867 100644 --- a/searchcore/src/tests/proton/documentdb/feedhandler/feedhandler_test.cpp +++ b/searchcore/src/tests/proton/documentdb/feedhandler/feedhandler_test.cpp @@ -2,6 +2,7 @@ #include <vespa/persistence/spi/result.h> #include <vespa/document/update/assignvalueupdate.h> +#include <vespa/document/repo/documenttyperepo.h> #include <vespa/searchcore/proton/bucketdb/bucketdbhandler.h> #include <vespa/searchcore/proton/test/bucketfactory.h> #include <vespa/searchcore/proton/common/feedtoken.h> @@ -35,6 +36,7 @@ LOG_SETUP("feedhandler_test"); using document::BucketId; using document::Document; using document::DocumentId; +using document::DocumentType; using document::DocumentTypeRepo; using document::DocumentUpdate; using document::GlobalId; @@ -181,7 +183,9 @@ struct MyFeedView : public test::DummyFeedView { int prune_removed_count; int update_count; SerialNum update_serial; - MyFeedView(const std::shared_ptr<const DocumentTypeRepo> &dtr); + const DocumentType *documentType; + MyFeedView(const std::shared_ptr<const DocumentTypeRepo> &dtr, + const DocTypeName &docTypeName); ~MyFeedView() override; void resetPutLatch(uint32_t count) { putLatch.reset(new vespalib::CountDownLatch(count)); } void preparePut(PutOperation &op) override { @@ -203,6 +207,8 @@ struct MyFeedView : public test::DummyFeedView { if (usePutRdz) { putRdz.run(); } + EXPECT_EQUAL(_docTypeRepo.get(), putOp.getDocument()->getRepo()); + EXPECT_EQUAL(documentType, &putOp.getDocument()->getType()); ++put_count; put_serial = putOp.getSerialNum(); metaStore.allocate(putOp.getDocument()->getId().getGlobalId()); @@ -216,6 +222,7 @@ struct MyFeedView : public test::DummyFeedView { void handleUpdate(FeedToken token, const UpdateOperation &op) override { (void) token; + EXPECT_EQUAL(documentType, &op.getUpdate()->getType()); ++update_count; update_serial = op.getSerialNum(); } @@ -237,7 +244,7 @@ struct MyFeedView : public test::DummyFeedView { } }; -MyFeedView::MyFeedView(const std::shared_ptr<const DocumentTypeRepo> &dtr) +MyFeedView::MyFeedView(const std::shared_ptr<const DocumentTypeRepo> &dtr, const DocTypeName &docTypeName) : test::DummyFeedView(dtr), putRdz(), usePutRdz(false), @@ -250,7 +257,8 @@ MyFeedView::MyFeedView(const std::shared_ptr<const DocumentTypeRepo> &dtr) move_count(0), prune_removed_count(0), update_count(0), - update_serial(0) + update_serial(0), + documentType(dtr->getDocumentType(docTypeName.getName())) {} MyFeedView::~MyFeedView() {} @@ -294,6 +302,13 @@ struct DocumentContext { } }; +struct TwoFieldsSchemaContext : public SchemaContext { + TwoFieldsSchemaContext() + : SchemaContext() + { + addField("i2"); + } +}; struct UpdateContext { DocumentUpdate::SP update; @@ -433,7 +448,7 @@ struct FeedHandlerFixture owner(), _state(), replayConfig(), - feedView(schema.getRepo()), + feedView(schema.getRepo(), schema.getDocType()), _bucketDB(), _bucketDBHandler(_bucketDB), handler(writeService, tlsSpec, schema.getDocType(), _state, owner, @@ -714,15 +729,13 @@ TEST_F("require that update with same document type repo is ok", FeedHandlerFixt TEST_F("require that update with different document type repo can be ok", FeedHandlerFixture) { - SchemaContext schema; - schema.addField("i2"); + TwoFieldsSchemaContext schema; checkUpdate(f, schema, "i1", false, true); } TEST_F("require that update with different document type repo can be rejected", FeedHandlerFixture) { - SchemaContext schema; - schema.addField("i2"); + TwoFieldsSchemaContext schema; checkUpdate(f, schema, "i2", true, true); } @@ -733,18 +746,31 @@ TEST_F("require that update with same document type repo is ok, fallback to crea TEST_F("require that update with different document type repo can be ok, fallback to create document", FeedHandlerFixture) { - SchemaContext schema; - schema.addField("i2"); + TwoFieldsSchemaContext schema; checkUpdate(f, schema, "i1", false, false); } TEST_F("require that update with different document type repo can be rejected, preventing fallback to create document", FeedHandlerFixture) { - SchemaContext schema; - schema.addField("i2"); + TwoFieldsSchemaContext schema; checkUpdate(f, schema, "i2", true, false); } +TEST_F("require that put with different document type repo is ok", FeedHandlerFixture) +{ + TwoFieldsSchemaContext schema; + DocumentContext doc_context("doc:test:foo", *schema.builder); + auto op = std::make_unique<PutOperation>(doc_context.bucketId, + Timestamp(10), doc_context.doc); + FeedTokenContext token_context; + EXPECT_EQUAL(schema.getRepo().get(), op->getDocument()->getRepo()); + EXPECT_NOT_EQUAL(f.schema.getRepo().get(), op->getDocument()->getRepo()); + EXPECT_NOT_EQUAL(f.feedView.documentType, &op->getDocument()->getType()); + f.handler.performOperation(std::move(token_context.token), std::move(op)); + EXPECT_EQUAL(1, f.feedView.put_count); + EXPECT_EQUAL(1, f.tls_writer.store_count); +} + } // namespace TEST_MAIN() diff --git a/searchcore/src/tests/proton/matching/query_test.cpp b/searchcore/src/tests/proton/matching/query_test.cpp index eb49603f71d..7875e7ec4aa 100644 --- a/searchcore/src/tests/proton/matching/query_test.cpp +++ b/searchcore/src/tests/proton/matching/query_test.cpp @@ -1,7 +1,6 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. // Unit tests for query. -#include <vespa/document/datatype/positiondatatype.h> #include <vespa/searchcore/proton/matching/fakesearchcontext.h> #include <vespa/searchcore/proton/matching/matchdatareservevisitor.h> #include <vespa/searchcore/proton/matching/blueprintbuilder.h> @@ -26,8 +25,9 @@ #include <vespa/searchlib/queryeval/simpleresult.h> #include <vespa/searchlib/queryeval/fake_requestcontext.h> #include <vespa/searchlib/queryeval/termasstring.h> +#include <vespa/document/datatype/positiondatatype.h> + #include <vespa/vespalib/testkit/testapp.h> -#include <vector> using document::PositionDataType; using search::fef::FieldInfo; @@ -62,8 +62,7 @@ using std::vector; namespace fef_test = search::fef::test; using CollectionType = FieldInfo::CollectionType; -namespace proton { -namespace matching { +namespace proton::matching { namespace { class Test : public vespalib::TestApp { @@ -175,6 +174,12 @@ Node::UP buildQueryTree(const ViewResolver &resolver, query_builder.addPhrase(2, field, 7, Weight(0)); query_builder.addStringTerm(phrase_term, field, 8, Weight(0)); query_builder.addStringTerm(phrase_term, field, 9, Weight(0)); +#if 0 + //Todo add testing when SameElement blueprints are ready + query_builder.addSameElement(2, field); + query_builder.addStringTerm(string_term, field, 10, Weight(0)); + query_builder.addStringTerm(prefix_term, field, 11, Weight(0)); +#endif Node::UP node = query_builder.build(); ResolveViewVisitor visitor(resolver, idxEnv); @@ -222,19 +227,19 @@ public: EXPECT_EQUAL((double)estimatedHitCount / doc_count, n.field(0).getDocFreq()); } - virtual void visit(ProtonNumberTerm &n) override { checkNode(n, 1, false); } - virtual void visit(ProtonLocationTerm &n) override { checkNode(n, 0, true); } - virtual void visit(ProtonPrefixTerm &n) override { checkNode(n, 1, false); } - virtual void visit(ProtonRangeTerm &n) override { checkNode(n, 2, false); } - virtual void visit(ProtonStringTerm &n) override { checkNode(n, 2, false); } - virtual void visit(ProtonSubstringTerm &n) override { checkNode(n, 0, true); } - virtual void visit(ProtonSuffixTerm &n) override { checkNode(n, 2, false); } - virtual void visit(ProtonPhrase &n) override { checkNode(n, 0, true); } - virtual void visit(ProtonWeightedSetTerm &) override {} - virtual void visit(ProtonDotProduct &) override {} - virtual void visit(ProtonWandTerm &) override {} - virtual void visit(ProtonPredicateQuery &) override {} - virtual void visit(ProtonRegExpTerm &) override {} + void visit(ProtonNumberTerm &n) override { checkNode(n, 1, false); } + void visit(ProtonLocationTerm &n) override { checkNode(n, 0, true); } + void visit(ProtonPrefixTerm &n) override { checkNode(n, 1, false); } + void visit(ProtonRangeTerm &n) override { checkNode(n, 2, false); } + void visit(ProtonStringTerm &n) override { checkNode(n, 2, false); } + void visit(ProtonSubstringTerm &n) override { checkNode(n, 0, true); } + void visit(ProtonSuffixTerm &n) override { checkNode(n, 2, false); } + void visit(ProtonPhrase &n) override { checkNode(n, 0, true); } + void visit(ProtonWeightedSetTerm &) override {} + void visit(ProtonDotProduct &) override {} + void visit(ProtonWandTerm &) override {} + void visit(ProtonPredicateQuery &) override {} + void visit(ProtonRegExpTerm &) override {} }; void Test::requireThatTermsAreLookedUp() { @@ -354,12 +359,12 @@ class SetUpTermDataTestCheckerVisitor int Main() { return 0; } public: - virtual void visit(ProtonNumberTerm &) override {} - virtual void visit(ProtonLocationTerm &) override {} - virtual void visit(ProtonPrefixTerm &) override {} - virtual void visit(ProtonRangeTerm &) override {} + void visit(ProtonNumberTerm &) override {} + void visit(ProtonLocationTerm &) override {} + void visit(ProtonPrefixTerm &) override {} + void visit(ProtonRangeTerm &) override {} - virtual void visit(ProtonStringTerm &n) override { + void visit(ProtonStringTerm &n) override { const ITermData &term_data = n; EXPECT_EQUAL(string_weight.percent(), term_data.getWeight().percent()); @@ -375,17 +380,17 @@ public: } } - virtual void visit(ProtonSubstringTerm &) override {} - virtual void visit(ProtonSuffixTerm &) override {} - virtual void visit(ProtonPhrase &n) override { + void visit(ProtonSubstringTerm &) override {} + void visit(ProtonSuffixTerm &) override {} + void visit(ProtonPhrase &n) override { const ITermData &term_data = n; EXPECT_EQUAL(2u, term_data.getPhraseLength()); } - virtual void visit(ProtonWeightedSetTerm &) override {} - virtual void visit(ProtonDotProduct &) override {} - virtual void visit(ProtonWandTerm &) override {} - virtual void visit(ProtonPredicateQuery &) override {} - virtual void visit(ProtonRegExpTerm &) override {} + void visit(ProtonWeightedSetTerm &) override {} + void visit(ProtonDotProduct &) override {} + void visit(ProtonWandTerm &) override {} + void visit(ProtonPredicateQuery &) override {} + void visit(ProtonRegExpTerm &) override {} }; void Test::requireThatTermDataIsFilledIn() { @@ -855,7 +860,7 @@ Test::requireThatWhiteListBlueprintCanBeUsed() EXPECT_EQUAL(exp, act); } -Test::~Test() {} +Test::~Test() = default; int Test::Main() @@ -877,6 +882,7 @@ Test::Main() TEST_CALL(requireThatNearIteratorsCanBeBuilt); TEST_CALL(requireThatONearIteratorsCanBeBuilt); TEST_CALL(requireThatPhraseIteratorsCanBeBuilt); + //TODO Add SameElement testing TEST_CALL(requireThatUnknownFieldActsEmpty); TEST_CALL(requireThatIllegalFieldsAreIgnored); TEST_CALL(requireThatQueryGluesEverythingTogether); @@ -893,7 +899,6 @@ Test::Main() } // namespace -} // namespace matching -} // namespace proton +} // namespace proton::matching TEST_APPHOOK(proton::matching::Test); diff --git a/searchcore/src/tests/proton/matching/querynodes_test.cpp b/searchcore/src/tests/proton/matching/querynodes_test.cpp index f8a419ba15b..7b6fdd1ae88 100644 --- a/searchcore/src/tests/proton/matching/querynodes_test.cpp +++ b/searchcore/src/tests/proton/matching/querynodes_test.cpp @@ -1,11 +1,7 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. // Unit tests for querynodes. -#include <vespa/log/log.h> -LOG_SETUP("querynodes_test"); - #include <vespa/searchcore/proton/matching/querynodes.h> - #include <vespa/searchcore/proton/matching/fakesearchcontext.h> #include <vespa/searchcore/proton/matching/blueprintbuilder.h> #include <vespa/searchcore/proton/matching/matchdatareservevisitor.h> @@ -33,11 +29,12 @@ LOG_SETUP("querynodes_test"); #include <vespa/searchlib/queryeval/fake_search.h> #include <vespa/searchlib/queryeval/fake_requestcontext.h> #include <vespa/vespalib/testkit/testapp.h> -#include <cstdarg> -#include <string> -#include <vector> + #include <vespa/searchlib/attribute/singlenumericattribute.hpp> +#include <vespa/log/log.h> +LOG_SETUP("querynodes_test"); + using search::fef::FieldInfo; using search::fef::FieldType; using search::fef::MatchData; @@ -210,9 +207,8 @@ public: }; typedef QueryBuilder<ProtonNodeTypes> QB; -struct Phrase { - void addToBuilder(QB& b) { b.addPhrase(2, view, id, weight); } -}; +struct Phrase { void addToBuilder(QB& b) { b.addPhrase(2, view, id, weight); }}; +struct SameElement { void addToBuilder(QB& b) { b.addSameElement(2, view); }}; struct Near { void addToBuilder(QB& b) { b.addNear(2, distance); } }; struct ONear { void addToBuilder(QB& b) { b.addONear(2, distance); } }; struct Or { void addToBuilder(QB& b) { b.addOr(2); } }; @@ -466,6 +462,11 @@ TEST("requireThatPhrasesGetProperBlending") { TEST_DO(checkProperBlending<Phrase>()); } +TEST("requireThatSameElementGetProperBlending") { + //TODO SameEelement needs proper testing/implementation + //TEST_DO(checkProperBlending<SameElement>()); +} + TEST("requireThatNearGetProperBlending") { TEST_DO(checkProperBlendingWithParent<Near>()); } diff --git a/searchcore/src/vespa/searchcore/proton/feedoperation/putoperation.cpp b/searchcore/src/vespa/searchcore/proton/feedoperation/putoperation.cpp index a6d34b696ca..efac7297c67 100644 --- a/searchcore/src/vespa/searchcore/proton/feedoperation/putoperation.cpp +++ b/searchcore/src/vespa/searchcore/proton/feedoperation/putoperation.cpp @@ -49,6 +49,15 @@ PutOperation::deserialize(vespalib::nbostream &is, _serializedDocSize = oldSize - is.size(); } +void +PutOperation::deserializeDocument(const DocumentTypeRepo &repo) +{ + vespalib::nbostream stream; + _doc->serialize(stream); + auto fixedDoc = std::make_shared<Document>(repo, stream); + _doc = std::move(fixedDoc); +} + vespalib::string PutOperation::toString() const { diff --git a/searchcore/src/vespa/searchcore/proton/feedoperation/putoperation.h b/searchcore/src/vespa/searchcore/proton/feedoperation/putoperation.h index 7e9dee2cbc0..33330692fab 100644 --- a/searchcore/src/vespa/searchcore/proton/feedoperation/putoperation.h +++ b/searchcore/src/vespa/searchcore/proton/feedoperation/putoperation.h @@ -21,6 +21,7 @@ public: virtual void serialize(vespalib::nbostream &os) const override; virtual void deserialize(vespalib::nbostream &is, const document::DocumentTypeRepo &repo) override; + void deserializeDocument(const document::DocumentTypeRepo &repo); virtual vespalib::string toString() const override; }; diff --git a/searchcore/src/vespa/searchcore/proton/feedoperation/updateoperation.cpp b/searchcore/src/vespa/searchcore/proton/feedoperation/updateoperation.cpp index fa5bbee8e6d..beaf719dc5c 100644 --- a/searchcore/src/vespa/searchcore/proton/feedoperation/updateoperation.cpp +++ b/searchcore/src/vespa/searchcore/proton/feedoperation/updateoperation.cpp @@ -8,6 +8,7 @@ LOG_SETUP(".proton.feedoperation.updateoperation"); using document::BucketId; +using document::DocumentType; using document::DocumentTypeRepo; using document::DocumentUpdate; using storage::spi::Timestamp; @@ -46,12 +47,9 @@ UpdateOperation::UpdateOperation(const BucketId &bucketId, { } - void -UpdateOperation::serialize(vespalib::nbostream &os) const +UpdateOperation::serializeUpdate(vespalib::nbostream &os) const { - assertValidBucketId(_upd->getId()); - DocumentOperation::serialize(os); if (getType() == FeedOperation::UPDATE_42) { _upd->serialize42(os); } else { @@ -59,19 +57,33 @@ UpdateOperation::serialize(vespalib::nbostream &os) const } } +void +UpdateOperation::deserializeUpdate(vespalib::nbostream &is, const document::DocumentTypeRepo &repo) +{ + document::ByteBuffer buf(is.peek(), is.size()); + using Version = DocumentUpdate::SerializeVersion; + Version version = ((getType() == FeedOperation::UPDATE_42) ? Version::SERIALIZE_42 : Version::SERIALIZE_HEAD); + DocumentUpdate::SP update(std::make_shared<DocumentUpdate>(repo, buf, version)); + is.adjustReadPos(buf.getPos()); + _upd = std::move(update); +} + +void +UpdateOperation::serialize(vespalib::nbostream &os) const +{ + assertValidBucketId(_upd->getId()); + DocumentOperation::serialize(os); + serializeUpdate(os); +} + void UpdateOperation::deserialize(vespalib::nbostream &is, const DocumentTypeRepo &repo) { DocumentOperation::deserialize(is, repo); - document::ByteBuffer buf(is.peek(), is.size()); - using Version = DocumentUpdate::SerializeVersion; - Version version = ((getType() == FeedOperation::UPDATE_42) ? Version::SERIALIZE_42 : Version::SERIALIZE_HEAD); try { - DocumentUpdate::SP update(std::make_shared<DocumentUpdate>(repo, buf, version)); - is.adjustReadPos(buf.getPos()); - _upd = update; + deserializeUpdate(is, repo); } catch (document::DocumentTypeNotFoundException &e) { LOG(warning, "Failed deserialize update operation using unknown document type '%s'", e.getDocumentTypeName().c_str()); @@ -80,6 +92,14 @@ UpdateOperation::deserialize(vespalib::nbostream &is, } } +void +UpdateOperation::deserializeUpdate(const DocumentTypeRepo &repo) +{ + vespalib::nbostream stream; + serializeUpdate(stream); + deserializeUpdate(stream, repo); +} + vespalib::string UpdateOperation::toString() const { return make_string("%s(%s, %s)", ((getType() == FeedOperation::UPDATE_42) ? "Update42" : "Update"), diff --git a/searchcore/src/vespa/searchcore/proton/feedoperation/updateoperation.h b/searchcore/src/vespa/searchcore/proton/feedoperation/updateoperation.h index 6e061f79f30..7886231af82 100644 --- a/searchcore/src/vespa/searchcore/proton/feedoperation/updateoperation.h +++ b/searchcore/src/vespa/searchcore/proton/feedoperation/updateoperation.h @@ -3,7 +3,10 @@ #include "documentoperation.h" -namespace document { class DocumentUpdate; } +namespace document { +class DocumentTypeRepo; +class DocumentUpdate; +} namespace proton { @@ -16,6 +19,8 @@ private: const document::BucketId &bucketId, const storage::spi::Timestamp ×tamp, const DocumentUpdateSP &upd); + void serializeUpdate(vespalib::nbostream &os) const; + void deserializeUpdate(vespalib::nbostream &is, const document::DocumentTypeRepo &repo); public: UpdateOperation(); UpdateOperation(Type type); @@ -26,6 +31,7 @@ public: const DocumentUpdateSP &getUpdate() const { return _upd; } void serialize(vespalib::nbostream &os) const override; void deserialize(vespalib::nbostream &is, const document::DocumentTypeRepo &repo) override; + void deserializeUpdate(const document::DocumentTypeRepo &repo); virtual vespalib::string toString() const override; static UpdateOperation makeOldUpdate(const document::BucketId &bucketId, const storage::spi::Timestamp ×tamp, diff --git a/searchcore/src/vespa/searchcore/proton/matching/blueprintbuilder.cpp b/searchcore/src/vespa/searchcore/proton/matching/blueprintbuilder.cpp index 97fc1905f50..165fc67179a 100644 --- a/searchcore/src/vespa/searchcore/proton/matching/blueprintbuilder.cpp +++ b/searchcore/src/vespa/searchcore/proton/matching/blueprintbuilder.cpp @@ -10,8 +10,7 @@ using namespace search::queryeval; -namespace proton { -namespace matching { +namespace proton::matching { namespace { @@ -124,29 +123,31 @@ private: } protected: - virtual void visit(ProtonAnd &n) override { buildIntermediate(new AndBlueprint(), n); } - virtual void visit(ProtonAndNot &n) override { buildIntermediate(new AndNotBlueprint(), n); } - virtual void visit(ProtonOr &n) override { buildIntermediate(new OrBlueprint(), n); } - virtual void visit(ProtonWeakAnd &n) override { buildWeakAnd(n); } - virtual void visit(ProtonEquiv &n) override { buildEquiv(n); } - virtual void visit(ProtonRank &n) override { buildIntermediate(new RankBlueprint(), n); } - virtual void visit(ProtonNear &n) override { buildIntermediate(new NearBlueprint(n.getDistance()), n); } - virtual void visit(ProtonONear &n) override { buildIntermediate(new ONearBlueprint(n.getDistance()), n); } - - virtual void visit(ProtonWeightedSetTerm &n) override { buildTerm(n); } - virtual void visit(ProtonDotProduct &n) override { buildTerm(n); } - virtual void visit(ProtonWandTerm &n) override { buildTerm(n); } - - virtual void visit(ProtonPhrase &n) override { buildTerm(n); } - virtual void visit(ProtonNumberTerm &n) override { buildTerm(n); } - virtual void visit(ProtonLocationTerm &n) override { buildTerm(n); } - virtual void visit(ProtonPrefixTerm &n) override { buildTerm(n); } - virtual void visit(ProtonRangeTerm &n) override { buildTerm(n); } - virtual void visit(ProtonStringTerm &n) override { buildTerm(n); } - virtual void visit(ProtonSubstringTerm &n) override { buildTerm(n); } - virtual void visit(ProtonSuffixTerm &n) override { buildTerm(n); } - virtual void visit(ProtonPredicateQuery &n) override { buildTerm(n); } - virtual void visit(ProtonRegExpTerm &n) override { buildTerm(n); } + void visit(ProtonAnd &n) override { buildIntermediate(new AndBlueprint(), n); } + void visit(ProtonAndNot &n) override { buildIntermediate(new AndNotBlueprint(), n); } + void visit(ProtonOr &n) override { buildIntermediate(new OrBlueprint(), n); } + void visit(ProtonWeakAnd &n) override { buildWeakAnd(n); } + void visit(ProtonEquiv &n) override { buildEquiv(n); } + void visit(ProtonRank &n) override { buildIntermediate(new RankBlueprint(), n); } + void visit(ProtonNear &n) override { buildIntermediate(new NearBlueprint(n.getDistance()), n); } + void visit(ProtonONear &n) override { buildIntermediate(new ONearBlueprint(n.getDistance()), n); } + void visit(ProtonSameElement &n) override { buildIntermediate(nullptr /*new SameElementBlueprint())*/, n); } + + + void visit(ProtonWeightedSetTerm &n) override { buildTerm(n); } + void visit(ProtonDotProduct &n) override { buildTerm(n); } + void visit(ProtonWandTerm &n) override { buildTerm(n); } + + void visit(ProtonPhrase &n) override { buildTerm(n); } + void visit(ProtonNumberTerm &n) override { buildTerm(n); } + void visit(ProtonLocationTerm &n) override { buildTerm(n); } + void visit(ProtonPrefixTerm &n) override { buildTerm(n); } + void visit(ProtonRangeTerm &n) override { buildTerm(n); } + void visit(ProtonStringTerm &n) override { buildTerm(n); } + void visit(ProtonSubstringTerm &n) override { buildTerm(n); } + void visit(ProtonSuffixTerm &n) override { buildTerm(n); } + void visit(ProtonPredicateQuery &n) override { buildTerm(n); } + void visit(ProtonRegExpTerm &n) override { buildTerm(n); } public: BlueprintBuilderVisitor(const IRequestContext & requestContext, ISearchContext &context) : @@ -174,5 +175,4 @@ BlueprintBuilder::build(const IRequestContext & requestContext, return result; } -} // namespace matching -} // namespace proton +} diff --git a/searchcore/src/vespa/searchcore/proton/matching/matchdatareservevisitor.h b/searchcore/src/vespa/searchcore/proton/matching/matchdatareservevisitor.h index ebe4e9b2ad7..a20f648ca1c 100644 --- a/searchcore/src/vespa/searchcore/proton/matching/matchdatareservevisitor.h +++ b/searchcore/src/vespa/searchcore/proton/matching/matchdatareservevisitor.h @@ -22,13 +22,14 @@ public: template <class TermNode> void visitTerm(TermNode &n) { n.allocateTerms(_mdl); } - virtual void visit(ProtonNodeTypes::Equiv &n) override { + void visit(ProtonNodeTypes::Equiv &n) override { MatchDataReserveVisitor subAllocator(n.children_mdl); for (size_t i = 0; i < n.getChildren().size(); ++i) { n.getChildren()[i]->accept(subAllocator); } n.allocateTerms(_mdl); } + void visit(ProtonNodeTypes::SameElement &) override { } MatchDataReserveVisitor(search::fef::MatchDataLayout &mdl) : _mdl(mdl) {} }; diff --git a/searchcore/src/vespa/searchcore/proton/matching/query.cpp b/searchcore/src/vespa/searchcore/proton/matching/query.cpp index 9181205bb19..8896e4d35c8 100644 --- a/searchcore/src/vespa/searchcore/proton/matching/query.cpp +++ b/searchcore/src/vespa/searchcore/proton/matching/query.cpp @@ -78,8 +78,8 @@ void AddLocationNode(const string &location_str, Node::UP &query_tree, Location } } // namespace -Query::Query() {} -Query::~Query() {} +Query::Query() = default; +Query::~Query() = default; bool Query::buildTree(const vespalib::stringref &stack, const string &location, diff --git a/searchcore/src/vespa/searchcore/proton/matching/querynodes.cpp b/searchcore/src/vespa/searchcore/proton/matching/querynodes.cpp index 63302424db6..b0d45ee0684 100644 --- a/searchcore/src/vespa/searchcore/proton/matching/querynodes.cpp +++ b/searchcore/src/vespa/searchcore/proton/matching/querynodes.cpp @@ -30,7 +30,7 @@ namespace proton::matching { ProtonTermData::ProtonTermData() = default; ProtonTermData::ProtonTermData(const ProtonTermData &) = default; ProtonTermData & ProtonTermData::operator = (const ProtonTermData &) = default; -ProtonTermData::~ProtonTermData() { } +ProtonTermData::~ProtonTermData() = default; void ProtonTermData::setDocumentFrequency(double freq) @@ -42,9 +42,9 @@ ProtonTermData::setDocumentFrequency(double freq) void ProtonTermData::resolve(const ViewResolver &resolver, - const IIndexEnvironment &idxEnv, - const string &view, - bool forceFilter) + const IIndexEnvironment &idxEnv, + const string &view, + bool forceFilter) { std::vector<string> fields; resolver.resolve(((view == "") ? "default" : view), fields); diff --git a/searchcore/src/vespa/searchcore/proton/matching/querynodes.h b/searchcore/src/vespa/searchcore/proton/matching/querynodes.h index ca6c8c75310..986c5d2dde9 100644 --- a/searchcore/src/vespa/searchcore/proton/matching/querynodes.h +++ b/searchcore/src/vespa/searchcore/proton/matching/querynodes.h @@ -104,13 +104,15 @@ struct ProtonTerm : public ProtonTermBase<Base> { ~ProtonTerm() {} }; -typedef search::query::SimpleAnd ProtonAnd; -typedef search::query::SimpleAndNot ProtonAndNot; -typedef search::query::SimpleNear ProtonNear; -typedef search::query::SimpleONear ProtonONear; -typedef search::query::SimpleOr ProtonOr; -typedef search::query::SimpleRank ProtonRank; -typedef search::query::SimpleWeakAnd ProtonWeakAnd; +typedef search::query::SimpleAnd ProtonAnd; +typedef search::query::SimpleAndNot ProtonAndNot; +typedef search::query::SimpleNear ProtonNear; +typedef search::query::SimpleONear ProtonONear; +typedef search::query::SimpleOr ProtonOr; +typedef search::query::SimpleRank ProtonRank; +typedef search::query::SimpleWeakAnd ProtonWeakAnd; +typedef search::query::SimpleSameElement ProtonSameElement; + struct ProtonEquiv final : public ProtonTermBase<search::query::Equiv> { @@ -121,6 +123,7 @@ struct ProtonEquiv final : public ProtonTermBase<search::query::Equiv> typedef ProtonTerm<search::query::LocationTerm> ProtonLocationTerm; typedef ProtonTerm<search::query::NumberTerm> ProtonNumberTerm; typedef ProtonTerm<search::query::Phrase> ProtonPhrase; + typedef ProtonTerm<search::query::PrefixTerm> ProtonPrefixTerm; typedef ProtonTerm<search::query::RangeTerm> ProtonRangeTerm; typedef ProtonTerm<search::query::StringTerm> ProtonStringTerm; @@ -142,6 +145,7 @@ struct ProtonNodeTypes { typedef ProtonONear ONear; typedef ProtonOr Or; typedef ProtonPhrase Phrase; + typedef ProtonSameElement SameElement; typedef ProtonPrefixTerm PrefixTerm; typedef ProtonRangeTerm RangeTerm; typedef ProtonRank Rank; diff --git a/searchcore/src/vespa/searchcore/proton/matching/termdatafromnode.cpp b/searchcore/src/vespa/searchcore/proton/matching/termdatafromnode.cpp index 26b765cf3cf..3fd4000bf9f 100644 --- a/searchcore/src/vespa/searchcore/proton/matching/termdatafromnode.cpp +++ b/searchcore/src/vespa/searchcore/proton/matching/termdatafromnode.cpp @@ -4,8 +4,7 @@ #include "querynodes.h" #include <vespa/searchlib/query/tree/customtypevisitor.h> -namespace proton { -namespace matching { +namespace proton::matching { namespace { struct TermDataFromTermVisitor @@ -19,29 +18,30 @@ struct TermDataFromTermVisitor data = &n; } - virtual void visit(ProtonAnd &) override {} - virtual void visit(ProtonAndNot &) override {} - virtual void visit(ProtonNear &) override {} - virtual void visit(ProtonONear &) override {} - virtual void visit(ProtonOr &) override {} - virtual void visit(ProtonRank &) override {} - virtual void visit(ProtonWeakAnd &) override {} - - virtual void visit(ProtonWeightedSetTerm &n) override { visitTerm(n); } - virtual void visit(ProtonDotProduct &n) override { visitTerm(n); } - virtual void visit(ProtonWandTerm &n) override { visitTerm(n); } - virtual void visit(ProtonPhrase &n) override { visitTerm(n); } - virtual void visit(ProtonEquiv &n) override { visitTerm(n); } - - virtual void visit(ProtonNumberTerm &n) override { visitTerm(n); } - virtual void visit(ProtonLocationTerm &n) override { visitTerm(n); } - virtual void visit(ProtonPrefixTerm &n) override { visitTerm(n); } - virtual void visit(ProtonRangeTerm &n) override { visitTerm(n); } - virtual void visit(ProtonStringTerm &n) override { visitTerm(n); } - virtual void visit(ProtonSubstringTerm &n) override { visitTerm(n); } - virtual void visit(ProtonSuffixTerm &n) override { visitTerm(n); } - virtual void visit(ProtonPredicateQuery &) override { } - virtual void visit(ProtonRegExpTerm &n) override { visitTerm(n); } + void visit(ProtonAnd &) override {} + void visit(ProtonAndNot &) override {} + void visit(ProtonNear &) override {} + void visit(ProtonONear &) override {} + void visit(ProtonOr &) override {} + void visit(ProtonRank &) override {} + void visit(ProtonWeakAnd &) override {} + void visit(ProtonSameElement &) override { } + + void visit(ProtonWeightedSetTerm &n) override { visitTerm(n); } + void visit(ProtonDotProduct &n) override { visitTerm(n); } + void visit(ProtonWandTerm &n) override { visitTerm(n); } + void visit(ProtonPhrase &n) override { visitTerm(n); } + void visit(ProtonEquiv &n) override { visitTerm(n); } + + void visit(ProtonNumberTerm &n) override { visitTerm(n); } + void visit(ProtonLocationTerm &n) override { visitTerm(n); } + void visit(ProtonPrefixTerm &n) override { visitTerm(n); } + void visit(ProtonRangeTerm &n) override { visitTerm(n); } + void visit(ProtonStringTerm &n) override { visitTerm(n); } + void visit(ProtonSubstringTerm &n) override { visitTerm(n); } + void visit(ProtonSuffixTerm &n) override { visitTerm(n); } + void visit(ProtonPredicateQuery &) override { } + void visit(ProtonRegExpTerm &n) override { visitTerm(n); } }; } // namespace @@ -53,5 +53,4 @@ termDataFromNode(const search::query::Node &node) return visitor.data; } -} // namespace matching -} // namespace proton +} diff --git a/searchcore/src/vespa/searchcore/proton/matching/termdatafromnode.h b/searchcore/src/vespa/searchcore/proton/matching/termdatafromnode.h index 3e78ace1900..e445dbcfc50 100644 --- a/searchcore/src/vespa/searchcore/proton/matching/termdatafromnode.h +++ b/searchcore/src/vespa/searchcore/proton/matching/termdatafromnode.h @@ -2,16 +2,13 @@ #pragma once - namespace search { namespace query { class Node; } } -namespace proton { -namespace matching { +namespace proton::matching { class ProtonTermData; const ProtonTermData *termDataFromNode(const search::query::Node &node); -} // namespace matching -} // namespace proton +} diff --git a/searchcore/src/vespa/searchcore/proton/server/feedhandler.cpp b/searchcore/src/vespa/searchcore/proton/server/feedhandler.cpp index ad5372b4af6..90b9bbc7f34 100644 --- a/searchcore/src/vespa/searchcore/proton/server/feedhandler.cpp +++ b/searchcore/src/vespa/searchcore/proton/server/feedhandler.cpp @@ -96,6 +96,14 @@ void FeedHandler::performPut(FeedToken token, PutOperation &op) { } return; } + /* + * Check if document type repos are equal. DocumentTypeRepoFactory::make + * returns the same document type repo if document type configs are equal, + * thus we can just perform a cheaper identity check here. + */ + if (_repo != op.getDocument()->getRepo()) { + op.deserializeDocument(*_repo); + } storeOperation(op, token); if (token) { token->setResult(make_unique<Result>(), false); @@ -344,6 +352,8 @@ FeedHandler::FeedHandler(IThreadingService &writeService, _feedLock(), _feedState(make_shared<InitState>(getDocTypeName())), _activeFeedView(nullptr), + _repo(nullptr), + _documentType(nullptr), _bucketDBHandler(nullptr), _syncLock(), _syncedSerialNum(0), @@ -408,6 +418,14 @@ void FeedHandler::changeToNormalFeedState() { changeFeedState(make_shared<NormalState>(*this)); } +void +FeedHandler::setActiveFeedView(IFeedView *feedView) +{ + _activeFeedView = feedView; + _repo = feedView->getDocumentTypeRepo().get(); + _documentType = _repo->getDocumentType(_docTypeName.getName()); +} + bool FeedHandler::isDoingReplay() const { return _tlsMgr.isDoingReplay(); @@ -492,22 +510,17 @@ FeedHandler::considerWriteOperationForRejection(FeedToken & token, const FeedOpe } bool -FeedHandler::considerUpdateOperationForRejection(FeedToken &token, const UpdateOperation &op) +FeedHandler::considerUpdateOperationForRejection(FeedToken &token, UpdateOperation &op) { - const auto *repo = _activeFeedView->getDocumentTypeRepo().get(); const auto &update = *op.getUpdate(); /* * Check if document types are equal. DocumentTypeRepoFactory::make returns * the same document type repo if document type configs are equal, thus we * can just perform a cheaper identity check here. */ - if (repo->getDocumentType(_docTypeName.getName()) != &update.getType()) { + if (_documentType != &update.getType()) { try { - vespalib::nbostream stream; - op.serialize(stream); - UpdateOperation checkOp(op.getType()); - vespalib::nbostream checkStream(stream.peek(), stream.size()); - checkOp.deserialize(stream, *repo); + op.deserializeUpdate(*_repo); } catch (document::FieldNotFoundException &e) { if (token) { auto message = make_string("Update operation rejected for document '%s' of type '%s': 'Field not found'", @@ -516,6 +529,14 @@ FeedHandler::considerUpdateOperationForRejection(FeedToken &token, const UpdateO token->fail(); } return true; + } catch (document::DocumentTypeNotFoundException &e) { + auto message = make_string("Update operation rejected for document '%s' of type '%s': 'Uknown document type', expected '%s'", + update.getId().toString().c_str(), + e.getDocumentTypeName().c_str(), + _docTypeName.toString().c_str()); + token->setResult(make_unique<UpdateResult>(Result::TRANSIENT_ERROR, message), false); + token->fail(); + return true; } } return false; diff --git a/searchcore/src/vespa/searchcore/proton/server/feedhandler.h b/searchcore/src/vespa/searchcore/proton/server/feedhandler.h index faf909080d9..34f979b7115 100644 --- a/searchcore/src/vespa/searchcore/proton/server/feedhandler.h +++ b/searchcore/src/vespa/searchcore/proton/server/feedhandler.h @@ -90,6 +90,8 @@ private: FeedStateSP _feedState; // used by master write thread tasks IFeedView *_activeFeedView; + const document::DocumentTypeRepo *_repo; + const document::DocumentType *_documentType; bucketdb::IBucketDBHandler *_bucketDBHandler; std::mutex _syncLock; SerialNum _syncedSerialNum; @@ -102,7 +104,7 @@ private: void doHandleOperation(FeedToken token, FeedOperationUP op); bool considerWriteOperationForRejection(FeedToken & token, const FeedOperation &op); - bool considerUpdateOperationForRejection(FeedToken &token, const UpdateOperation &op); + bool considerUpdateOperationForRejection(FeedToken &token, UpdateOperation &op); /** * Delayed execution of feed operations against feed view, in @@ -203,9 +205,7 @@ public: * Update the active feed view. * Always called by the master write thread so locking is not needed. */ - void setActiveFeedView(IFeedView *feedView) { - _activeFeedView = feedView; - } + void setActiveFeedView(IFeedView *feedView); void setBucketDBHandler(bucketdb::IBucketDBHandler *bucketDBHandler) { _bucketDBHandler = bucketDBHandler; diff --git a/searchcorespi/src/vespa/searchcorespi/index/indexcollection.cpp b/searchcorespi/src/vespa/searchcorespi/index/indexcollection.cpp index 8c8ea8e6f28..de4cde956d0 100644 --- a/searchcorespi/src/vespa/searchcorespi/index/indexcollection.cpp +++ b/searchcorespi/src/vespa/searchcorespi/index/indexcollection.cpp @@ -179,28 +179,30 @@ private: _result = mixer.mix(); } - virtual void visit(And &) override { } - virtual void visit(AndNot &) override { } - virtual void visit(Or &) override { } - virtual void visit(WeakAnd &) override { } - virtual void visit(Equiv &) override { } - virtual void visit(Rank &) override { } - virtual void visit(Near &) override { } - virtual void visit(ONear &) override { } - - virtual void visit(WeightedSetTerm &n) override { visitTerm(n); } - virtual void visit(DotProduct &n) override { visitTerm(n); } - virtual void visit(WandTerm &n) override { visitTerm(n); } - virtual void visit(Phrase &n) override { visitTerm(n); } - virtual void visit(NumberTerm &n) override { visitTerm(n); } - virtual void visit(LocationTerm &n) override { visitTerm(n); } - virtual void visit(PrefixTerm &n) override { visitTerm(n); } - virtual void visit(RangeTerm &n) override { visitTerm(n); } - virtual void visit(StringTerm &n) override { visitTerm(n); } - virtual void visit(SubstringTerm &n) override { visitTerm(n); } - virtual void visit(SuffixTerm &n) override { visitTerm(n); } - virtual void visit(PredicateQuery &n) override { visitTerm(n); } - virtual void visit(RegExpTerm &n) override { visitTerm(n); } + void visit(And &) override { } + void visit(AndNot &) override { } + void visit(Or &) override { } + void visit(WeakAnd &) override { } + void visit(Equiv &) override { } + void visit(Rank &) override { } + void visit(Near &) override { } + void visit(ONear &) override { } + void visit(SameElement &) override { } + + + void visit(WeightedSetTerm &n) override { visitTerm(n); } + void visit(DotProduct &n) override { visitTerm(n); } + void visit(WandTerm &n) override { visitTerm(n); } + void visit(Phrase &n) override { visitTerm(n); } + void visit(NumberTerm &n) override { visitTerm(n); } + void visit(LocationTerm &n) override { visitTerm(n); } + void visit(PrefixTerm &n) override { visitTerm(n); } + void visit(RangeTerm &n) override { visitTerm(n); } + void visit(StringTerm &n) override { visitTerm(n); } + void visit(SubstringTerm &n) override { visitTerm(n); } + void visit(SuffixTerm &n) override { visitTerm(n); } + void visit(PredicateQuery &n) override { visitTerm(n); } + void visit(RegExpTerm &n) override { visitTerm(n); } public: CreateBlueprintVisitor(const IIndexCollection &indexes, diff --git a/searchlib/src/tests/query/customtypevisitor_test.cpp b/searchlib/src/tests/query/customtypevisitor_test.cpp index 5aabb328354..a941694d375 100644 --- a/searchlib/src/tests/query/customtypevisitor_test.cpp +++ b/searchlib/src/tests/query/customtypevisitor_test.cpp @@ -1,14 +1,14 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. // Unit tests for customtypevisitor. -#include <vespa/log/log.h> -LOG_SETUP("customtypevisitor_test"); - #include <vespa/searchlib/query/tree/customtypevisitor.h> #include <vespa/searchlib/query/tree/intermediatenodes.h> #include <vespa/searchlib/query/tree/termnodes.h> #include <vespa/vespalib/testkit/testapp.h> +#include <vespa/log/log.h> +LOG_SETUP("customtypevisitor_test"); + using std::string; using namespace search::query; @@ -39,6 +39,7 @@ struct MyNear : Near { MyNear() : Near(1) {} }; struct MyONear : ONear { MyONear() : ONear(1) {} }; struct MyOr : Or {}; struct MyPhrase : Phrase { MyPhrase() : Phrase("view", 0, Weight(42)) {} }; +struct MySameElement : SameElement { MySameElement() : SameElement("view") {} }; struct MyRank : Rank {}; struct MyNumberTerm : InitTerm<NumberTerm> {}; struct MyLocationTerm : InitTerm<LocationTerm> {}; @@ -64,6 +65,7 @@ struct MyQueryNodeTypes { typedef MyONear ONear; typedef MyOr Or; typedef MyPhrase Phrase; + typedef MySameElement SameElement; typedef MyPrefixTerm PrefixTerm; typedef MyRangeTerm RangeTerm; typedef MyRank Rank; @@ -89,27 +91,28 @@ public: template <typename T> void setVisited() { isVisited<T>() = true; } - virtual void visit(MyAnd &) override { setVisited<MyAnd>(); } - virtual void visit(MyAndNot &) override { setVisited<MyAndNot>(); } - virtual void visit(MyEquiv &) override { setVisited<MyEquiv>(); } - virtual void visit(MyNumberTerm &) override { setVisited<MyNumberTerm>(); } - virtual void visit(MyLocationTerm &) override { setVisited<MyLocationTerm>(); } - virtual void visit(MyNear &) override { setVisited<MyNear>(); } - virtual void visit(MyONear &) override { setVisited<MyONear>(); } - virtual void visit(MyOr &) override { setVisited<MyOr>(); } - virtual void visit(MyPhrase &) override { setVisited<MyPhrase>(); } - virtual void visit(MyPrefixTerm &) override { setVisited<MyPrefixTerm>(); } - virtual void visit(MyRangeTerm &) override { setVisited<MyRangeTerm>(); } - virtual void visit(MyRank &) override { setVisited<MyRank>(); } - virtual void visit(MyStringTerm &) override { setVisited<MyStringTerm>(); } - virtual void visit(MySubstrTerm &) override { setVisited<MySubstrTerm>(); } - virtual void visit(MySuffixTerm &) override { setVisited<MySuffixTerm>(); } - virtual void visit(MyWeakAnd &) override { setVisited<MyWeakAnd>(); } - virtual void visit(MyWeightedSetTerm &) override { setVisited<MyWeightedSetTerm>(); } - virtual void visit(MyDotProduct &) override { setVisited<MyDotProduct>(); } - virtual void visit(MyWandTerm &) override { setVisited<MyWandTerm>(); } - virtual void visit(MyPredicateQuery &) override { setVisited<MyPredicateQuery>(); } - virtual void visit(MyRegExpTerm &) override { setVisited<MyRegExpTerm>(); } + void visit(MyAnd &) override { setVisited<MyAnd>(); } + void visit(MyAndNot &) override { setVisited<MyAndNot>(); } + void visit(MyEquiv &) override { setVisited<MyEquiv>(); } + void visit(MyNumberTerm &) override { setVisited<MyNumberTerm>(); } + void visit(MyLocationTerm &) override { setVisited<MyLocationTerm>(); } + void visit(MyNear &) override { setVisited<MyNear>(); } + void visit(MyONear &) override { setVisited<MyONear>(); } + void visit(MyOr &) override { setVisited<MyOr>(); } + void visit(MyPhrase &) override { setVisited<MyPhrase>(); } + void visit(MySameElement &) override { setVisited<MySameElement>(); } + void visit(MyPrefixTerm &) override { setVisited<MyPrefixTerm>(); } + void visit(MyRangeTerm &) override { setVisited<MyRangeTerm>(); } + void visit(MyRank &) override { setVisited<MyRank>(); } + void visit(MyStringTerm &) override { setVisited<MyStringTerm>(); } + void visit(MySubstrTerm &) override { setVisited<MySubstrTerm>(); } + void visit(MySuffixTerm &) override { setVisited<MySuffixTerm>(); } + void visit(MyWeakAnd &) override { setVisited<MyWeakAnd>(); } + void visit(MyWeightedSetTerm &) override { setVisited<MyWeightedSetTerm>(); } + void visit(MyDotProduct &) override { setVisited<MyDotProduct>(); } + void visit(MyWandTerm &) override { setVisited<MyWandTerm>(); } + void visit(MyPredicateQuery &) override { setVisited<MyPredicateQuery>(); } + void visit(MyRegExpTerm &) override { setVisited<MyRegExpTerm>(); } }; template <class T> diff --git a/searchlib/src/tests/query/query_visitor_test.cpp b/searchlib/src/tests/query/query_visitor_test.cpp index 9e82c6ea5ec..f8922c54a4e 100644 --- a/searchlib/src/tests/query/query_visitor_test.cpp +++ b/searchlib/src/tests/query/query_visitor_test.cpp @@ -1,9 +1,6 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. // Unit tests for query_visitor. -#include <vespa/log/log.h> -LOG_SETUP("query_visitor_test"); - #include <vespa/searchlib/query/tree/intermediatenodes.h> #include <vespa/searchlib/query/tree/point.h> #include <vespa/searchlib/query/tree/queryvisitor.h> @@ -11,6 +8,9 @@ LOG_SETUP("query_visitor_test"); #include <vespa/searchlib/query/tree/termnodes.h> #include <vespa/vespalib/testkit/testapp.h> +#include <vespa/log/log.h> +LOG_SETUP("query_visitor_test"); + using namespace search::query; namespace { @@ -43,29 +43,28 @@ public: return b; } - virtual void visit(And &) override { isVisited<And>() = true; } - virtual void visit(AndNot &) override { isVisited<AndNot>() = true; } - virtual void visit(Equiv &) override { isVisited<Equiv>() = true; } - virtual void visit(NumberTerm &) override { isVisited<NumberTerm>() = true; } - virtual void visit(LocationTerm &) override { isVisited<LocationTerm>() = true; } - virtual void visit(Near &) override { isVisited<Near>() = true; } - virtual void visit(ONear &) override { isVisited<ONear>() = true; } - virtual void visit(Or &) override { isVisited<Or>() = true; } - virtual void visit(Phrase &) override { isVisited<Phrase>() = true; } - virtual void visit(PrefixTerm &) override { isVisited<PrefixTerm>() = true; } - virtual void visit(RangeTerm &) override { isVisited<RangeTerm>() = true; } - virtual void visit(Rank &) override { isVisited<Rank>() = true; } - virtual void visit(StringTerm &) override { isVisited<StringTerm>() = true; } - virtual void visit(SubstringTerm &) override { isVisited<SubstringTerm>() = true; } - virtual void visit(SuffixTerm &) override { isVisited<SuffixTerm>() = true; } - virtual void visit(WeakAnd &) override { isVisited<WeakAnd>() = true; } - virtual void visit(WeightedSetTerm &) override - { isVisited<WeightedSetTerm>() = true; } - virtual void visit(DotProduct &) override { isVisited<DotProduct>() = true; } - virtual void visit(WandTerm &) override { isVisited<WandTerm>() = true; } - virtual void visit(PredicateQuery &) override - { isVisited<PredicateQuery>() = true; } - virtual void visit(RegExpTerm &) override { isVisited<RegExpTerm>() = true; } + void visit(And &) override { isVisited<And>() = true; } + void visit(AndNot &) override { isVisited<AndNot>() = true; } + void visit(Equiv &) override { isVisited<Equiv>() = true; } + void visit(NumberTerm &) override { isVisited<NumberTerm>() = true; } + void visit(LocationTerm &) override { isVisited<LocationTerm>() = true; } + void visit(Near &) override { isVisited<Near>() = true; } + void visit(ONear &) override { isVisited<ONear>() = true; } + void visit(Or &) override { isVisited<Or>() = true; } + void visit(Phrase &) override { isVisited<Phrase>() = true; } + void visit(SameElement &) override { isVisited<SameElement>() = true; } + void visit(PrefixTerm &) override { isVisited<PrefixTerm>() = true; } + void visit(RangeTerm &) override { isVisited<RangeTerm>() = true; } + void visit(Rank &) override { isVisited<Rank>() = true; } + void visit(StringTerm &) override { isVisited<StringTerm>() = true; } + void visit(SubstringTerm &) override { isVisited<SubstringTerm>() = true; } + void visit(SuffixTerm &) override { isVisited<SuffixTerm>() = true; } + void visit(WeakAnd &) override { isVisited<WeakAnd>() = true; } + void visit(WeightedSetTerm &) override { isVisited<WeightedSetTerm>() = true; } + void visit(DotProduct &) override { isVisited<DotProduct>() = true; } + void visit(WandTerm &) override { isVisited<WandTerm>() = true; } + void visit(PredicateQuery &) override { isVisited<PredicateQuery>() = true; } + void visit(RegExpTerm &) override { isVisited<RegExpTerm>() = true; } }; template <class T> @@ -84,27 +83,20 @@ void Test::requireThatAllNodesCanBeVisited() { checkVisit<ONear>(new SimpleONear(0)); checkVisit<Or>(new SimpleOr); checkVisit<Phrase>(new SimplePhrase("field", 0, Weight(42))); - checkVisit<WeightedSetTerm>( - new SimpleWeightedSetTerm("field", 0, Weight(42))); + checkVisit<SameElement>(new SimpleSameElement("field")); + checkVisit<WeightedSetTerm>(new SimpleWeightedSetTerm("field", 0, Weight(42))); checkVisit<DotProduct>(new SimpleDotProduct("field", 0, Weight(42))); - checkVisit<WandTerm>( - new SimpleWandTerm("field", 0, Weight(42), 57, 67, 77.7)); + checkVisit<WandTerm>(new SimpleWandTerm("field", 0, Weight(42), 57, 67, 77.7)); checkVisit<Rank>(new SimpleRank); - checkVisit<NumberTerm>( - new SimpleNumberTerm("0.42", "field", 0, Weight(0))); + checkVisit<NumberTerm>(new SimpleNumberTerm("0.42", "field", 0, Weight(0))); const Location location(Point(10, 10), 20, 0); - checkVisit<LocationTerm>( - new SimpleLocationTerm(location, "field", 0, Weight(0))); + checkVisit<LocationTerm>(new SimpleLocationTerm(location, "field", 0, Weight(0))); checkVisit<PrefixTerm>(new SimplePrefixTerm("t", "field", 0, Weight(0))); - checkVisit<RangeTerm>( - new SimpleRangeTerm(Range(0, 1), "field", 0, Weight(0))); + checkVisit<RangeTerm>(new SimpleRangeTerm(Range(0, 1), "field", 0, Weight(0))); checkVisit<StringTerm>(new SimpleStringTerm("t", "field", 0, Weight(0))); - checkVisit<SubstringTerm>( - new SimpleSubstringTerm("t", "field", 0, Weight(0))); + checkVisit<SubstringTerm>(new SimpleSubstringTerm("t", "field", 0, Weight(0))); checkVisit<SuffixTerm>(new SimpleSuffixTerm("t", "field", 0, Weight(0))); - checkVisit<PredicateQuery>( - new SimplePredicateQuery(PredicateQueryTerm::UP(), - "field", 0, Weight(0))); + checkVisit<PredicateQuery>(new SimplePredicateQuery(PredicateQueryTerm::UP(), "field", 0, Weight(0))); checkVisit<RegExpTerm>(new SimpleRegExpTerm("t", "field", 0, Weight(0))); } diff --git a/searchlib/src/tests/query/querybuilder_test.cpp b/searchlib/src/tests/query/querybuilder_test.cpp index b968f794833..0f05419c4e5 100644 --- a/searchlib/src/tests/query/querybuilder_test.cpp +++ b/searchlib/src/tests/query/querybuilder_test.cpp @@ -1,22 +1,18 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. // Unit tests for querybuilder. -#include <vespa/log/log.h> -LOG_SETUP("querybuilder_test"); - #include <vespa/searchlib/parsequery/parse.h> #include <vespa/searchlib/parsequery/simplequerystack.h> #include <vespa/searchlib/query/tree/customtypevisitor.h> -#include <vespa/searchlib/query/tree/intermediatenodes.h> #include <vespa/searchlib/query/tree/point.h> #include <vespa/searchlib/query/tree/querybuilder.h> -#include <vespa/searchlib/query/tree/querytreecreator.h> #include <vespa/searchlib/query/tree/simplequery.h> #include <vespa/searchlib/query/tree/stackdumpcreator.h> -#include <vespa/searchlib/query/tree/termnodes.h> -#include <vespa/searchlib/util/rawbuf.h> #include <vespa/vespalib/testkit/test_kit.h> -#include <string> + +#include <vespa/log/log.h> +LOG_SETUP("querybuilder_test"); +#include <vespa/searchlib/query/tree/querytreecreator.h> using std::string; using search::SimpleQueryStackDumpIterator; @@ -52,7 +48,7 @@ PredicateQueryTerm::UP getPredicateQueryTerm() { template <class NodeTypes> Node::UP createQueryTree() { QueryBuilder<NodeTypes> builder; - builder.addAnd(9); + builder.addAnd(10); { builder.addRank(2); { @@ -109,6 +105,12 @@ Node::UP createQueryTree() { builder.addStringTerm(str[2], view[2], id[2], weight[2]); } builder.addRegExpTerm(str[5], view[5], id[5], weight[5]); + builder.addSameElement(3, view[4]); + { + builder.addStringTerm(str[4], view[4], id[4], weight[5]); + builder.addStringTerm(str[5], view[5], id[5], weight[6]); + builder.addStringTerm(str[6], view[6], id[6], weight[7]); + } } Node::UP node = builder.build(); ASSERT_TRUE(node.get()); @@ -146,6 +148,7 @@ void checkQueryTreeTypes(Node *node) { //typedef typename NodeTypes::NumberTerm FloatTrm; typedef typename NodeTypes::Near Near; typedef typename NodeTypes::ONear ONear; + typedef typename NodeTypes::SameElement SameElement; typedef typename NodeTypes::Or Or; typedef typename NodeTypes::Phrase Phrase; typedef typename NodeTypes::PrefixTerm PrefixTerm; @@ -165,7 +168,7 @@ void checkQueryTreeTypes(Node *node) { ASSERT_TRUE(node); And *and_node = dynamic_cast<And *>(node); ASSERT_TRUE(and_node); - EXPECT_EQUAL(9u, and_node->getChildren().size()); + EXPECT_EQUAL(10u, and_node->getChildren().size()); Rank *rank = dynamic_cast<Rank *>(and_node->getChildren()[0]); @@ -176,22 +179,18 @@ void checkQueryTreeTypes(Node *node) { ASSERT_TRUE(near); EXPECT_EQUAL(2u, near->getChildren().size()); EXPECT_EQUAL(distance, near->getDistance()); - StringTerm *string_term = - dynamic_cast<StringTerm *>(near->getChildren()[0]); + StringTerm *string_term = dynamic_cast<StringTerm *>(near->getChildren()[0]); EXPECT_TRUE(checkTerm(string_term, str[0], view[0], id[0], weight[0])); - SubstringTerm *substring_term = - dynamic_cast<SubstringTerm *>(near->getChildren()[1]); + SubstringTerm *substring_term = dynamic_cast<SubstringTerm *>(near->getChildren()[1]); EXPECT_TRUE(checkTerm(substring_term, str[1], view[1], id[1], weight[1])); ONear *onear = dynamic_cast<ONear *>(rank->getChildren()[1]); ASSERT_TRUE(onear); EXPECT_EQUAL(2u, onear->getChildren().size()); EXPECT_EQUAL(distance, onear->getDistance()); - SuffixTerm *suffix_term = - dynamic_cast<SuffixTerm *>(onear->getChildren()[0]); + SuffixTerm *suffix_term = dynamic_cast<SuffixTerm *>(onear->getChildren()[0]); EXPECT_TRUE(checkTerm(suffix_term, str[2], view[2], id[2], weight[2])); - PrefixTerm *prefix_term = - dynamic_cast<PrefixTerm *>(onear->getChildren()[1]); + PrefixTerm *prefix_term = dynamic_cast<PrefixTerm *>(onear->getChildren()[1]); EXPECT_TRUE(checkTerm(prefix_term, str[3], view[3], id[3], weight[3])); @@ -224,26 +223,20 @@ void checkQueryTreeTypes(Node *node) { AndNot *and_not = dynamic_cast<AndNot *>(or_node->getChildren()[2]); ASSERT_TRUE(and_not); EXPECT_EQUAL(2u, and_not->getChildren().size()); - NumberTerm *integer_term = - dynamic_cast<NumberTerm *>(and_not->getChildren()[0]); + NumberTerm *integer_term = dynamic_cast<NumberTerm *>(and_not->getChildren()[0]); EXPECT_TRUE(checkTerm(integer_term, int1, view[7], id[7], weight[7])); - NumberTerm *float_term = - dynamic_cast<NumberTerm *>(and_not->getChildren()[1]); - EXPECT_TRUE(checkTerm(float_term, float1, view[8], id[8], weight[8], - false)); + NumberTerm *float_term = dynamic_cast<NumberTerm *>(and_not->getChildren()[1]); + EXPECT_TRUE(checkTerm(float_term, float1, view[8], id[8], weight[8], false)); - RangeTerm *range_term = - dynamic_cast<RangeTerm *>(and_node->getChildren()[2]); + RangeTerm *range_term = dynamic_cast<RangeTerm *>(and_node->getChildren()[2]); ASSERT_TRUE(range_term); EXPECT_TRUE(checkTerm(range_term, range, view[9], id[9], weight[9])); - LocationTerm *loc_term = - dynamic_cast<LocationTerm *>(and_node->getChildren()[3]); + LocationTerm *loc_term = dynamic_cast<LocationTerm *>(and_node->getChildren()[3]); ASSERT_TRUE(loc_term); EXPECT_TRUE(checkTerm(loc_term, location, view[10], id[10], weight[10])); - WeakAnd *wand = dynamic_cast<WeakAnd *>(and_node->getChildren()[4]); ASSERT_TRUE(wand != 0); EXPECT_EQUAL(123u, wand->getMinHits()); @@ -253,15 +246,12 @@ void checkQueryTreeTypes(Node *node) { string_term = dynamic_cast<StringTerm *>(wand->getChildren()[1]); EXPECT_TRUE(checkTerm(string_term, str[5], view[5], id[5], weight[5])); - PredicateQuery *predicateQuery = - dynamic_cast<PredicateQuery *>(and_node->getChildren()[5]); + PredicateQuery *predicateQuery = dynamic_cast<PredicateQuery *>(and_node->getChildren()[5]); ASSERT_TRUE(predicateQuery); PredicateQueryTerm::UP pqt(new PredicateQueryTerm); - EXPECT_TRUE(checkTerm(predicateQuery, getPredicateQueryTerm(), - view[3], id[3], weight[3])); + EXPECT_TRUE(checkTerm(predicateQuery, getPredicateQueryTerm(), view[3], id[3], weight[3])); - DotProduct *dotProduct = - dynamic_cast<DotProduct *>(and_node->getChildren()[6]); + DotProduct *dotProduct = dynamic_cast<DotProduct *>(and_node->getChildren()[6]); ASSERT_TRUE(dotProduct); EXPECT_EQUAL(3u, dotProduct->getChildren().size()); string_term = dynamic_cast<StringTerm *>(dotProduct->getChildren()[0]); @@ -282,9 +272,20 @@ void checkQueryTreeTypes(Node *node) { string_term = dynamic_cast<StringTerm *>(wandTerm->getChildren()[1]); EXPECT_TRUE(checkTerm(string_term, str[2], view[2], id[2], weight[2])); - RegExpTerm *regexp_term = - dynamic_cast<RegExpTerm *>(and_node->getChildren()[8]); + RegExpTerm *regexp_term = dynamic_cast<RegExpTerm *>(and_node->getChildren()[8]); EXPECT_TRUE(checkTerm(regexp_term, str[5], view[5], id[5], weight[5])); + + SameElement *same = dynamic_cast<SameElement *>(and_node->getChildren()[9]); + ASSERT_TRUE(same != nullptr); + EXPECT_EQUAL(view[4], same->getView()); + EXPECT_EQUAL(3u, same->getChildren().size()); + string_term = dynamic_cast<StringTerm *>(same->getChildren()[0]); + EXPECT_TRUE(checkTerm(string_term, str[4], view[4], id[4], weight[5])); + string_term = dynamic_cast<StringTerm *>(same->getChildren()[1]); + EXPECT_TRUE(checkTerm(string_term, str[5], view[5], id[5], weight[6])); + string_term = dynamic_cast<StringTerm *>(same->getChildren()[2]); + EXPECT_TRUE(checkTerm(string_term, str[6], view[6], id[6], weight[7])); + } struct AbstractTypes { @@ -294,6 +295,7 @@ struct AbstractTypes { typedef search::query::LocationTerm LocationTerm; typedef search::query::Near Near; typedef search::query::ONear ONear; + typedef search::query::SameElement SameElement; typedef search::query::Or Or; typedef search::query::Phrase Phrase; typedef search::query::PrefixTerm PrefixTerm; @@ -333,9 +335,9 @@ struct MyNear : Near { MyNear(size_t dist) : Near(dist) {} }; struct MyONear : ONear { MyONear(size_t dist) : ONear(dist) {} }; struct MyWeakAnd : WeakAnd { MyWeakAnd(uint32_t minHits, const vespalib::string & v) : WeakAnd(minHits, v) {} }; struct MyOr : Or {}; -struct MyPhrase : Phrase { - MyPhrase(const string &f, int32_t i, Weight w) : Phrase(f, i, w) {} -}; +struct MyPhrase : Phrase { MyPhrase(const string &f, int32_t i, Weight w) : Phrase(f, i, w) {}}; +struct MySameElement : SameElement { MySameElement(const string &f) : SameElement(f) {}}; + struct MyWeightedSetTerm : WeightedSetTerm { MyWeightedSetTerm(const string &f, int32_t i, Weight w) : WeightedSetTerm(f, i, w) {} }; @@ -404,6 +406,7 @@ struct MyQueryNodeTypes { typedef MyONear ONear; typedef MyOr Or; typedef MyPhrase Phrase; + typedef MySameElement SameElement; typedef MyPrefixTerm PrefixTerm; typedef MyRangeTerm RangeTerm; typedef MyRank Rank; @@ -556,8 +559,7 @@ TEST("require that Query Tree Creator Can Create Queries From Stack") { string stackDump = StackDumpCreator::create(*node); SimpleQueryStackDumpIterator iterator(stackDump); - Node::UP new_node = - QueryTreeCreator<SimpleQueryNodeTypes>::create(iterator); + Node::UP new_node = QueryTreeCreator<SimpleQueryNodeTypes>::create(iterator); checkQueryTreeTypes<SimpleQueryNodeTypes>(new_node.get()); } diff --git a/searchlib/src/tests/stackdumpiterator/stackdumpiteratortest.cpp b/searchlib/src/tests/stackdumpiterator/stackdumpiteratortest.cpp index d3a99dc439a..8ad4578b6c1 100644 --- a/searchlib/src/tests/stackdumpiterator/stackdumpiteratortest.cpp +++ b/searchlib/src/tests/stackdumpiterator/stackdumpiteratortest.cpp @@ -244,6 +244,7 @@ StackDumpIteratorTest::RunTest(int testno, bool verify) stack.Push(new search::ParseItem(search::ParseItem::ITEM_NUMTERM, "foo", "[0;22]")); stack.Push(new search::ParseItem(search::ParseItem::ITEM_PREFIXTERM, "bar", "baz")); stack.Push(new search::ParseItem(search::ParseItem::ITEM_PHRASE, 3, "bar")); + stack.Push(new search::ParseItem(search::ParseItem::ITEM_SAME_ELEMENT, 3, "bar")); stack.Push(new search::ParseItem(search::ParseItem::ITEM_OR, 2)); stack.Push(new search::ParseItem(search::ParseItem::ITEM_AND, 3)); stack.Push(new search::ParseItem(search::ParseItem::ITEM_RANK, 5)); diff --git a/searchlib/src/vespa/searchlib/features/distancetopathfeature.cpp b/searchlib/src/vespa/searchlib/features/distancetopathfeature.cpp index 4f4491327e7..834f5913af9 100644 --- a/searchlib/src/vespa/searchlib/features/distancetopathfeature.cpp +++ b/searchlib/src/vespa/searchlib/features/distancetopathfeature.cpp @@ -14,8 +14,7 @@ #include <vespa/log/log.h> LOG_SETUP(".features.distancetopathfeature"); -namespace search { -namespace features { +namespace search::features { const feature_t DistanceToPathExecutor::DEFAULT_DISTANCE(6400000000.0); @@ -96,9 +95,7 @@ DistanceToPathBlueprint::DistanceToPathBlueprint() : { } -DistanceToPathBlueprint::~DistanceToPathBlueprint() -{ -} +DistanceToPathBlueprint::~DistanceToPathBlueprint() = default; void DistanceToPathBlueprint::visitDumpFeatures(const search::fef::IIndexEnvironment &, @@ -175,5 +172,4 @@ DistanceToPathBlueprint::createExecutor(const search::fef::IQueryEnvironment &en return stash.create<DistanceToPathExecutor>(path, pos); } -} // namespace features -} // namespace search +} diff --git a/searchlib/src/vespa/searchlib/features/distancetopathfeature.h b/searchlib/src/vespa/searchlib/features/distancetopathfeature.h index cf268c59a2e..442f1ba3b28 100644 --- a/searchlib/src/vespa/searchlib/features/distancetopathfeature.h +++ b/searchlib/src/vespa/searchlib/features/distancetopathfeature.h @@ -6,8 +6,7 @@ #include <vespa/searchlib/fef/featureexecutor.h> #include <vespa/searchlib/common/feature.h> -namespace search { -namespace features { +namespace search::features { /** * Define the point type that makes up the end-points in our path. @@ -52,7 +51,7 @@ private: public: DistanceToPathBlueprint(); - ~DistanceToPathBlueprint(); + ~DistanceToPathBlueprint() override; void visitDumpFeatures(const fef::IIndexEnvironment &env, fef::IDumpFeatureVisitor &visitor) const override; fef::Blueprint::UP createInstance() const override; fef::ParameterDescriptions getDescriptions() const override { @@ -64,6 +63,4 @@ public: }; -} // namespace features -} // namespace search - +} diff --git a/searchlib/src/vespa/searchlib/parsequery/parse.cpp b/searchlib/src/vespa/searchlib/parsequery/parse.cpp index b189331878c..cba69ea474a 100644 --- a/searchlib/src/vespa/searchlib/parsequery/parse.cpp +++ b/searchlib/src/vespa/searchlib/parsequery/parse.cpp @@ -24,9 +24,8 @@ namespace search { ParseItem::ParseItem(ItemType type, int arity) : PARSEITEM_DEFAULT_CONSTRUCTOR_LIST { - assert(type==ITEM_OR || type==ITEM_WEAK_AND || type==ITEM_EQUIV || - type==ITEM_AND || type==ITEM_NOT || type==ITEM_RANK || - type==ITEM_PHRASE || type==ITEM_ANY || type==ITEM_NEAR || type==ITEM_ONEAR); + assert(type==ITEM_OR || type==ITEM_WEAK_AND || type==ITEM_EQUIV || type==ITEM_AND || type==ITEM_NOT + || type==ITEM_RANK || type==ITEM_ANY || type==ITEM_NEAR || type==ITEM_ONEAR); SetType(type); _arity = arity; } @@ -34,7 +33,8 @@ ParseItem::ParseItem(ItemType type, int arity) ParseItem::ParseItem(ItemType type, int arity, const char *idx) : PARSEITEM_DEFAULT_CONSTRUCTOR_LIST { - assert(type == ITEM_PHRASE || type==ITEM_WEIGHTED_SET || type==ITEM_DOT_PRODUCT || type==ITEM_WAND); + assert(type==ITEM_PHRASE || type==ITEM_SAME_ELEMENT || type==ITEM_WEIGHTED_SET + || type==ITEM_DOT_PRODUCT || type==ITEM_WAND); SetType(type); _arity = arity; SetIndex(idx); @@ -108,16 +108,24 @@ ParseItem::AppendBuffer(RawBuf *buf) const case ITEM_ANY: buf->appendCompressedPositiveNumber(_arity); break; - case ITEM_WEAK_AND: case ITEM_NEAR: case ITEM_ONEAR: buf->appendCompressedPositiveNumber(_arity); buf->appendCompressedPositiveNumber(_arg1); - if (Type() == ITEM_WEAK_AND) { - buf->appendCompressedPositiveNumber(indexLen); - if (indexLen != 0) { - buf->append(_indexName.c_str(), indexLen); - } + break; + case ITEM_SAME_ELEMENT: + buf->appendCompressedPositiveNumber(_arity); + buf->appendCompressedPositiveNumber(indexLen); + if (indexLen != 0) { + buf->append(_indexName.c_str(), indexLen); + } + break; + case ITEM_WEAK_AND: + buf->appendCompressedPositiveNumber(_arity); + buf->appendCompressedPositiveNumber(_arg1); + buf->appendCompressedPositiveNumber(indexLen); + if (indexLen != 0) { + buf->append(_indexName.c_str(), indexLen); } break; case ITEM_WEIGHTED_SET: @@ -199,6 +207,9 @@ ParseItem::GetBufferLen() const case ITEM_PHRASE: len += sizeof(uint32_t) * 2 + indexLen; break; + case ITEM_SAME_ELEMENT: + len += sizeof(uint32_t) * 2 + indexLen; + break; case ITEM_WAND: len += sizeof(uint32_t) * 4 + indexLen; break; diff --git a/searchlib/src/vespa/searchlib/parsequery/parse.h b/searchlib/src/vespa/searchlib/parsequery/parse.h index 3d5a1a5e2bb..d8cbdc696a5 100644 --- a/searchlib/src/vespa/searchlib/parsequery/parse.h +++ b/searchlib/src/vespa/searchlib/parsequery/parse.h @@ -52,7 +52,7 @@ public: ITEM_WEIGHTED_SET = 15, ITEM_WEAK_AND = 16, ITEM_EXACTSTRINGTERM = 17, - UNUSED_LEGACY_ITEM_RISE_QUERY = 18, + ITEM_SAME_ELEMENT = 18, ITEM_PURE_WEIGHTED_STRING = 19, ITEM_PURE_WEIGHTED_LONG = 20, ITEM_DOT_PRODUCT = 21, diff --git a/searchlib/src/vespa/searchlib/parsequery/simplequerystack.cpp b/searchlib/src/vespa/searchlib/parsequery/simplequerystack.cpp index a7b41476ec6..6f49dc62686 100644 --- a/searchlib/src/vespa/searchlib/parsequery/simplequerystack.cpp +++ b/searchlib/src/vespa/searchlib/parsequery/simplequerystack.cpp @@ -25,12 +25,12 @@ SimpleQueryStack::~SimpleQueryStack() } void -SimpleQueryStack::Push(search::ParseItem *item) +SimpleQueryStack::Push(ParseItem *item) { // Check if query OK for FirstPage _FP_queryOK &= - ( item->Type() != search::ParseItem::ITEM_UNDEF - && item->Type() != search::ParseItem::ITEM_PAREN + ( item->Type() != ParseItem::ITEM_UNDEF + && item->Type() != ParseItem::ITEM_PAREN ); @@ -40,10 +40,10 @@ SimpleQueryStack::Push(search::ParseItem *item) _numItems++; } -search::ParseItem * +ParseItem * SimpleQueryStack::Pop() { - search::ParseItem *item = _stack; + ParseItem *item = _stack; if (_stack != NULL) { _numItems--; _stack = _stack->_next; @@ -53,9 +53,9 @@ SimpleQueryStack::Pop() } void -SimpleQueryStack::AppendBuffer(search::RawBuf *buf) const +SimpleQueryStack::AppendBuffer(RawBuf *buf) const { - for (search::ParseItem *item = _stack; item != NULL; item = item->_next) { + for (ParseItem *item = _stack; item != NULL; item = item->_next) { item->AppendBuffer(buf); } } @@ -66,7 +66,7 @@ SimpleQueryStack::GetBufferLen() const size_t result; result = 0; - for (const search::ParseItem *item = _stack; + for (const ParseItem *item = _stack; item != NULL; item = item->_next) { result += item->GetBufferLen(); } @@ -90,34 +90,35 @@ class ItemName { public: ItemName() { memset(_name, 'X', sizeof(_name)); - _name[search::ParseItem::ITEM_OR] = '|'; - _name[search::ParseItem::ITEM_WEAK_AND] = 'w'; - _name[search::ParseItem::ITEM_EQUIV] = 'E'; - _name[search::ParseItem::ITEM_AND] = '&'; - _name[search::ParseItem::ITEM_NOT] = '-'; - _name[search::ParseItem::ITEM_ANY] = '?'; - _name[search::ParseItem::ITEM_RANK] = '%'; - _name[search::ParseItem::ITEM_NEAR] = 'N'; - _name[search::ParseItem::ITEM_ONEAR] = 'O'; - _name[search::ParseItem::ITEM_NUMTERM] = '#'; - _name[search::ParseItem::ITEM_TERM] = 't'; - _name[search::ParseItem::ITEM_PURE_WEIGHTED_STRING] = 'T'; - _name[search::ParseItem::ITEM_PURE_WEIGHTED_LONG] = 'L'; - _name[search::ParseItem::ITEM_PREFIXTERM] = '*'; - _name[search::ParseItem::ITEM_SUBSTRINGTERM] = 's'; - _name[search::ParseItem::ITEM_EXACTSTRINGTERM] = 'e'; - _name[search::ParseItem::ITEM_SUFFIXTERM] = 'S'; - _name[search::ParseItem::ITEM_PHRASE] = '"'; - _name[search::ParseItem::ITEM_WEIGHTED_SET] = 'W'; - _name[search::ParseItem::ITEM_DOT_PRODUCT] = 'D'; - _name[search::ParseItem::ITEM_WAND] = 'A'; - _name[search::ParseItem::ITEM_PREDICATE_QUERY] = 'P'; - _name[search::ParseItem::ITEM_REGEXP] = '^'; + _name[ParseItem::ITEM_OR] = '|'; + _name[ParseItem::ITEM_WEAK_AND] = 'w'; + _name[ParseItem::ITEM_EQUIV] = 'E'; + _name[ParseItem::ITEM_AND] = '&'; + _name[ParseItem::ITEM_NOT] = '-'; + _name[ParseItem::ITEM_ANY] = '?'; + _name[ParseItem::ITEM_RANK] = '%'; + _name[ParseItem::ITEM_NEAR] = 'N'; + _name[ParseItem::ITEM_ONEAR] = 'O'; + _name[ParseItem::ITEM_NUMTERM] = '#'; + _name[ParseItem::ITEM_TERM] = 't'; + _name[ParseItem::ITEM_PURE_WEIGHTED_STRING] = 'T'; + _name[ParseItem::ITEM_PURE_WEIGHTED_LONG] = 'L'; + _name[ParseItem::ITEM_PREFIXTERM] = '*'; + _name[ParseItem::ITEM_SUBSTRINGTERM] = 's'; + _name[ParseItem::ITEM_EXACTSTRINGTERM] = 'e'; + _name[ParseItem::ITEM_SUFFIXTERM] = 'S'; + _name[ParseItem::ITEM_PHRASE] = '"'; + _name[ParseItem::ITEM_SAME_ELEMENT] = 'M'; + _name[ParseItem::ITEM_WEIGHTED_SET] = 'W'; + _name[ParseItem::ITEM_DOT_PRODUCT] = 'D'; + _name[ParseItem::ITEM_WAND] = 'A'; + _name[ParseItem::ITEM_PREDICATE_QUERY] = 'P'; + _name[ParseItem::ITEM_REGEXP] = '^'; } - char operator[] (search::ParseItem::ItemType i) const { return _name[i]; } + char operator[] (ParseItem::ItemType i) const { return _name[i]; } char operator[] (size_t i) const { return _name[i]; } private: - char _name[search::ParseItem::ITEM_MAX]; + char _name[ParseItem::ITEM_MAX]; }; static ItemName _G_ItemName; @@ -162,29 +163,29 @@ SimpleQueryStack::StackbufToString(const vespalib::stringref &theBuf) while (p < ep) { vespalib::string metaStr; rawtype = *p++; - type = search::ParseItem::GetType(rawtype); - if (search::ParseItem::GetFeature_Weight(rawtype)) { + type = ParseItem::GetType(rawtype); + if (ParseItem::GetFeature_Weight(rawtype)) { int64_t tmpLong(0); p += vespalib::compress::Integer::decompress(tmpLong, p); metaStr.append("(w:"); metaStr.append(make_string("%ld", tmpLong)); metaStr.append(")"); } - if (search::ParseItem::getFeature_UniqueId(rawtype)) { + if (ParseItem::getFeature_UniqueId(rawtype)) { p += vespalib::compress::Integer::decompressPositive(tmp, p); metaStr.append("(u:"); metaStr.append(make_string("%ld", tmp)); metaStr.append(")"); } - if (search::ParseItem::getFeature_Flags(rawtype)) { + if (ParseItem::getFeature_Flags(rawtype)) { flags = *p++; metaStr.append("(f:"); metaStr.append(make_string("%d", flags)); metaStr.append(")"); } - if (search::ParseItem::GetCreator(flags) != search::ParseItem::CREA_ORIG) { + if (ParseItem::GetCreator(flags) != ParseItem::CREA_ORIG) { metaStr.append("(c:"); - metaStr.append(make_string("%d", search::ParseItem::GetCreator(flags))); + metaStr.append(make_string("%d", ParseItem::GetCreator(flags))); metaStr.append(")"); } @@ -192,41 +193,52 @@ SimpleQueryStack::StackbufToString(const vespalib::stringref &theBuf) result.append(metaStr); switch (type) { - case search::ParseItem::ITEM_OR: - case search::ParseItem::ITEM_AND: - case search::ParseItem::ITEM_EQUIV: - case search::ParseItem::ITEM_NOT: - case search::ParseItem::ITEM_RANK: - case search::ParseItem::ITEM_ANY: + case ParseItem::ITEM_OR: + case ParseItem::ITEM_AND: + case ParseItem::ITEM_EQUIV: + case ParseItem::ITEM_NOT: + case ParseItem::ITEM_RANK: + case ParseItem::ITEM_ANY: p += vespalib::compress::Integer::decompressPositive(tmp, p); arity = tmp; result.append(make_string("%c/%d~", _G_ItemName[type], arity)); break; - case search::ParseItem::ITEM_WEAK_AND: - case search::ParseItem::ITEM_NEAR: - case search::ParseItem::ITEM_ONEAR: + case ParseItem::ITEM_NEAR: + case ParseItem::ITEM_ONEAR: p += vespalib::compress::Integer::decompressPositive(tmp, p); arity = tmp; p += vespalib::compress::Integer::decompressPositive(tmp, p); arg1 = tmp; - if (type == search::ParseItem::ITEM_WEAK_AND) { - p += vespalib::compress::Integer::decompressPositive(tmp, p); - idxRefLen = tmp; - idxRef = p; - p += idxRefLen; - result.append(make_string("%c/%d/%d/%d:%.*s~", _G_ItemName[type], arity, arg1, idxRefLen, idxRefLen, idxRef)); - } else { - result.append(make_string("%c/%d/%d~", _G_ItemName[type], arity, arg1)); - } + result.append(make_string("%c/%d/%d~", _G_ItemName[type], arity, arg1)); + break; + case ParseItem::ITEM_WEAK_AND: + p += vespalib::compress::Integer::decompressPositive(tmp, p); + arity = tmp; + p += vespalib::compress::Integer::decompressPositive(tmp, p); + arg1 = tmp; + p += vespalib::compress::Integer::decompressPositive(tmp, p); + idxRefLen = tmp; + idxRef = p; + p += idxRefLen; + result.append(make_string("%c/%d/%d/%d:%.*s~", _G_ItemName[type], arity, arg1, idxRefLen, idxRefLen, idxRef)); + break; + case ParseItem::ITEM_SAME_ELEMENT: + p += vespalib::compress::Integer::decompressPositive(tmp, p); + arity = tmp; + p += vespalib::compress::Integer::decompressPositive(tmp, p); + idxRefLen = tmp; + idxRef = p; + p += idxRefLen; + result.append(make_string("%c/%d/%d:%.*s~", _G_ItemName[type], arity, idxRefLen, idxRefLen, idxRef)); break; - case search::ParseItem::ITEM_NUMTERM: - case search::ParseItem::ITEM_TERM: - case search::ParseItem::ITEM_PREFIXTERM: - case search::ParseItem::ITEM_SUBSTRINGTERM: - case search::ParseItem::ITEM_EXACTSTRINGTERM: - case search::ParseItem::ITEM_SUFFIXTERM: - case search::ParseItem::ITEM_REGEXP: + case ParseItem::ITEM_NUMTERM: + case ParseItem::ITEM_TERM: + case ParseItem::ITEM_PREFIXTERM: + case ParseItem::ITEM_SUBSTRINGTERM: + case ParseItem::ITEM_EXACTSTRINGTERM: + case ParseItem::ITEM_SUFFIXTERM: + case ParseItem::ITEM_REGEXP: p += vespalib::compress::Integer::decompressPositive(tmp, p); idxRefLen = tmp; idxRef = p; @@ -239,7 +251,7 @@ SimpleQueryStack::StackbufToString(const vespalib::stringref &theBuf) idxRefLen, idxRefLen, idxRef, termRefLen, termRefLen, termRef)); break; - case search::ParseItem::ITEM_PURE_WEIGHTED_STRING: + case ParseItem::ITEM_PURE_WEIGHTED_STRING: p += vespalib::compress::Integer::decompressPositive(tmp, p); termRefLen = tmp; termRef = p; @@ -248,23 +260,23 @@ SimpleQueryStack::StackbufToString(const vespalib::stringref &theBuf) termRefLen, termRefLen, termRef)); break; - case search::ParseItem::ITEM_PURE_WEIGHTED_LONG: + case ParseItem::ITEM_PURE_WEIGHTED_LONG: tmp = vespalib::nbo::n2h(*reinterpret_cast<const uint64_t *>(p)); p += sizeof(uint64_t); result.append(make_string("%c/%lu", _G_ItemName[type], tmp)); break; - case search::ParseItem::ITEM_PHRASE: - case search::ParseItem::ITEM_WEIGHTED_SET: - case search::ParseItem::ITEM_DOT_PRODUCT: - case search::ParseItem::ITEM_WAND: + case ParseItem::ITEM_PHRASE: + case ParseItem::ITEM_WEIGHTED_SET: + case ParseItem::ITEM_DOT_PRODUCT: + case ParseItem::ITEM_WAND: p += vespalib::compress::Integer::decompressPositive(tmp, p); arity = tmp; p += vespalib::compress::Integer::decompressPositive(tmp, p); idxRefLen = tmp; idxRef = p; p += idxRefLen; - if (type == search::ParseItem::ITEM_WAND) { + if (type == ParseItem::ITEM_WAND) { p += vespalib::compress::Integer::decompressPositive(tmp, p); uint32_t targetNumHits = tmp; double scoreThreshold = vespalib::nbo::n2h(*reinterpret_cast<const double *>(p)); @@ -279,7 +291,7 @@ SimpleQueryStack::StackbufToString(const vespalib::stringref &theBuf) } break; - case search::ParseItem::ITEM_PREDICATE_QUERY: + case ParseItem::ITEM_PREDICATE_QUERY: { idxRefLen = static_cast<uint32_t>(ReadCompressedPositiveInt(p)); idxRef = p; diff --git a/searchlib/src/vespa/searchlib/parsequery/stackdumpiterator.cpp b/searchlib/src/vespa/searchlib/parsequery/stackdumpiterator.cpp index ec34b2d3a84..542e7990c1e 100644 --- a/searchlib/src/vespa/searchlib/parsequery/stackdumpiterator.cpp +++ b/searchlib/src/vespa/searchlib/parsequery/stackdumpiterator.cpp @@ -34,9 +34,7 @@ SimpleQueryStackDumpIterator::SimpleQueryStackDumpIterator(const vespalib::strin { } -SimpleQueryStackDumpIterator::~SimpleQueryStackDumpIterator() -{ -} +SimpleQueryStackDumpIterator::~SimpleQueryStackDumpIterator() = default; vespalib::string SimpleQueryStackDumpIterator::readString(const char *&p) { if (p >= _bufEnd) throw false; @@ -154,6 +152,20 @@ SimpleQueryStackDumpIterator::next() _currTerm = NULL; _currTermLen = 0; break; + case ParseItem::ITEM_SAME_ELEMENT: + if (p >= _bufEnd) return false; + p += vespalib::compress::Integer::decompressPositive(tmp, p); + _currArity = tmp; + _currArg1 = 0; + p += vespalib::compress::Integer::decompressPositive(tmp, p); + _currIndexNameLen = tmp; + if (p > _bufEnd) return false; + _currIndexName = p; + p += _currIndexNameLen; + if (p > _bufEnd) return false; + _currTerm = NULL; + _currTermLen = 0; + break; case ParseItem::ITEM_PURE_WEIGHTED_STRING: if (p >= _bufEnd) return false; diff --git a/searchlib/src/vespa/searchlib/query/query.cpp b/searchlib/src/vespa/searchlib/query/query.cpp index d380c273d02..984337f40ba 100644 --- a/searchlib/src/vespa/searchlib/query/query.cpp +++ b/searchlib/src/vespa/searchlib/query/query.cpp @@ -102,10 +102,11 @@ QueryConnector::create(ParseItem::ItemType type) case search::ParseItem::ITEM_WAND: return new OrQueryNode(); case search::ParseItem::ITEM_NOT: return new AndNotQueryNode(); case search::ParseItem::ITEM_PHRASE: return new PhraseQueryNode(); + case search::ParseItem::ITEM_SAME_ELEMENT: return new AndQueryNode(); // TODO: This needs a same element operation to work for streaming search too. case search::ParseItem::ITEM_NEAR: return new NearQueryNode(); case search::ParseItem::ITEM_ONEAR: return new ONearQueryNode(); default: - return NULL; + return nullptr; } } diff --git a/searchlib/src/vespa/searchlib/query/querynode.cpp b/searchlib/src/vespa/searchlib/query/querynode.cpp index 2e9d8be95f4..0d0a06de7af 100644 --- a/searchlib/src/vespa/searchlib/query/querynode.cpp +++ b/searchlib/src/vespa/searchlib/query/querynode.cpp @@ -26,6 +26,7 @@ QueryNode::UP QueryNode::Build(const QueryNode * parent, const QueryNodeResultFa case search::ParseItem::ITEM_WAND: case search::ParseItem::ITEM_NOT: case search::ParseItem::ITEM_PHRASE: + case search::ParseItem::ITEM_SAME_ELEMENT: case search::ParseItem::ITEM_NEAR: case search::ParseItem::ITEM_ONEAR: { diff --git a/searchlib/src/vespa/searchlib/query/tree/customtypetermvisitor.h b/searchlib/src/vespa/searchlib/query/tree/customtypetermvisitor.h index 72763839b95..611406e6ea3 100644 --- a/searchlib/src/vespa/searchlib/query/tree/customtypetermvisitor.h +++ b/searchlib/src/vespa/searchlib/query/tree/customtypetermvisitor.h @@ -5,8 +5,7 @@ #include "customtypevisitor.h" #include "intermediate.h" -namespace search { -namespace query { +namespace search::query { template <class NodeTypes> class CustomTypeTermVisitor : public CustomTypeVisitor<NodeTypes> @@ -27,10 +26,10 @@ private: void visit(typename NodeTypes::Or &n) override { visitChildren(n); } void visit(typename NodeTypes::Rank &n) override { visitChildren(n); } void visit(typename NodeTypes::WeakAnd &n) override { visitChildren(n); } + void visit(typename NodeTypes::SameElement &n) override { visitChildren(n); } // phrases and weighted set terms are conceptual leaf nodes and // should be handled that way. }; -} // namespace query -} // namespace search +} diff --git a/searchlib/src/vespa/searchlib/query/tree/customtypevisitor.h b/searchlib/src/vespa/searchlib/query/tree/customtypevisitor.h index 83e6343e223..cdeebcaf9e5 100644 --- a/searchlib/src/vespa/searchlib/query/tree/customtypevisitor.h +++ b/searchlib/src/vespa/searchlib/query/tree/customtypevisitor.h @@ -4,8 +4,7 @@ #include "queryvisitor.h" -namespace search { -namespace query { +namespace search::query { /** * By typedefing a (complete) set of subclasses to the query nodes in @@ -37,6 +36,7 @@ public: virtual void visit(typename NodeTypes::ONear &) = 0; virtual void visit(typename NodeTypes::Or &) = 0; virtual void visit(typename NodeTypes::Phrase &) = 0; + virtual void visit(typename NodeTypes::SameElement &) = 0; virtual void visit(typename NodeTypes::PrefixTerm &) = 0; virtual void visit(typename NodeTypes::RangeTerm &) = 0; virtual void visit(typename NodeTypes::Rank &) = 0; @@ -62,6 +62,7 @@ private: typedef typename NodeTypes::ONear TONear; typedef typename NodeTypes::Or TOr; typedef typename NodeTypes::Phrase TPhrase; + typedef typename NodeTypes::SameElement TSameElement; typedef typename NodeTypes::PrefixTerm TPrefixTerm; typedef typename NodeTypes::RangeTerm TRangeTerm; typedef typename NodeTypes::Rank TRank; @@ -84,6 +85,7 @@ private: void visit(ONear &n) override { visit(static_cast<TONear&>(n)); } void visit(Or &n) override { visit(static_cast<TOr&>(n)); } void visit(Phrase &n) override { visit(static_cast<TPhrase&>(n)); } + void visit(SameElement &n) override { visit(static_cast<TSameElement &>(n)); } void visit(PrefixTerm &n) override { visit(static_cast<TPrefixTerm&>(n)); } void visit(RangeTerm &n) override { visit(static_cast<TRangeTerm&>(n)); } void visit(Rank &n) override { visit(static_cast<TRank&>(n)); } @@ -98,5 +100,4 @@ private: void visit(RegExpTerm &n) override { visit(static_cast<TRegExpTerm&>(n)); } }; -} // namespace query -} // namespace search +} diff --git a/searchlib/src/vespa/searchlib/query/tree/intermediate.cpp b/searchlib/src/vespa/searchlib/query/tree/intermediate.cpp index 1274777dc74..f56da9c2cf9 100644 --- a/searchlib/src/vespa/searchlib/query/tree/intermediate.cpp +++ b/searchlib/src/vespa/searchlib/query/tree/intermediate.cpp @@ -1,8 +1,7 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #include "intermediate.h" -namespace search { -namespace query { +namespace search::query { Intermediate::~Intermediate() { for (size_t i = 0; i < _children.size(); ++i) { @@ -16,5 +15,4 @@ Intermediate &Intermediate::append(Node::UP child) return *this; } -} // namespace query -} // namespace search +} diff --git a/searchlib/src/vespa/searchlib/query/tree/intermediate.h b/searchlib/src/vespa/searchlib/query/tree/intermediate.h index c28ab8241e0..052dc1db269 100644 --- a/searchlib/src/vespa/searchlib/query/tree/intermediate.h +++ b/searchlib/src/vespa/searchlib/query/tree/intermediate.h @@ -1,11 +1,10 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #pragma once +#include "node.h" #include <vector> -#include <vespa/searchlib/query/tree/node.h> -namespace search { -namespace query { +namespace search::query { class Intermediate : public Node { @@ -24,6 +23,4 @@ class Intermediate : public Node Intermediate &append(Node::UP child); }; -} // namespace query -} // namespace search - +} diff --git a/searchlib/src/vespa/searchlib/query/tree/intermediatenodes.cpp b/searchlib/src/vespa/searchlib/query/tree/intermediatenodes.cpp index 9fabbe58a19..4a4b606ef8f 100644 --- a/searchlib/src/vespa/searchlib/query/tree/intermediatenodes.cpp +++ b/searchlib/src/vespa/searchlib/query/tree/intermediatenodes.cpp @@ -1,32 +1,20 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #include "intermediatenodes.h" -namespace search { -namespace query { - -And::~And() {} - -AndNot::~AndNot() {} - -Or::~Or() {} - -WeakAnd::~WeakAnd() {} - -Equiv::~Equiv() {} - -Rank::~Rank() {} - -Near::~Near() {} - -ONear::~ONear() {} - -Phrase::~Phrase() {} - -WeightedSetTerm::~WeightedSetTerm() {} - -DotProduct::~DotProduct() {} - -WandTerm::~WandTerm() {} - -} // namespace query -} // namespace search +namespace search::query { + +And::~And() = default; +AndNot::~AndNot() = default; +Or::~Or() = default; +WeakAnd::~WeakAnd() = default; +Equiv::~Equiv() = default; +Rank::~Rank() = default; +Near::~Near() = default; +ONear::~ONear() = default; +Phrase::~Phrase() = default; +SameElement::~SameElement() = default; +WeightedSetTerm::~WeightedSetTerm() = default; +DotProduct::~DotProduct() = default; +WandTerm::~WandTerm() = default; + +} diff --git a/searchlib/src/vespa/searchlib/query/tree/intermediatenodes.h b/searchlib/src/vespa/searchlib/query/tree/intermediatenodes.h index e358c7d7bef..6d643d951f0 100644 --- a/searchlib/src/vespa/searchlib/query/tree/intermediatenodes.h +++ b/searchlib/src/vespa/searchlib/query/tree/intermediatenodes.h @@ -5,10 +5,8 @@ #include "intermediate.h" #include "querynodemixin.h" #include "term.h" -#include <vespa/searchlib/query/weight.h> -namespace search { -namespace query { +namespace search::query { class And : public QueryNodeMixin<And, Intermediate> { public: @@ -105,6 +103,15 @@ public: virtual ~Phrase() = 0; }; +class SameElement : public QueryNodeMixin<SameElement, Intermediate> { +public: + SameElement(const vespalib::string &view) : _view(view) {} + virtual ~SameElement() = 0; + const vespalib::string & getView() const { return _view; } +private: + vespalib::string _view; +}; + class WeightedSetTerm : public QueryNodeMixin<WeightedSetTerm, Intermediate>, public Term { public: WeightedSetTerm(const vespalib::string &view, int32_t id, Weight weight) @@ -137,6 +144,4 @@ public: double getThresholdBoostFactor() const { return _thresholdBoostFactor; } }; -} // namespace query -} // namespace search - +} diff --git a/searchlib/src/vespa/searchlib/query/tree/location.cpp b/searchlib/src/vespa/searchlib/query/tree/location.cpp index 5817b93a2fb..216c5ec5ad0 100644 --- a/searchlib/src/vespa/searchlib/query/tree/location.cpp +++ b/searchlib/src/vespa/searchlib/query/tree/location.cpp @@ -7,8 +7,7 @@ using vespalib::asciistream; -namespace search { -namespace query { +namespace search::query { Location::Location(const Point &point, uint32_t max_dist, uint32_t x_aspect) { asciistream loc; @@ -61,5 +60,4 @@ vespalib::asciistream &operator<<(vespalib::asciistream &out, const Location &lo return out << loc.getLocationString(); } -} // namespace query -} // namespace search +} diff --git a/searchlib/src/vespa/searchlib/query/tree/location.h b/searchlib/src/vespa/searchlib/query/tree/location.h index 0abad19b696..5ed717c87d6 100644 --- a/searchlib/src/vespa/searchlib/query/tree/location.h +++ b/searchlib/src/vespa/searchlib/query/tree/location.h @@ -4,11 +4,8 @@ #include <vespa/vespalib/stllike/string.h> -namespace vespalib { - class asciistream; -} -namespace search { -namespace query { +namespace vespalib { class asciistream; } +namespace search::query { class Point; class Rectangle; @@ -32,6 +29,4 @@ public: vespalib::asciistream &operator<<(vespalib::asciistream &out, const Location &loc); -} // namespace query -} // namespace search - +} diff --git a/searchlib/src/vespa/searchlib/query/tree/point.h b/searchlib/src/vespa/searchlib/query/tree/point.h index af9b958a474..89d0bc1db44 100644 --- a/searchlib/src/vespa/searchlib/query/tree/point.h +++ b/searchlib/src/vespa/searchlib/query/tree/point.h @@ -2,10 +2,9 @@ #pragma once -#include <stdint.h> +#include <cstdint> -namespace search { -namespace query { +namespace search::query { struct Point { int64_t x; @@ -18,6 +17,4 @@ inline bool operator==(const Point &p1, const Point &p2) { return p1.x == p2.x && p1.y == p2.y; } -} // namespace query -} // namespace search - +} diff --git a/searchlib/src/vespa/searchlib/query/tree/predicate_query_term.h b/searchlib/src/vespa/searchlib/query/tree/predicate_query_term.h index b851563e198..0a92546e414 100644 --- a/searchlib/src/vespa/searchlib/query/tree/predicate_query_term.h +++ b/searchlib/src/vespa/searchlib/query/tree/predicate_query_term.h @@ -6,8 +6,7 @@ #include <memory> #include <vector> -namespace search { -namespace query { +namespace search::query { /** * Represents a predicate query, with features and range features. @@ -71,6 +70,4 @@ public: } }; -} // namespace query -} // namespace search - +} diff --git a/searchlib/src/vespa/searchlib/query/tree/querybuilder.h b/searchlib/src/vespa/searchlib/query/tree/querybuilder.h index 2732d7895a5..3c6ff93457d 100644 --- a/searchlib/src/vespa/searchlib/query/tree/querybuilder.h +++ b/searchlib/src/vespa/searchlib/query/tree/querybuilder.h @@ -20,13 +20,11 @@ #pragma once #include "predicate_query_term.h" -#include <stack> -#include <vespa/vespalib/stllike/string.h> -#include <vespa/searchlib/query/weight.h> #include "node.h" +#include <vespa/searchlib/query/weight.h> +#include <stack> -namespace search { -namespace query { +namespace search::query { class Intermediate; class Location; @@ -124,6 +122,10 @@ typename NodeTypes::Phrase *createPhrase(const vespalib::stringref &view, int32_ return new typename NodeTypes::Phrase(view, id, weight); } template <class NodeTypes> +typename NodeTypes::SameElement *createSameElement(const vespalib::stringref &view) { + return new typename NodeTypes::SameElement(view); +} +template <class NodeTypes> typename NodeTypes::WeightedSetTerm *createWeightedSetTerm(const vespalib::stringref &view, int32_t id, Weight weight) { return new typename NodeTypes::WeightedSetTerm(view, id, weight); } @@ -243,6 +245,9 @@ public: setWeightOverride(weight); return node; } + typename NodeTypes::SameElement &addSameElement(int child_count, const stringref &view) { + return addIntermediate(createSameElement<NodeTypes>(view), child_count); + } typename NodeTypes::WeightedSetTerm &addWeightedSetTerm( int child_count, const stringref &view, int32_t id, Weight weight) { adjustWeight(weight); typename NodeTypes::WeightedSetTerm &node = addIntermediate(createWeightedSetTerm<NodeTypes>(view, id, weight), child_count); @@ -306,6 +311,4 @@ public: } }; -} // namespace query -} // namespace search - +} diff --git a/searchlib/src/vespa/searchlib/query/tree/querynodemixin.h b/searchlib/src/vespa/searchlib/query/tree/querynodemixin.h index d6e0950dea2..9e8c97cff94 100644 --- a/searchlib/src/vespa/searchlib/query/tree/querynodemixin.h +++ b/searchlib/src/vespa/searchlib/query/tree/querynodemixin.h @@ -4,8 +4,7 @@ #include "queryvisitor.h" -namespace search { -namespace query { +namespace search::query { template <typename T, typename Base> struct QueryNodeMixin : Base { @@ -21,8 +20,6 @@ protected: }; template <typename T, typename Base> -QueryNodeMixin<T, Base>::~QueryNodeMixin() {} - -} // namespace query -} // namespace search +QueryNodeMixin<T, Base>::~QueryNodeMixin() = default; +} diff --git a/searchlib/src/vespa/searchlib/query/tree/queryreplicator.h b/searchlib/src/vespa/searchlib/query/tree/queryreplicator.h index aad85d9b28c..7bf6c17f136 100644 --- a/searchlib/src/vespa/searchlib/query/tree/queryreplicator.h +++ b/searchlib/src/vespa/searchlib/query/tree/queryreplicator.h @@ -7,8 +7,7 @@ #include "queryvisitor.h" #include "termnodes.h" -namespace search { -namespace query { +namespace search::query { /** * Creates a new query tree based on an existing one. The traits class @@ -70,22 +69,24 @@ private: } void visit(Phrase &node) override { - replicate(node, _builder.addPhrase(node.getChildren().size(), - node.getView(), + replicate(node, _builder.addPhrase(node.getChildren().size(), node.getView(), node.getId(), node.getWeight())); visitNodes(node.getChildren()); } + void visit(SameElement &node) override { + _builder.addSameElement(node.getChildren().size(), node.getView()); + visitNodes(node.getChildren()); + } + void visit(WeightedSetTerm &node) override { - replicate(node, _builder.addWeightedSetTerm(node.getChildren().size(), - node.getView(), + replicate(node, _builder.addWeightedSetTerm(node.getChildren().size(), node.getView(), node.getId(), node.getWeight())); visitNodes(node.getChildren()); } void visit(DotProduct &node) override { - replicate(node, _builder.addDotProduct(node.getChildren().size(), - node.getView(), + replicate(node, _builder.addDotProduct(node.getChildren().size(), node.getView(), node.getId(), node.getWeight())); visitNodes(node.getChildren()); } @@ -165,5 +166,4 @@ private: } }; -} // namespace query -} // namespace search +} diff --git a/searchlib/src/vespa/searchlib/query/tree/querytreecreator.h b/searchlib/src/vespa/searchlib/query/tree/querytreecreator.h index a3e6ac523ae..c42a16d8ab3 100644 --- a/searchlib/src/vespa/searchlib/query/tree/querytreecreator.h +++ b/searchlib/src/vespa/searchlib/query/tree/querytreecreator.h @@ -5,8 +5,7 @@ #include "queryreplicator.h" #include "stackdumpquerycreator.h" -namespace search { -namespace query { +namespace search::query { /** * Holds functions for creating query trees, either from a stack dump @@ -27,6 +26,4 @@ private: QueryTreeCreator(); }; -} // namespace query -} // namespace search - +} diff --git a/searchlib/src/vespa/searchlib/query/tree/queryvisitor.h b/searchlib/src/vespa/searchlib/query/tree/queryvisitor.h index 4596359201b..0cb56f9127a 100644 --- a/searchlib/src/vespa/searchlib/query/tree/queryvisitor.h +++ b/searchlib/src/vespa/searchlib/query/tree/queryvisitor.h @@ -2,8 +2,7 @@ #pragma once -namespace search { -namespace query { +namespace search::query { class And; class AndNot; @@ -26,6 +25,7 @@ class DotProduct; class WandTerm; class PredicateQuery; class RegExpTerm; +class SameElement; struct QueryVisitor { virtual ~QueryVisitor() {} @@ -39,6 +39,7 @@ struct QueryVisitor { virtual void visit(ONear &) = 0; virtual void visit(Or &) = 0; virtual void visit(Phrase &) = 0; + virtual void visit(SameElement &node) = 0; virtual void visit(PrefixTerm &) = 0; virtual void visit(RangeTerm &) = 0; virtual void visit(Rank &) = 0; @@ -53,6 +54,5 @@ struct QueryVisitor { virtual void visit(RegExpTerm &) = 0; }; -} // namespace query -} // namespace search +} diff --git a/searchlib/src/vespa/searchlib/query/tree/range.cpp b/searchlib/src/vespa/searchlib/query/tree/range.cpp index 583d57bb74d..202b80d98a2 100644 --- a/searchlib/src/vespa/searchlib/query/tree/range.cpp +++ b/searchlib/src/vespa/searchlib/query/tree/range.cpp @@ -3,8 +3,7 @@ #include "range.h" #include <vespa/vespalib/stllike/asciistream.h> -namespace search { -namespace query { +namespace search::query { Range::Range(int64_t f, int64_t t) { @@ -18,5 +17,4 @@ vespalib::asciistream &operator<<(vespalib::asciistream &out, const Range &range return out << range.getRangeString(); } -} // namespace query -} // namespace search +} diff --git a/searchlib/src/vespa/searchlib/query/tree/range.h b/searchlib/src/vespa/searchlib/query/tree/range.h index 862258873e6..e55ddf7f14b 100644 --- a/searchlib/src/vespa/searchlib/query/tree/range.h +++ b/searchlib/src/vespa/searchlib/query/tree/range.h @@ -3,12 +3,9 @@ #pragma once #include <vespa/vespalib/stllike/string.h> -namespace vespalib { - class asciistream; -} +namespace vespalib { class asciistream; } -namespace search { -namespace query { +namespace search::query { class Range { vespalib::string _range; @@ -27,6 +24,4 @@ inline bool operator==(const Range &r1, const Range &r2) { vespalib::asciistream &operator<<(vespalib::asciistream &out, const Range &range); -} // namespace query -} // namespace search - +} diff --git a/searchlib/src/vespa/searchlib/query/tree/rectangle.h b/searchlib/src/vespa/searchlib/query/tree/rectangle.h index 29b144ac5dc..97be9ddeb32 100644 --- a/searchlib/src/vespa/searchlib/query/tree/rectangle.h +++ b/searchlib/src/vespa/searchlib/query/tree/rectangle.h @@ -2,8 +2,7 @@ #pragma once -namespace search { -namespace query { +namespace search::query { struct Rectangle { int64_t left; @@ -21,6 +20,5 @@ inline bool operator==(const Rectangle &r1, const Rectangle &r2) { && r1.top == r2.top && r1.bottom == r2.bottom; } -} // namespace query -} // namespace search +} diff --git a/searchlib/src/vespa/searchlib/query/tree/simplequery.h b/searchlib/src/vespa/searchlib/query/tree/simplequery.h index 28791dafe53..557d0964bcb 100644 --- a/searchlib/src/vespa/searchlib/query/tree/simplequery.h +++ b/searchlib/src/vespa/searchlib/query/tree/simplequery.h @@ -10,8 +10,7 @@ #include "intermediatenodes.h" #include "termnodes.h" -namespace search { -namespace query { +namespace search::query { struct SimpleAnd : And {}; struct SimpleAndNot : AndNot {}; @@ -31,6 +30,10 @@ struct SimplePhrase : Phrase { SimplePhrase(const vespalib::stringref &view, int32_t id, Weight weight) : Phrase(view, id, weight) {} }; + +struct SimpleSameElement : SameElement { + SimpleSameElement(const vespalib::stringref &view) : SameElement(view) {} +}; struct SimpleWeightedSetTerm : WeightedSetTerm { SimpleWeightedSetTerm(const vespalib::stringref &view, int32_t id, Weight weight) : WeightedSetTerm(view, id, weight) {} @@ -112,6 +115,7 @@ struct SimpleQueryNodeTypes { typedef SimpleONear ONear; typedef SimpleOr Or; typedef SimplePhrase Phrase; + typedef SimpleSameElement SameElement; typedef SimplePrefixTerm PrefixTerm; typedef SimpleRangeTerm RangeTerm; typedef SimpleRank Rank; @@ -126,6 +130,4 @@ struct SimpleQueryNodeTypes { typedef SimpleRegExpTerm RegExpTerm; }; -} // namespace query -} // namespace search - +} diff --git a/searchlib/src/vespa/searchlib/query/tree/stackdumpcreator.cpp b/searchlib/src/vespa/searchlib/query/tree/stackdumpcreator.cpp index 771830c0b03..645750b8576 100644 --- a/searchlib/src/vespa/searchlib/query/tree/stackdumpcreator.cpp +++ b/searchlib/src/vespa/searchlib/query/tree/stackdumpcreator.cpp @@ -64,23 +64,48 @@ class QueryNodeConverter : public QueryVisitor { template <typename V> void appendPredicateQueryTermVector(const V& v); + void createComplexIntermediate(const Term &node, const std::vector<Node *> & children, size_t type) { + uint8_t flags = 0; + if (!node.isRanked()) { + flags |= ParseItem::IFLAG_NORANK; + } + if (!node.usePositionData()) { + flags |= ParseItem::IFLAG_NOPOSITIONDATA; + } + if (flags != 0) { + type |= ParseItem::IF_FLAGS; + } + appendByte(type); + appendCompressedNumber(node.getWeight().percent()); + if (type & ParseItem::IF_FLAGS) { + appendByte(flags); + } + appendCompressedPositiveNumber(children.size()); + appendString(node.getView()); + visitNodes(children); + } + void createIntermediate(const Intermediate &node, size_t type) { appendByte(type); appendCompressedPositiveNumber(node.getChildren().size()); visitNodes(node.getChildren()); } - void createIntermediate(const Intermediate &node, size_t type, - size_t distance) { + void createIntermediate(const Intermediate &node, size_t type, size_t distance) { appendByte(type); appendCompressedPositiveNumber(node.getChildren().size()); appendCompressedPositiveNumber(distance); visitNodes(node.getChildren()); } - void createIntermediate(const Intermediate &node, size_t type, - size_t distance, - const vespalib::string & view) { + void createIntermediate(const Intermediate &node, size_t type, const vespalib::string & view) { + appendByte(type); + appendCompressedPositiveNumber(node.getChildren().size()); + appendString(view); + visitNodes(node.getChildren()); + } + + void createIntermediate(const Intermediate &node, size_t type, size_t distance, const vespalib::string & view) { appendByte(type); appendCompressedPositiveNumber(node.getChildren().size()); appendCompressedPositiveNumber(distance); @@ -116,26 +141,12 @@ class QueryNodeConverter : public QueryVisitor { createIntermediate(node, ParseItem::ITEM_EQUIV); } + void visit(SameElement &node) override { + createIntermediate(node, ParseItem::ITEM_SAME_ELEMENT, node.getView()); + } + void visit(Phrase &node) override { - uint8_t typefield = (ParseItem::ITEM_PHRASE | ParseItem::IF_WEIGHT); - uint8_t flags = 0; - if (!node.isRanked()) { - flags |= ParseItem::IFLAG_NORANK; - } - if (!node.usePositionData()) { - flags |= ParseItem::IFLAG_NOPOSITIONDATA; - } - if (flags != 0) { - typefield |= ParseItem::IF_FLAGS; - } - appendByte(typefield); - appendCompressedNumber(node.getWeight().percent()); - if (typefield & ParseItem::IF_FLAGS) { - appendByte(flags); - } - appendCompressedPositiveNumber(node.getChildren().size()); - appendString(node.getView()); - visitNodes(node.getChildren()); + createComplexIntermediate(node, node.getChildren(), (ParseItem::ITEM_PHRASE | ParseItem::IF_WEIGHT)); } template <typename NODE> @@ -187,9 +198,7 @@ class QueryNodeConverter : public QueryVisitor { template <class Term> void createTerm(const Term &node, size_t type) { - uint8_t typefield = type | - ParseItem::IF_WEIGHT | - ParseItem::IF_UNIQUEID; + uint8_t typefield = type | ParseItem::IF_WEIGHT | ParseItem::IF_UNIQUEID; uint8_t flags = 0; if (!node.isRanked()) { flags |= ParseItem::IFLAG_NORANK; diff --git a/searchlib/src/vespa/searchlib/query/tree/stackdumpcreator.h b/searchlib/src/vespa/searchlib/query/tree/stackdumpcreator.h index 448f1c9bd08..4e1556d05e6 100644 --- a/searchlib/src/vespa/searchlib/query/tree/stackdumpcreator.h +++ b/searchlib/src/vespa/searchlib/query/tree/stackdumpcreator.h @@ -4,8 +4,7 @@ #include <vespa/vespalib/stllike/string.h> -namespace search { -namespace query { +namespace search::query { class Node; @@ -14,6 +13,4 @@ struct StackDumpCreator { static vespalib::string create(const Node &node); }; -} // namespace query -} // namespace search - +} diff --git a/searchlib/src/vespa/searchlib/query/tree/stackdumpquerycreator.h b/searchlib/src/vespa/searchlib/query/tree/stackdumpquerycreator.h index f9c66965cc4..fa42cdac1c0 100644 --- a/searchlib/src/vespa/searchlib/query/tree/stackdumpquerycreator.h +++ b/searchlib/src/vespa/searchlib/query/tree/stackdumpquerycreator.h @@ -9,8 +9,7 @@ #include <vespa/searchlib/parsequery/simplequerystack.h> #include <vespa/vespalib/objects/hexdump.h> -namespace search { -namespace query { +namespace search::query { /** * Creates a query tree from a stack dump. @@ -90,6 +89,10 @@ private: Weight weight = queryStack.GetWeight(); t = &builder.addPhrase(arity, view, id, weight); pureTermView = view; + } else if (type == ParseItem::ITEM_SAME_ELEMENT) { + vespalib::stringref view = queryStack.getIndexName(); + builder.addSameElement(arity, view); + pureTermView = view; } else if (type == ParseItem::ITEM_WEIGHTED_SET) { vespalib::stringref view = queryStack.getIndexName(); int32_t id = queryStack.getUniqueId(); @@ -152,6 +155,4 @@ private: } }; -} // namespace query -} // namespace search - +} diff --git a/searchlib/src/vespa/searchlib/query/tree/templatetermvisitor.h b/searchlib/src/vespa/searchlib/query/tree/templatetermvisitor.h index e4ce4ccf807..0cdaca82572 100644 --- a/searchlib/src/vespa/searchlib/query/tree/templatetermvisitor.h +++ b/searchlib/src/vespa/searchlib/query/tree/templatetermvisitor.h @@ -4,8 +4,7 @@ #include "customtypetermvisitor.h" -namespace search { -namespace query { +namespace search::query { /** * Use this class to visit all term nodes by deriving from this class @@ -54,5 +53,4 @@ class TemplateTermVisitor : public CustomTypeTermVisitor<NodeTypes> { void visit(typename NodeTypes::WandTerm &n) override { myVisit(n); } }; -} // namespace query -} // namespace search +} diff --git a/searchlib/src/vespa/searchlib/query/tree/term.cpp b/searchlib/src/vespa/searchlib/query/tree/term.cpp index 54def08afe8..de59752aa10 100644 --- a/searchlib/src/vespa/searchlib/query/tree/term.cpp +++ b/searchlib/src/vespa/searchlib/query/tree/term.cpp @@ -1,11 +1,11 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #include "term.h" +#include <cassert> -namespace search { -namespace query { +namespace search::query { -Term::~Term() { } +Term::~Term() = default; Term::Term(const vespalib::stringref &view, int32_t id, Weight weight) : _view(view), @@ -16,5 +16,14 @@ Term::Term(const vespalib::stringref &view, int32_t id, Weight weight) : _position_data(true) { } -} // namespace query -} // namespace search +void Term::setStateFrom(const Term& other) { + setTermIndex(other.getTermIndex()); + setRanked(other.isRanked()); + setPositionData(other.usePositionData()); + // too late to copy this state: + assert(_view == other.getView()); + assert(_id == other.getId()); + assert(_weight == other.getWeight()); +} + +} diff --git a/searchlib/src/vespa/searchlib/query/tree/term.h b/searchlib/src/vespa/searchlib/query/tree/term.h index f8c0d98ac22..8e9b9897e9d 100644 --- a/searchlib/src/vespa/searchlib/query/tree/term.h +++ b/searchlib/src/vespa/searchlib/query/tree/term.h @@ -1,13 +1,11 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #pragma once -#include <vespa/vespalib/stllike/string.h> -#include <vespa/searchlib/query/tree/node.h> +#include "node.h" #include <vespa/searchlib/query/weight.h> -#include <cassert> +#include <vespa/vespalib/stllike/string.h> -namespace search { -namespace query { +namespace search::query { /** * This is a leaf in the Query tree. Sort of. Phrases are both terms @@ -16,11 +14,11 @@ namespace query { class Term { vespalib::string _view; - int32_t _id; - Weight _weight; - int32_t _term_index; - bool _ranked; - bool _position_data; + int32_t _id; + Weight _weight; + int32_t _term_index; + bool _ranked; + bool _position_data; public: virtual ~Term() = 0; @@ -29,15 +27,7 @@ public: void setRanked(bool ranked) { _ranked = ranked; } void setPositionData(bool position_data) { _position_data = position_data; } - void setStateFrom(const Term& other) { - setTermIndex(other.getTermIndex()); - setRanked(other.isRanked()); - setPositionData(other.usePositionData()); - // too late to copy this state: - assert(_view == other.getView()); - assert(_id == other.getId()); - assert(_weight == other.getWeight()); - } + void setStateFrom(const Term& other); const vespalib::string & getView() const { return _view; } Weight getWeight() const { return _weight; } @@ -60,7 +50,7 @@ class TermBase : public Node, public Term { public: typedef T Type; - virtual ~TermBase() = 0; + ~TermBase() override = 0; const T &getTerm() const { return _term; } protected: @@ -71,8 +61,6 @@ protected: }; template <typename T> -TermBase<T>::~TermBase() {} - -} // namespace query -} // namespace search +TermBase<T>::~TermBase() = default; +} diff --git a/searchlib/src/vespa/searchlib/query/tree/termnodes.cpp b/searchlib/src/vespa/searchlib/query/tree/termnodes.cpp index 8e8ae16827b..0a6a6af62b5 100644 --- a/searchlib/src/vespa/searchlib/query/tree/termnodes.cpp +++ b/searchlib/src/vespa/searchlib/query/tree/termnodes.cpp @@ -2,27 +2,25 @@ #include "termnodes.h" -namespace search { -namespace query { +namespace search::query { -NumberTerm::~NumberTerm() {} +NumberTerm::~NumberTerm() = default; -PrefixTerm::~PrefixTerm() {} +PrefixTerm::~PrefixTerm() = default; -RangeTerm::~RangeTerm() {} +RangeTerm::~RangeTerm() = default; StringTerm::StringTerm(const Type &term, const vespalib::stringref &view, int32_t id, Weight weight) : QueryNodeMixinType(term, view, id, weight) {} -StringTerm::~StringTerm() {} +StringTerm::~StringTerm() = default; -SubstringTerm::~SubstringTerm() {} +SubstringTerm::~SubstringTerm() = default; -SuffixTerm::~SuffixTerm() {} +SuffixTerm::~SuffixTerm() = default; -LocationTerm::~LocationTerm() {} +LocationTerm::~LocationTerm() = default; -RegExpTerm::~RegExpTerm() {} +RegExpTerm::~RegExpTerm() = default; -} // namespace query -} // namespace search +} diff --git a/searchlib/src/vespa/searchlib/query/tree/termnodes.h b/searchlib/src/vespa/searchlib/query/tree/termnodes.h index 4c98ba92ff5..8d4882fb393 100644 --- a/searchlib/src/vespa/searchlib/query/tree/termnodes.h +++ b/searchlib/src/vespa/searchlib/query/tree/termnodes.h @@ -8,8 +8,7 @@ #include "range.h" #include "term.h" -namespace search { -namespace query { +namespace search::query { typedef TermBase<vespalib::string> StringBase; @@ -117,6 +116,4 @@ public: }; -} // namespace query -} // namespace search - +} diff --git a/searchlib/src/vespa/searchlib/query/weight.h b/searchlib/src/vespa/searchlib/query/weight.h index 1b4168231c5..51596642cd2 100644 --- a/searchlib/src/vespa/searchlib/query/weight.h +++ b/searchlib/src/vespa/searchlib/query/weight.h @@ -3,8 +3,7 @@ #include <cstdint> -namespace search { -namespace query { +namespace search::query { /** * Represents the weight given on a query item such as a term, phrase, or equiv. @@ -44,8 +43,7 @@ public: bool operator== (const Weight& other) const { return _weight == other._weight; } }; -} // namespace query -} // namespace search +} inline search::query::Weight operator+(const search::query::Weight& a, const search::query::Weight& b) { diff --git a/searchlib/src/vespa/searchlib/queryeval/create_blueprint_visitor_helper.cpp b/searchlib/src/vespa/searchlib/queryeval/create_blueprint_visitor_helper.cpp index 8e6429aaa90..e3dac98e588 100644 --- a/searchlib/src/vespa/searchlib/queryeval/create_blueprint_visitor_helper.cpp +++ b/searchlib/src/vespa/searchlib/queryeval/create_blueprint_visitor_helper.cpp @@ -19,7 +19,7 @@ CreateBlueprintVisitorHelper::CreateBlueprintVisitorHelper(Searchable &searchabl _result() {} -CreateBlueprintVisitorHelper::~CreateBlueprintVisitorHelper() {} +CreateBlueprintVisitorHelper::~CreateBlueprintVisitorHelper() = default; Blueprint::UP CreateBlueprintVisitorHelper::getResult() @@ -30,7 +30,7 @@ CreateBlueprintVisitorHelper::getResult() } void -CreateBlueprintVisitorHelper::visitPhrase(search::query::Phrase &n) { +CreateBlueprintVisitorHelper::visitPhrase(query::Phrase &n) { SimplePhraseBlueprint *phrase = new SimplePhraseBlueprint(_field, _requestContext); Blueprint::UP result(phrase); for (size_t i = 0; i < n.getChildren().size(); ++i) { @@ -42,7 +42,7 @@ CreateBlueprintVisitorHelper::visitPhrase(search::query::Phrase &n) { } void -CreateBlueprintVisitorHelper::handleNumberTermAsText(search::query::NumberTerm &n) +CreateBlueprintVisitorHelper::handleNumberTermAsText(query::NumberTerm &n) { vespalib::string termStr = termAsString(n); queryeval::SplitFloat splitter(termStr); @@ -73,24 +73,24 @@ CreateBlueprintVisitorHelper::createWeightedSet(WS *bp, NODE &n) { for (size_t i = 0; i < n.getChildren().size(); ++i) { fields.clear(); fields.add(bp->getNextChildField(_field)); - const search::query::Node &node = *n.getChildren()[i]; + const query::Node &node = *n.getChildren()[i]; uint32_t weight = getWeightFromNode(node).percent(); bp->addTerm(_searchable.createBlueprint(_requestContext, fields, node), weight); } setResult(std::move(result)); } void -CreateBlueprintVisitorHelper::visitWeightedSetTerm(search::query::WeightedSetTerm &n) { +CreateBlueprintVisitorHelper::visitWeightedSetTerm(query::WeightedSetTerm &n) { WeightedSetTermBlueprint *bp = new WeightedSetTermBlueprint(_field); createWeightedSet(bp, n); } void -CreateBlueprintVisitorHelper::visitDotProduct(search::query::DotProduct &n) { +CreateBlueprintVisitorHelper::visitDotProduct(query::DotProduct &n) { DotProductBlueprint *bp = new DotProductBlueprint(_field); createWeightedSet(bp, n); } void -CreateBlueprintVisitorHelper::visitWandTerm(search::query::WandTerm &n) { +CreateBlueprintVisitorHelper::visitWandTerm(query::WandTerm &n) { ParallelWeakAndBlueprint *bp = new ParallelWeakAndBlueprint(_field, n.getTargetNumHits(), n.getScoreThreshold(), diff --git a/searchlib/src/vespa/searchlib/queryeval/create_blueprint_visitor_helper.h b/searchlib/src/vespa/searchlib/queryeval/create_blueprint_visitor_helper.h index cded9c103dc..5bcc4f4c4c5 100644 --- a/searchlib/src/vespa/searchlib/queryeval/create_blueprint_visitor_helper.h +++ b/searchlib/src/vespa/searchlib/queryeval/create_blueprint_visitor_helper.h @@ -12,7 +12,7 @@ namespace search::queryeval { -class CreateBlueprintVisitorHelper : public search::query::QueryVisitor +class CreateBlueprintVisitorHelper : public query::QueryVisitor { private: const IRequestContext & _requestContext; @@ -37,42 +37,43 @@ public: const FieldSpec &getField() const { return _field; } - void visitPhrase(search::query::Phrase &n); + void visitPhrase(query::Phrase &n); template <typename WS, typename NODE> void createWeightedSet(WS *bp, NODE &n); - void visitWeightedSetTerm(search::query::WeightedSetTerm &n); - void visitDotProduct(search::query::DotProduct &n); - void visitWandTerm(search::query::WandTerm &n); + void visitWeightedSetTerm(query::WeightedSetTerm &n); + void visitDotProduct(query::DotProduct &n); + void visitWandTerm(query::WandTerm &n); - void handleNumberTermAsText(search::query::NumberTerm &n); + void handleNumberTermAsText(query::NumberTerm &n); void illegalVisit() {} - void visit(search::query::And &) override { illegalVisit(); } - void visit(search::query::AndNot &) override { illegalVisit(); } - void visit(search::query::Equiv &) override { illegalVisit(); } - void visit(search::query::Near &) override { illegalVisit(); } - void visit(search::query::ONear &) override { illegalVisit(); } - void visit(search::query::Or &) override { illegalVisit(); } - void visit(search::query::Rank &) override { illegalVisit(); } - void visit(search::query::WeakAnd &) override { illegalVisit(); } - - void visit(search::query::Phrase &n) override { + void visit(query::And &) override { illegalVisit(); } + void visit(query::AndNot &) override { illegalVisit(); } + void visit(query::Equiv &) override { illegalVisit(); } + void visit(query::Near &) override { illegalVisit(); } + void visit(query::ONear &) override { illegalVisit(); } + void visit(query::Or &) override { illegalVisit(); } + void visit(query::Rank &) override { illegalVisit(); } + void visit(query::WeakAnd &) override { illegalVisit(); } + void visit(query::SameElement &) override { illegalVisit(); } + + void visit(query::Phrase &n) override { visitPhrase(n); } - void visit(search::query::WeightedSetTerm &n) override { visitWeightedSetTerm(n); } - void visit(search::query::DotProduct &n) override { visitDotProduct(n); } - void visit(search::query::WandTerm &n) override { visitWandTerm(n); } - - void visit(search::query::NumberTerm &n) override = 0; - void visit(search::query::LocationTerm &n) override = 0; - void visit(search::query::PrefixTerm &n) override = 0; - void visit(search::query::RangeTerm &n) override = 0; - void visit(search::query::StringTerm &n) override = 0; - void visit(search::query::SubstringTerm &n) override = 0; - void visit(search::query::SuffixTerm &n) override = 0; - void visit(search::query::RegExpTerm &n) override = 0; + void visit(query::WeightedSetTerm &n) override { visitWeightedSetTerm(n); } + void visit(query::DotProduct &n) override { visitDotProduct(n); } + void visit(query::WandTerm &n) override { visitWandTerm(n); } + + void visit(query::NumberTerm &n) override = 0; + void visit(query::LocationTerm &n) override = 0; + void visit(query::PrefixTerm &n) override = 0; + void visit(query::RangeTerm &n) override = 0; + void visit(query::StringTerm &n) override = 0; + void visit(query::SubstringTerm &n) override = 0; + void visit(query::SuffixTerm &n) override = 0; + void visit(query::RegExpTerm &n) override = 0; }; } diff --git a/searchlib/src/vespa/searchlib/queryeval/get_weight_from_node.cpp b/searchlib/src/vespa/searchlib/queryeval/get_weight_from_node.cpp index 8fa6af74ae2..bd9de0a1762 100644 --- a/searchlib/src/vespa/searchlib/queryeval/get_weight_from_node.cpp +++ b/searchlib/src/vespa/searchlib/queryeval/get_weight_from_node.cpp @@ -13,8 +13,7 @@ using search::query::Weight; namespace search::queryeval { namespace { -struct WeightExtractor : public TemplateTermVisitor<WeightExtractor, - SimpleQueryNodeTypes> { +struct WeightExtractor : public TemplateTermVisitor<WeightExtractor, SimpleQueryNodeTypes> { Weight weight; WeightExtractor() : weight(0) {} diff --git a/searchlib/src/vespa/searchlib/queryeval/termasstring.cpp b/searchlib/src/vespa/searchlib/queryeval/termasstring.cpp index 14a6cefaf1b..3829ea45e2b 100644 --- a/searchlib/src/vespa/searchlib/queryeval/termasstring.cpp +++ b/searchlib/src/vespa/searchlib/queryeval/termasstring.cpp @@ -22,6 +22,7 @@ using search::query::Node; using search::query::ONear; using search::query::Or; using search::query::Phrase; +using search::query::SameElement; using search::query::PredicateQuery; using search::query::PrefixTerm; using search::query::QueryVisitor; @@ -84,6 +85,7 @@ struct TermAsStringVisitor : public QueryVisitor { void visit(ONear &) override {illegalVisit(); } void visit(Or &) override {illegalVisit(); } void visit(Phrase &) override {illegalVisit(); } + void visit(SameElement &) override {illegalVisit(); } void visit(Rank &) override {illegalVisit(); } void visit(WeakAnd &) override {illegalVisit(); } void visit(WeightedSetTerm &) override {illegalVisit(); } diff --git a/searchsummary/src/tests/extractkeywords/extractkeywordstest.cpp b/searchsummary/src/tests/extractkeywords/extractkeywordstest.cpp index eac6f65a48e..b2920b39eaf 100644 --- a/searchsummary/src/tests/extractkeywords/extractkeywordstest.cpp +++ b/searchsummary/src/tests/extractkeywords/extractkeywordstest.cpp @@ -200,7 +200,7 @@ ExtractKeywordsTest::RunTest(int testno, bool verify) stack.Push(new search::ParseItem(search::ParseItem::ITEM_TERM, "foobar")); stack.Push(new search::ParseItem(search::ParseItem::ITEM_TERM, "foo")); stack.Push(new search::ParseItem(search::ParseItem::ITEM_TERM, "bar")); - stack.Push(new search::ParseItem(search::ParseItem::ITEM_PHRASE, 3)); + stack.Push(new search::ParseItem(search::ParseItem::ITEM_PHRASE, 3, "index")); stack.AppendBuffer(&buf); keywords = _extractor->ExtractKeywords(vespalib::stringref(buf.GetDrainPos(), buf.GetUsedLen())); @@ -216,11 +216,11 @@ ExtractKeywordsTest::RunTest(int testno, bool verify) // multiple phrase and term query stack.Push(new search::ParseItem(search::ParseItem::ITEM_TERM, "xyzzy")); stack.Push(new search::ParseItem(search::ParseItem::ITEM_TERM, "xyz")); - stack.Push(new search::ParseItem(search::ParseItem::ITEM_PHRASE, 2)); + stack.Push(new search::ParseItem(search::ParseItem::ITEM_PHRASE, 2, "index")); stack.Push(new search::ParseItem(search::ParseItem::ITEM_TERM, "foobar")); stack.Push(new search::ParseItem(search::ParseItem::ITEM_TERM, "foo")); stack.Push(new search::ParseItem(search::ParseItem::ITEM_TERM, "bar")); - stack.Push(new search::ParseItem(search::ParseItem::ITEM_PHRASE, 3)); + stack.Push(new search::ParseItem(search::ParseItem::ITEM_PHRASE, 3, "index")); stack.Push(new search::ParseItem(search::ParseItem::ITEM_TERM, "baz")); stack.Push(new search::ParseItem(search::ParseItem::ITEM_TERM, "zog")); stack.Push(new search::ParseItem(search::ParseItem::ITEM_AND, 3)); @@ -241,7 +241,7 @@ ExtractKeywordsTest::RunTest(int testno, bool verify) stack.Push(new search::ParseItem(search::ParseItem::ITEM_TERM, "foo")); stack.Push(new search::ParseItem(search::ParseItem::ITEM_AND, 2)); stack.Push(new search::ParseItem(search::ParseItem::ITEM_TERM, "bar")); - stack.Push(new search::ParseItem(search::ParseItem::ITEM_PHRASE, 2)); + stack.Push(new search::ParseItem(search::ParseItem::ITEM_PHRASE, 2, "index")); stack.AppendBuffer(&buf); keywords = _extractor->ExtractKeywords(vespalib::stringref(buf.GetDrainPos(), buf.GetUsedLen())); diff --git a/searchsummary/src/vespa/searchsummary/docsummary/dynamicteaserdfw.cpp b/searchsummary/src/vespa/searchsummary/docsummary/dynamicteaserdfw.cpp index e535eef660c..c7eb63a4480 100644 --- a/searchsummary/src/vespa/searchsummary/docsummary/dynamicteaserdfw.cpp +++ b/searchsummary/src/vespa/searchsummary/docsummary/dynamicteaserdfw.cpp @@ -280,6 +280,7 @@ JuniperQueryAdapter::Traverse(juniper::IQueryVisitor *v) const case search::ParseItem::ITEM_SUFFIXTERM: case search::ParseItem::ITEM_REGEXP: case search::ParseItem::ITEM_PREDICATE_QUERY: + case search::ParseItem::ITEM_SAME_ELEMENT: if (!v->VisitOther(&item, iterator.getArity())) { rc = SkipItem(&iterator); } diff --git a/searchsummary/src/vespa/searchsummary/docsummary/keywordextractor.cpp b/searchsummary/src/vespa/searchsummary/docsummary/keywordextractor.cpp index e153a898f6a..3a60db52cf3 100644 --- a/searchsummary/src/vespa/searchsummary/docsummary/keywordextractor.cpp +++ b/searchsummary/src/vespa/searchsummary/docsummary/keywordextractor.cpp @@ -165,7 +165,7 @@ KeywordExtractor::ExtractKeywords(vespalib::stringref buf) const break; case search::ParseItem::ITEM_PHRASE: - { + { // Must take the next arity TERMS and put together bool phraseterms_was_added = false; int phraseterms = si.getArity(); diff --git a/valgrind-suppressions.txt b/valgrind-suppressions.txt index baef981a3f9..2df6c9c5691 100644 --- a/valgrind-suppressions.txt +++ b/valgrind-suppressions.txt @@ -6,6 +6,14 @@ fun:pthread_create@@GLIBC_2.2.5 } { + NPTL keeps a cache of thread stacks, and metadata for thread local storage is not freed for threads in that cache + Memcheck:Leak + fun:calloc + fun:allocate_dtv + fun:_dl_allocate_tls + fun:pthread_create@@GLIBC_2.2.5 +} +{ This is a bug in glibc. We can not suffer for that. Memcheck:Free fun:free |