summaryrefslogtreecommitdiffstats
path: root/config-model/src
diff options
context:
space:
mode:
Diffstat (limited to 'config-model/src')
-rw-r--r--config-model/src/main/java/com/yahoo/searchdefinition/DocumentReferenceResolver.java12
-rw-r--r--config-model/src/main/java/com/yahoo/searchdefinition/document/Attribute.java88
-rw-r--r--config-model/src/test/cfg/application/validation/global_distribution_validation/searchdefinitions/simple.sd2
-rw-r--r--config-model/src/test/cfg/application/validation/search_alltypes/searchdefinitions/simple.sd2
-rw-r--r--config-model/src/test/derived/importedfields/ad.sd4
-rw-r--r--config-model/src/test/java/com/yahoo/searchdefinition/DocumentReferenceResolverTest.java24
-rw-r--r--config-model/src/test/java/com/yahoo/searchdefinition/derived/SummaryTestCase.java6
-rw-r--r--config-model/src/test/java/com/yahoo/searchdefinition/processing/ImportedFieldsTestCase.java6
-rw-r--r--config-model/src/test/java/com/yahoo/searchdefinition/processing/ReferenceFieldTestCase.java8
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/documentmodel/DocumentModelBuilderReferenceTypeTestCase.java12
10 files changed, 124 insertions, 40 deletions
diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/DocumentReferenceResolver.java b/config-model/src/main/java/com/yahoo/searchdefinition/DocumentReferenceResolver.java
index db22d0b88e9..e583ea3d9b1 100644
--- a/config-model/src/main/java/com/yahoo/searchdefinition/DocumentReferenceResolver.java
+++ b/config-model/src/main/java/com/yahoo/searchdefinition/DocumentReferenceResolver.java
@@ -4,6 +4,7 @@ package com.yahoo.searchdefinition;
import com.yahoo.document.Field;
import com.yahoo.document.ReferenceDataType;
import com.yahoo.searchdefinition.document.SDDocumentType;
+import com.yahoo.searchdefinition.document.SDField;
import java.util.List;
import java.util.Map;
@@ -40,6 +41,12 @@ public class DocumentReferenceResolver {
}
private DocumentReference createDocumentReference(Field field) {
+ if (!isAttribute(field)) {
+ throw new IllegalArgumentException(
+ String.format(
+ "The field '%s' is an invalid document reference. The field must be an attribute.",
+ field.getName()));
+ }
ReferenceDataType reference = (ReferenceDataType) field.getDataType();
String targetDocumentName = getTargetDocumentName(reference);
Search search = searchMapping.get(targetDocumentName);
@@ -51,6 +58,11 @@ public class DocumentReferenceResolver {
return new DocumentReference(field, search);
}
+ private static boolean isAttribute(Field field) {
+ SDField sdField = (SDField) field; // Ugly, but SDDocumentType only expose the fields as the super class Field
+ return sdField.doesAttributing();
+ }
+
private static Map<String, Search> createDocumentNameToSearchMapping(List<Search> searchDefintions) {
return searchDefintions.stream()
.filter(search -> search.getDocument() != null)
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 bc52aa27f4c..a93aeb6914b 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
@@ -1,12 +1,31 @@
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.searchdefinition.document;
-import com.yahoo.document.*;
-import com.yahoo.document.datatypes.*;
+import com.yahoo.document.ArrayDataType;
+import com.yahoo.document.CollectionDataType;
+import com.yahoo.document.DataType;
+import com.yahoo.document.DocumentType;
+import com.yahoo.document.PrimitiveDataType;
+import com.yahoo.document.ReferenceDataType;
+import com.yahoo.document.StructuredDataType;
+import com.yahoo.document.TemporaryStructuredDataType;
+import com.yahoo.document.TensorDataType;
+import com.yahoo.document.WeightedSetDataType;
+import com.yahoo.document.datatypes.ByteFieldValue;
+import com.yahoo.document.datatypes.DoubleFieldValue;
+import com.yahoo.document.datatypes.FieldValue;
+import com.yahoo.document.datatypes.FloatFieldValue;
+import com.yahoo.document.datatypes.IntegerFieldValue;
+import com.yahoo.document.datatypes.LongFieldValue;
+import com.yahoo.document.datatypes.PredicateFieldValue;
+import com.yahoo.document.datatypes.Raw;
+import com.yahoo.document.datatypes.StringFieldValue;
+import com.yahoo.document.datatypes.TensorFieldValue;
import com.yahoo.tensor.TensorType;
import java.io.Serializable;
import java.util.LinkedHashSet;
+import java.util.Objects;
import java.util.Optional;
import java.util.Set;
@@ -37,10 +56,13 @@ public final class Attribute implements Cloneable, Serializable {
private long lowerBound = BooleanIndexDefinition.DEFAULT_LOWER_BOUND;
private long upperBound = BooleanIndexDefinition.DEFAULT_UPPER_BOUND;
private double densePostingListThreshold = BooleanIndexDefinition.DEFAULT_DENSE_POSTING_LIST_THRESHOLD;
-
+
/** This is set if the type of this is TENSOR */
private Optional<TensorType> tensorType = Optional.empty();
+ /** This is set if the type of this is REFERENCE */
+ private final Optional<StructuredDataType> referenceDocumentType;
+
private boolean isPosition = false;
private final Sorting sorting = new Sorting();
@@ -63,7 +85,8 @@ public final class Attribute implements Cloneable, Serializable {
DOUBLE("double", "DOUBLE"),
STRING("string", "STRING"),
PREDICATE("predicate", "PREDICATE"),
- TENSOR("tensor", "TENSOR");
+ TENSOR("tensor", "TENSOR"),
+ REFERENCE("reference", "REFERENCE");
private final String myName; // different from what name() returns.
private final String exportAttributeTypeName;
@@ -103,20 +126,25 @@ public final class Attribute implements Cloneable, Serializable {
/** Creates an attribute with default settings */
public Attribute(String name, DataType fieldType) {
- this(name, convertDataType(fieldType), convertCollectionType(fieldType), convertTensorType(fieldType));
+ this(name, convertDataType(fieldType), convertCollectionType(fieldType), convertTensorType(fieldType), convertTargetType(fieldType));
setRemoveIfZero(fieldType instanceof WeightedSetDataType ? ((WeightedSetDataType)fieldType).removeIfZero() : false);
setCreateIfNonExistent(fieldType instanceof WeightedSetDataType ? ((WeightedSetDataType)fieldType).createIfNonExistent() : false);
}
public Attribute(String name, Type type, CollectionType collectionType) {
- this(name, type, collectionType, Optional.empty());
+ this(name, type, collectionType, Optional.empty(), Optional.empty());
}
- public Attribute(String name, Type type, CollectionType collectionType, Optional<TensorType> tensorType) {
+ public Attribute(String name,
+ Type type,
+ CollectionType collectionType,
+ Optional<TensorType> tensorType,
+ Optional<StructuredDataType> referenceDocumentType) {
this.name=name;
setType(type);
setCollectionType(collectionType);
this.tensorType = tensorType;
+ this.referenceDocumentType = referenceDocumentType;
}
/**
@@ -207,6 +235,8 @@ public final class Attribute implements Cloneable, Serializable {
return Type.TENSOR;
} else if (fieldType instanceof CollectionDataType) {
return convertDataType(((CollectionDataType) fieldType).getNestedType());
+ } else if (fieldType instanceof ReferenceDataType) {
+ return Type.REFERENCE;
} else {
throw new IllegalArgumentException("Don't know which attribute type to " +
"convert " + fieldType + " to");
@@ -223,6 +253,8 @@ public final class Attribute implements Cloneable, Serializable {
return CollectionType.SINGLE;
} else if (fieldType instanceof PrimitiveDataType) {
return CollectionType.SINGLE;
+ } else if (fieldType instanceof ReferenceDataType) {
+ return CollectionType.SINGLE;
} else {
throw new IllegalArgumentException("Field " + fieldType + " not supported in convertCollectionType");
}
@@ -233,6 +265,13 @@ public final class Attribute implements Cloneable, Serializable {
return Optional.of(((TensorDataType)fieldType).getTensorType());
}
+ private static Optional<StructuredDataType> convertTargetType(DataType fieldType) {
+ return Optional.of(fieldType)
+ .filter(ReferenceDataType.class::isInstance)
+ .map(ReferenceDataType.class::cast)
+ .map(ReferenceDataType::getTargetType);
+ }
+
/** Converts to the right field type from an attribute type */
private DataType toDataType(Type attributeType) {
switch (attributeType) {
@@ -244,10 +283,23 @@ public final class Attribute implements Cloneable, Serializable {
case BYTE: return DataType.BYTE;
case PREDICATE: return DataType.PREDICATE;
case TENSOR: return DataType.getTensor(tensorType.orElseThrow(IllegalStateException::new));
+ case REFERENCE: return createReferenceDataType();
default: throw new IllegalArgumentException("Unknown attribute type " + attributeType);
}
}
+ private DataType createReferenceDataType() {
+ if (!referenceDocumentType.isPresent()) {
+ throw new IllegalStateException("Referenced document type is not set!");
+ }
+ StructuredDataType type = referenceDocumentType.get();
+ if (type instanceof DocumentType) {
+ return ReferenceDataType.createWithInferredId((DocumentType) type);
+ } else {
+ return ReferenceDataType.createWithInferredId((TemporaryStructuredDataType) type);
+ }
+ }
+
public DataType getDataType() {
DataType dataType = toDataType(type);
if (collectionType.equals(Attribute.CollectionType.ARRAY)) {
@@ -259,22 +311,14 @@ public final class Attribute implements Cloneable, Serializable {
}
}
+ @Override
public int hashCode() {
- return name.hashCode() +
- type.hashCode() +
- collectionType.hashCode() +
- sorting.hashCode() +
- (isPrefetch() ? 13 : 0) +
- (fastSearch ? 17 : 0) +
- (removeIfZero ? 47 : 0) +
- (createIfNonExistent ? 53 : 0) +
- (isPosition ? 61 : 0) +
- (huge ? 67 : 0) +
- (enableBitVectors ? 71 : 0) +
- (enableOnlyBitVector ? 73 : 0) +
- tensorType.hashCode();
+ return Objects.hash(
+ name, type, collectionType, sorting, isPrefetch(), fastAccess, removeIfZero, createIfNonExistent,
+ isPosition, huge, enableBitVectors, enableOnlyBitVector, tensorType, referenceDocumentType);
}
+ @Override
public boolean equals(Object object) {
if (! (object instanceof Attribute)) return false;
@@ -297,11 +341,13 @@ public final class Attribute implements Cloneable, Serializable {
if (this.huge != other.huge) return false;
if ( ! this.sorting.equals(other.sorting)) return false;
if (!this.tensorType.equals(other.tensorType)) return false;
+ if (!this.referenceDocumentType.equals(other.referenceDocumentType)) return false;
return true;
}
- public @Override Attribute clone() {
+ @Override
+ public Attribute clone() {
try {
return (Attribute)super.clone();
}
diff --git a/config-model/src/test/cfg/application/validation/global_distribution_validation/searchdefinitions/simple.sd b/config-model/src/test/cfg/application/validation/global_distribution_validation/searchdefinitions/simple.sd
index 49572be1cae..49223fabb76 100644
--- a/config-model/src/test/cfg/application/validation/global_distribution_validation/searchdefinitions/simple.sd
+++ b/config-model/src/test/cfg/application/validation/global_distribution_validation/searchdefinitions/simple.sd
@@ -1,6 +1,6 @@
# Copyright 2017 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
search simple {
document simple {
- field my_reference type reference<parent> { indexing: summary }
+ field my_reference type reference<parent> { indexing: summary | attribute }
}
}
diff --git a/config-model/src/test/cfg/application/validation/search_alltypes/searchdefinitions/simple.sd b/config-model/src/test/cfg/application/validation/search_alltypes/searchdefinitions/simple.sd
index 05d8b735249..36d8012b38e 100644
--- a/config-model/src/test/cfg/application/validation/search_alltypes/searchdefinitions/simple.sd
+++ b/config-model/src/test/cfg/application/validation/search_alltypes/searchdefinitions/simple.sd
@@ -12,6 +12,6 @@ search simple {
field my_byte type byte { indexing: summary }
field my_predicate type predicate { indexing: summary }
field my_tensor type tensor(x{}) { indexing: summary }
- field my_reference type reference<parent> { indexing: summary }
+ field my_reference type reference<parent> { indexing: summary | attribute }
}
}
diff --git a/config-model/src/test/derived/importedfields/ad.sd b/config-model/src/test/derived/importedfields/ad.sd
index ceb7acc7df4..fbc4925c542 100644
--- a/config-model/src/test/derived/importedfields/ad.sd
+++ b/config-model/src/test/derived/importedfields/ad.sd
@@ -1,7 +1,7 @@
search ad {
document ad {
- field campaign_ref type reference<campaign> {}
- field person_ref type reference<person> {}
+ field campaign_ref type reference<campaign> { indexing: attribute }
+ field person_ref type reference<person> { indexing: attribute }
}
import field campaign_ref.budget as my_budget {}
import field person_ref.name as my_person_name {}
diff --git a/config-model/src/test/java/com/yahoo/searchdefinition/DocumentReferenceResolverTest.java b/config-model/src/test/java/com/yahoo/searchdefinition/DocumentReferenceResolverTest.java
index c5e1df77210..da9680aa641 100644
--- a/config-model/src/test/java/com/yahoo/searchdefinition/DocumentReferenceResolverTest.java
+++ b/config-model/src/test/java/com/yahoo/searchdefinition/DocumentReferenceResolverTest.java
@@ -35,6 +35,7 @@ public class DocumentReferenceResolverTest {
// Create foo document with document reference to bar and add another field
SDField fooRefToBarField = new SDField
("bar_ref", ReferenceDataType.createWithInferredId(barDocument.getDocumentType()));
+ fooRefToBarField.parseIndexingScript("{ attribute }");
SDField irrelevantField = new SDField("irrelevant_stuff", DataType.INT);
Search fooSearch = new Search();
SDDocumentType fooDocument = new SDDocumentType("foo", fooSearch);
@@ -57,6 +58,7 @@ public class DocumentReferenceResolverTest {
// Create foo document with document reference to non-existing document bar
SDField fooRefToBarField = new SDField(
"bar_ref", ReferenceDataType.createWithInferredId(TemporaryStructuredDataType.create("bar")));
+ fooRefToBarField.parseIndexingScript("{ attribute }");
Search fooSearch = new Search();
SDDocumentType fooDocument = new SDDocumentType("foo", fooSearch);
fooDocument.addField(fooRefToBarField);
@@ -71,4 +73,26 @@ public class DocumentReferenceResolverTest {
resolver.resolveReferences(fooDocument);
}
+ @Test
+ public void throws_exception_if_reference_is_not_an_attribute() {
+ // Create bar document with no fields
+ Search barSearch = new Search();
+ SDDocumentType barDocument = new SDDocumentType("bar", barSearch);
+ barSearch.addDocument(barDocument);
+
+ // Create foo document with document reference to bar and add another field
+ SDField fooRefToBarField = new SDField
+ ("bar_ref", ReferenceDataType.createWithInferredId(barDocument.getDocumentType()));
+ Search fooSearch = new Search();
+ SDDocumentType fooDocument = new SDDocumentType("foo", fooSearch);
+ fooDocument.addField(fooRefToBarField);
+ fooSearch.addDocument(fooDocument);
+
+ DocumentReferenceResolver resolver = new DocumentReferenceResolver(asList(fooSearch, barSearch));
+ exceptionRule.expect(IllegalArgumentException.class);
+ exceptionRule.expectMessage(
+ "The field 'bar_ref' is an invalid document reference. The field must be an attribute.");
+ resolver.resolveReferences(fooDocument);
+ }
+
}
diff --git a/config-model/src/test/java/com/yahoo/searchdefinition/derived/SummaryTestCase.java b/config-model/src/test/java/com/yahoo/searchdefinition/derived/SummaryTestCase.java
index 54d10327de1..cdc4cbce77f 100644
--- a/config-model/src/test/java/com/yahoo/searchdefinition/derived/SummaryTestCase.java
+++ b/config-model/src/test/java/com/yahoo/searchdefinition/derived/SummaryTestCase.java
@@ -105,9 +105,11 @@ public class SummaryTestCase extends SearchDefinitionTestCase {
builder.importString(joinLines("search ad {",
" document ad {",
" field campaign_ref type reference<campaign> {",
- " indexing: summary",
+ " indexing: summary | attribute",
+ " }",
+ " field other_campaign_ref type reference<campaign> {",
+ " indexing: summary | attribute",
" }",
- " field other_campaign_ref type reference<campaign> {}",
" }",
" document-summary my_summary {",
" summary other_campaign_ref type reference<campaign> {}",
diff --git a/config-model/src/test/java/com/yahoo/searchdefinition/processing/ImportedFieldsTestCase.java b/config-model/src/test/java/com/yahoo/searchdefinition/processing/ImportedFieldsTestCase.java
index 44b30e3419a..4222a4ef66a 100644
--- a/config-model/src/test/java/com/yahoo/searchdefinition/processing/ImportedFieldsTestCase.java
+++ b/config-model/src/test/java/com/yahoo/searchdefinition/processing/ImportedFieldsTestCase.java
@@ -23,8 +23,8 @@ public class ImportedFieldsTestCase {
Search search = buildAdSearch(joinLines(
"search ad {",
" document ad {",
- " field campaign_ref type reference<campaign> {}",
- " field person_ref type reference<person> {}",
+ " field campaign_ref type reference<campaign> { indexing: attribute }",
+ " field person_ref type reference<person> { indexing: attribute }",
" }",
" import field campaign_ref.budget as my_budget {}",
" import field person_ref.name as my_name {}",
@@ -39,7 +39,7 @@ public class ImportedFieldsTestCase {
Search search = buildAdSearch(joinLines("search ad {",
" document ad {",
" field title type string { indexing: attribute }",
- " field self_ref type reference<ad> {}",
+ " field self_ref type reference<ad> { indexing: attribute }",
" }",
" import field self_ref.title as my_title {}",
"}"));
diff --git a/config-model/src/test/java/com/yahoo/searchdefinition/processing/ReferenceFieldTestCase.java b/config-model/src/test/java/com/yahoo/searchdefinition/processing/ReferenceFieldTestCase.java
index 016ae8b8e67..42f8c302346 100644
--- a/config-model/src/test/java/com/yahoo/searchdefinition/processing/ReferenceFieldTestCase.java
+++ b/config-model/src/test/java/com/yahoo/searchdefinition/processing/ReferenceFieldTestCase.java
@@ -41,8 +41,8 @@ public class ReferenceFieldTestCase {
String adSdContent =
"search ad {\n" +
" document ad {\n" +
- " field campaign_ref type reference<campaign> {}\n" +
- " field salesperson_ref type reference<salesperson> {}\n" +
+ " field campaign_ref type reference<campaign> { indexing: attribute }\n" +
+ " field salesperson_ref type reference<salesperson> { indexing: attribute }\n" +
" }\n" +
"}";
builder.importString(campaignSdContent);
@@ -60,13 +60,13 @@ public class ReferenceFieldTestCase {
String campaignSdContent =
"search campaign {\n" +
" document campaign {\n" +
- " field ad_ref type reference<ad> {}\n" +
+ " field ad_ref type reference<ad> { indexing: attribute }\n" +
" }\n" +
"}";
String adSdContent =
"search ad {\n" +
" document ad {\n" +
- " field campaign_ref type reference<campaign> {}\n" +
+ " field campaign_ref type reference<campaign> { indexing: attribute }\n" +
" }\n" +
"}";
builder.importString(campaignSdContent);
diff --git a/config-model/src/test/java/com/yahoo/vespa/documentmodel/DocumentModelBuilderReferenceTypeTestCase.java b/config-model/src/test/java/com/yahoo/vespa/documentmodel/DocumentModelBuilderReferenceTypeTestCase.java
index d2e41d0ec6d..bb115ff43e2 100644
--- a/config-model/src/test/java/com/yahoo/vespa/documentmodel/DocumentModelBuilderReferenceTypeTestCase.java
+++ b/config-model/src/test/java/com/yahoo/vespa/documentmodel/DocumentModelBuilderReferenceTypeTestCase.java
@@ -26,8 +26,8 @@ public class DocumentModelBuilderReferenceTypeTestCase extends SearchDefinitionT
assertDocumentConfigs(new TestDocumentModelBuilder().addCampaign().addPerson().build(joinLines(
"search ad {",
" document ad {",
- " field campaign_ref type reference<campaign> {}",
- " field person_ref type reference<person> {}",
+ " field campaign_ref type reference<campaign> { indexing: attribute }",
+ " field person_ref type reference<person> { indexing: attribute }",
" }",
"}")),
"refs_to_other_types");
@@ -38,8 +38,8 @@ public class DocumentModelBuilderReferenceTypeTestCase extends SearchDefinitionT
assertDocumentConfigs(new TestDocumentModelBuilder().addCampaign().build(joinLines(
"search ad {",
" document ad {",
- " field campaign_ref type reference<campaign> {}",
- " field other_campaign_ref type reference<campaign> {}",
+ " field campaign_ref type reference<campaign> { indexing: attribute }",
+ " field other_campaign_ref type reference<campaign> { indexing: attribute }",
" }",
"}")),
"refs_to_same_type");
@@ -50,7 +50,7 @@ public class DocumentModelBuilderReferenceTypeTestCase extends SearchDefinitionT
assertDocumentConfigs(new TestDocumentModelBuilder().build(joinLines(
"search ad {",
" document ad {",
- " field self_ref type reference<ad> {}",
+ " field self_ref type reference<ad> { indexing: attribute }",
" }",
"}")),
"ref_to_self_type");
@@ -61,7 +61,7 @@ public class DocumentModelBuilderReferenceTypeTestCase extends SearchDefinitionT
DocumentModel model = new TestDocumentModelBuilder().addCampaign().build(joinLines(
"search ad {",
" document ad {",
- " field campaign_ref type reference<campaign> {}",
+ " field campaign_ref type reference<campaign> { indexing: attribute }",
" }",
"}"));
NewDocumentType campaignType = model.getDocumentManager().getDocumentType("campaign");