summaryrefslogtreecommitdiffstats
path: root/config-model
diff options
context:
space:
mode:
authorJon Bratseth <bratseth@oath.com>2018-09-20 09:13:16 -0700
committerJon Bratseth <bratseth@oath.com>2018-09-20 09:13:16 -0700
commit7994462805a16f4665e52a0b9f9770d3c7563556 (patch)
tree2d53860f2e956655af720ff60e4c94c2e689d0a4 /config-model
parent5ed8c4deeb8384ac4583177ab618f89b3e6c9461 (diff)
Resolve types of all argument-less functions
Diffstat (limited to 'config-model')
-rw-r--r--config-model/src/main/java/com/yahoo/searchdefinition/RankProfile.java23
-rw-r--r--config-model/src/main/java/com/yahoo/searchdefinition/Search.java14
-rw-r--r--config-model/src/main/java/com/yahoo/searchdefinition/SearchBuilder.java7
-rw-r--r--config-model/src/main/java/com/yahoo/searchdefinition/derived/DerivedConfiguration.java10
-rw-r--r--config-model/src/main/java/com/yahoo/searchdefinition/derived/RawRankProfile.java32
-rw-r--r--config-model/src/main/java/com/yahoo/searchdefinition/processing/Processing.java28
-rw-r--r--config-model/src/main/java/com/yahoo/searchdefinition/processing/RankingExpressionTypeResolver.java (renamed from config-model/src/main/java/com/yahoo/searchdefinition/processing/RankingExpressionTypeValidator.java)57
-rw-r--r--config-model/src/main/java/com/yahoo/searchdefinition/processing/multifieldresolver/RankProfileTypeSettingsProcessor.java2
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/Service.java2
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/VespaModel.java23
-rw-r--r--config-model/src/test/derived/gemini2/gemini.sd6
-rw-r--r--config-model/src/test/java/com/yahoo/searchdefinition/RankingExpressionLoopDetectionTestCase.java6
-rw-r--r--config-model/src/test/java/com/yahoo/searchdefinition/processing/IntegerIndex2AttributeTestCase.java1
-rw-r--r--config-model/src/test/java/com/yahoo/searchdefinition/processing/RankingExpressionTypeResolverTestCase.java (renamed from config-model/src/test/java/com/yahoo/searchdefinition/processing/RankingExpressionTypeValidatorTestCase.java)2
-rw-r--r--config-model/src/test/java/com/yahoo/searchdefinition/processing/SummaryFieldsMustHaveValidSourceTestCase.java5
-rw-r--r--config-model/src/test/java/com/yahoo/searchdefinition/processing/TensorTransformTestCase.java4
16 files changed, 126 insertions, 96 deletions
diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/RankProfile.java b/config-model/src/main/java/com/yahoo/searchdefinition/RankProfile.java
index 16e494c2db1..a06cf36c7bb 100644
--- a/config-model/src/main/java/com/yahoo/searchdefinition/RankProfile.java
+++ b/config-model/src/main/java/com/yahoo/searchdefinition/RankProfile.java
@@ -449,7 +449,7 @@ public class RankProfile implements Serializable, Cloneable {
addRankProperty(new RankProperty(name, parameter));
}
- public void addRankProperty(RankProperty rankProperty) {
+ private void addRankProperty(RankProperty rankProperty) {
// Just the usual multimap semantics here
List<RankProperty> properties = rankProperties.get(rankProperty.getName());
if (properties == null) {
@@ -534,22 +534,21 @@ public class RankProfile implements Serializable, Cloneable {
/** Adds a function and returns it */
public RankingExpressionFunction addFunction(ExpressionFunction function, boolean inline) {
- RankingExpressionFunction rankingExpressionFunction = new RankingExpressionFunction(function, inline);
+ RankingExpressionFunction rankingExpressionFunction = new RankingExpressionFunction(function, inline, Optional.empty());
functions.put(function.getName(), rankingExpressionFunction);
return rankingExpressionFunction;
}
/** Returns an unmodifiable view of the functions in this */
public Map<String, RankingExpressionFunction> getFunctions() {
- if (functions.size() == 0 && getInherited() == null) return Collections.emptyMap();
- if (functions.size() == 0) return getInherited().getFunctions();
+ if (functions.isEmpty() && getInherited() == null) return Collections.emptyMap();
+ if (functions.isEmpty()) return getInherited().getFunctions();
if (getInherited() == null) return Collections.unmodifiableMap(functions);
// Neither is null
Map<String, RankingExpressionFunction> allFunctions = new LinkedHashMap<>(getInherited().getFunctions());
allFunctions.putAll(functions);
return Collections.unmodifiableMap(allFunctions);
-
}
public int getKeepRankCount() {
@@ -903,9 +902,16 @@ public class RankProfile implements Serializable, Cloneable {
/** True if this should be inlined into calling expressions. Useful for very cheap functions. */
private final boolean inline;
- public RankingExpressionFunction(ExpressionFunction function, boolean inline) {
+ private Optional<TensorType> type = Optional.empty();
+
+ public RankingExpressionFunction(ExpressionFunction function, boolean inline, Optional<TensorType> type) {
this.function = function;
this.inline = inline;
+ this.type = type;
+ }
+
+ public void setType(TensorType type) {
+ this.type = Optional.of(type);
}
public ExpressionFunction function() { return function; }
@@ -914,8 +920,11 @@ public class RankProfile implements Serializable, Cloneable {
return inline && function.arguments().isEmpty(); // only inline no-arg functions;
}
+ /** Returns the type this produces, or empty if not resolved */
+ public Optional<TensorType> type() { return type; }
+
public RankingExpressionFunction withBody(RankingExpression expression) {
- return new RankingExpressionFunction(function.withBody(expression), inline);
+ return new RankingExpressionFunction(function.withBody(expression), inline, type);
}
@Override
diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/Search.java b/config-model/src/main/java/com/yahoo/searchdefinition/Search.java
index f42d5de21e8..a988da9664e 100644
--- a/config-model/src/main/java/com/yahoo/searchdefinition/Search.java
+++ b/config-model/src/main/java/com/yahoo/searchdefinition/Search.java
@@ -59,9 +59,6 @@ public class Search implements Serializable, ImmutableSearch {
// Field sets
private FieldSets fieldSets = new FieldSets();
- // Whether or not this object has been processed.
- private boolean processed;
-
// The unique name of this search definition.
private String name;
@@ -585,17 +582,6 @@ public class Search implements Serializable, ImmutableSearch {
return false;
}
- public void process() {
- if (processed) {
- throw new IllegalStateException("Search '" + getName() + "' already processed.");
- }
- processed = true;
- }
-
- public boolean isProcessed() {
- return processed;
- }
-
/**
* The field set settings for this search
*
diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/SearchBuilder.java b/config-model/src/main/java/com/yahoo/searchdefinition/SearchBuilder.java
index 3c2ebc058ac..151ad02a3fa 100644
--- a/config-model/src/main/java/com/yahoo/searchdefinition/SearchBuilder.java
+++ b/config-model/src/main/java/com/yahoo/searchdefinition/SearchBuilder.java
@@ -188,10 +188,6 @@ public class SearchBuilder {
throw new IllegalArgumentException("Search has no name.");
}
String rawName = rawSearch.getName();
- if (rawSearch.isProcessed()) {
- throw new IllegalArgumentException("A search definition with a search section called '" + rawName +
- "' has already been processed.");
- }
for (Search search : searchList) {
if (rawName.equals(search.getName())) {
throw new IllegalArgumentException("A search definition with a search section called '" + rawName +
@@ -247,8 +243,7 @@ public class SearchBuilder {
DocumentModelBuilder builder = new DocumentModelBuilder(model);
for (Search search : new SearchOrderer().order(searchList)) {
- new FieldOperationApplierForSearch().process(search);
- // These two needed for a couple of old unit tests, ideally these are just read from app
+ new FieldOperationApplierForSearch().process(search); // TODO: Why is this not in the regular list?
process(search, deployLogger, new QueryProfiles(queryProfileRegistry), validate);
built.add(search);
}
diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/derived/DerivedConfiguration.java b/config-model/src/main/java/com/yahoo/searchdefinition/derived/DerivedConfiguration.java
index 9a00ee5bbd0..7c2d9a3b0ad 100644
--- a/config-model/src/main/java/com/yahoo/searchdefinition/derived/DerivedConfiguration.java
+++ b/config-model/src/main/java/com/yahoo/searchdefinition/derived/DerivedConfiguration.java
@@ -74,21 +74,11 @@ public class DerivedConfiguration {
QueryProfileRegistry queryProfiles,
ImportedModels importedModels) {
Validator.ensureNotNull("Search definition", search);
- if ( ! search.isProcessed()) {
- throw new IllegalArgumentException("Search '" + search.getName() + "' not processed.");
- }
this.search = search;
if ( ! search.isDocumentsOnly()) {
streamingFields = new VsmFields(search);
streamingSummary = new VsmSummary(search);
}
- if (abstractSearchList != null) {
- for (Search abstractSearch : abstractSearchList) {
- if (!abstractSearch.isProcessed()) {
- throw new IllegalArgumentException("Search '" + search.getName() + "' not processed.");
- }
- }
- }
if ( ! search.isDocumentsOnly()) {
attributeFields = new AttributeFields(search);
summaries = new Summaries(search, deployLogger);
diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/derived/RawRankProfile.java b/config-model/src/main/java/com/yahoo/searchdefinition/derived/RawRankProfile.java
index c041d5c6a89..c3a2673ef2b 100644
--- a/config-model/src/main/java/com/yahoo/searchdefinition/derived/RawRankProfile.java
+++ b/config-model/src/main/java/com/yahoo/searchdefinition/derived/RawRankProfile.java
@@ -23,6 +23,7 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.stream.Collectors;
/**
* A rank profile derived from a search definition, containing exactly the features available natively in the server
@@ -180,32 +181,37 @@ public class RawRankProfile implements RankProfilesConfig.Producer {
private void derivePropertiesAndSummaryFeaturesFromFunctions(Map<String, RankProfile.RankingExpressionFunction> functions) {
if (functions.isEmpty()) return;
- Map<String, ExpressionFunction> expressionFunctions = new LinkedHashMap<>();
- for (Map.Entry<String, RankProfile.RankingExpressionFunction> function : functions.entrySet()) {
- expressionFunctions.put(function.getKey(), function.getValue().function());
- }
+
+ List<ExpressionFunction> functionExpressions = functions.values().stream().map(f -> f.function()).collect(Collectors.toList());
Map<String, String> functionProperties = new LinkedHashMap<>();
- functionProperties.putAll(deriveFunctionProperties(expressionFunctions));
+ functionProperties.putAll(deriveFunctionProperties(functions, functionExpressions));
+
if (firstPhaseRanking != null) {
- functionProperties.putAll(firstPhaseRanking.getRankProperties(new ArrayList<>(expressionFunctions.values())));
+ functionProperties.putAll(firstPhaseRanking.getRankProperties(functionExpressions));
}
if (secondPhaseRanking != null) {
- functionProperties.putAll(secondPhaseRanking.getRankProperties(new ArrayList<>(expressionFunctions.values())));
+ functionProperties.putAll(secondPhaseRanking.getRankProperties(functionExpressions));
}
for (Map.Entry<String, String> e : functionProperties.entrySet()) {
rankProperties.add(new RankProfile.RankProperty(e.getKey(), e.getValue()));
}
- SerializationContext context = new SerializationContext(expressionFunctions.values(), null, functionProperties);
+ SerializationContext context = new SerializationContext(functionExpressions, null, functionProperties);
replaceFunctionSummaryFeatures(context);
}
- private Map<String, String> deriveFunctionProperties(Map<String, ExpressionFunction> functions) {
- SerializationContext context = new SerializationContext(functions);
- for (Map.Entry<String, ExpressionFunction> e : functions.entrySet()) {
- String expression = e.getValue().getBody().getRoot().toString(new StringBuilder(), context, null, null).toString();
- context.addFunctionSerialization(RankingExpression.propertyName(e.getKey()), expression);
+ private Map<String, String> deriveFunctionProperties(Map<String, RankProfile.RankingExpressionFunction> functions,
+ List<ExpressionFunction> functionExpressions) {
+ SerializationContext context = new SerializationContext(functionExpressions);
+ for (Map.Entry<String, RankProfile.RankingExpressionFunction> e : functions.entrySet()) {
+ String expressionString = e.getValue().function().getBody().getRoot().toString(new StringBuilder(), context, null, null).toString();
+ context.addFunctionSerialization(RankingExpression.propertyName(e.getKey()), expressionString);
+
+ if (e.getValue().type().isPresent())
+ context.addFunctionTypeSerialization(RankingExpression.propertyTypeName(e.getKey()), e.getValue().type().get().toString());
+ else if (e.getValue().function().arguments().isEmpty())
+ throw new IllegalStateException("Type of function '" + e.getKey() + "' is not resolved");
}
return context.serializedFunctions();
}
diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/processing/Processing.java b/config-model/src/main/java/com/yahoo/searchdefinition/processing/Processing.java
index 8c8c32389e2..15d295736c1 100644
--- a/config-model/src/main/java/com/yahoo/searchdefinition/processing/Processing.java
+++ b/config-model/src/main/java/com/yahoo/searchdefinition/processing/Processing.java
@@ -7,10 +7,8 @@ import com.yahoo.searchdefinition.Search;
import com.yahoo.searchdefinition.processing.multifieldresolver.RankProfileTypeSettingsProcessor;
import com.yahoo.vespa.model.container.search.QueryProfiles;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
-import java.util.List;
/**
* Executor of processors. This defines the right order of processor execution.
@@ -75,12 +73,20 @@ public class Processing {
ReferenceFieldsProcessor::new,
FastAccessValidator::new,
ReservedFunctionNames::new,
- RankingExpressionTypeValidator::new,
+ RankingExpressionTypeResolver::new,
// These should be last:
IndexingValidation::new,
IndexingValues::new);
}
+ /** Processors of rank profiles only (those who tolerate and so something useful when the search field is null) */
+ private Collection<ProcessorFactory> rankProfileProcessors() {
+ return Arrays.asList(
+ RankProfileTypeSettingsProcessor::new,
+ ReservedFunctionNames::new,
+ RankingExpressionTypeResolver::new);
+ }
+
/**
* Runs all search processors on the given {@link Search} object. These will modify the search object, <b>possibly
* exchanging it with another</b>, as well as its document types.
@@ -93,12 +99,26 @@ public class Processing {
public void process(Search search, DeployLogger deployLogger, RankProfileRegistry rankProfileRegistry,
QueryProfiles queryProfiles, boolean validate, boolean documentsOnly) {
Collection<ProcessorFactory> factories = processors();
- search.process();
factories.stream()
.map(factory -> factory.create(search, deployLogger, rankProfileRegistry, queryProfiles))
.forEach(processor -> processor.process(validate, documentsOnly));
}
+ /**
+ * Runs rank profiles processors only.
+ *
+ * @param deployLogger The log to log messages and warnings for application deployment to
+ * @param rankProfileRegistry a {@link com.yahoo.searchdefinition.RankProfileRegistry}
+ * @param queryProfiles The query profiles contained in the application this search is part of.
+ */
+ public void processRankProfiles(DeployLogger deployLogger, RankProfileRegistry rankProfileRegistry,
+ QueryProfiles queryProfiles, boolean validate, boolean documentsOnly) {
+ Collection<ProcessorFactory> factories = rankProfileProcessors();
+ factories.stream()
+ .map(factory -> factory.create(null, deployLogger, rankProfileRegistry, queryProfiles))
+ .forEach(processor -> processor.process(validate, documentsOnly));
+ }
+
@FunctionalInterface
public interface ProcessorFactory {
Processor create(Search search, DeployLogger deployLogger, RankProfileRegistry rankProfileRegistry, QueryProfiles queryProfiles);
diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/processing/RankingExpressionTypeValidator.java b/config-model/src/main/java/com/yahoo/searchdefinition/processing/RankingExpressionTypeResolver.java
index 102d1910360..f502af922e9 100644
--- a/config-model/src/main/java/com/yahoo/searchdefinition/processing/RankingExpressionTypeValidator.java
+++ b/config-model/src/main/java/com/yahoo/searchdefinition/processing/RankingExpressionTypeResolver.java
@@ -7,39 +7,44 @@ import com.yahoo.searchdefinition.RankProfile;
import com.yahoo.searchdefinition.RankProfileRegistry;
import com.yahoo.searchdefinition.Search;
import com.yahoo.searchlib.rankingexpression.RankingExpression;
+import com.yahoo.searchlib.rankingexpression.Reference;
import com.yahoo.searchlib.rankingexpression.rule.ExpressionNode;
import com.yahoo.tensor.TensorType;
import com.yahoo.tensor.evaluation.TypeContext;
import com.yahoo.vespa.model.container.search.QueryProfiles;
+import java.util.Map;
+
/**
- * Validates the types of all ranking expressions under a search instance:
+ * Resolves and assigns types to all functions in a ranking expression, and
+ * validates the types of all ranking expressions under a search instance:
* Some operators constrain the types of inputs, and first-and second-phase expressions
- * must return scalar values. In addition, the existence of all referred attribute, query and constant
+ * must return scalar values.
+ *
+ * In addition, the existence of all referred attribute, query and constant
* features is ensured.
*
* @author bratseth
*/
-public class RankingExpressionTypeValidator extends Processor {
+public class RankingExpressionTypeResolver extends Processor {
private final QueryProfileRegistry queryProfiles;
- public RankingExpressionTypeValidator(Search search,
- DeployLogger deployLogger,
- RankProfileRegistry rankProfileRegistry,
- QueryProfiles queryProfiles) {
+ public RankingExpressionTypeResolver(Search search,
+ DeployLogger deployLogger,
+ RankProfileRegistry rankProfileRegistry,
+ QueryProfiles queryProfiles) {
super(search, deployLogger, rankProfileRegistry, queryProfiles);
this.queryProfiles = queryProfiles.getRegistry();
}
@Override
public void process(boolean validate, boolean documentsOnly) {
- if ( ! validate) return;
if (documentsOnly) return;
for (RankProfile profile : rankProfileRegistry.rankProfilesOf(search)) {
try {
- validate(profile);
+ resolveTypesIn(profile, validate);
}
catch (IllegalArgumentException e) {
throw new IllegalArgumentException("In " + search + ", " + profile, e);
@@ -47,20 +52,34 @@ public class RankingExpressionTypeValidator extends Processor {
}
}
- /** Throws an IllegalArgumentException if the given rank profile does not produce valid type */
- private void validate(RankProfile profile) {
- TypeContext context = profile.typeContext(queryProfiles);
- profile.getSummaryFeatures().forEach(f -> ensureValid(f, "summary feature " + f, context));
- ensureValidDouble(profile.getFirstPhaseRanking(), "first-phase expression", context);
- ensureValidDouble(profile.getSecondPhaseRanking(), "second-phase expression", context);
+ /**
+ * Resolves the types of all functions in the given profile
+ *
+ * @throws IllegalArgumentException if validate is true and the given rank profile does not produce valid types
+ */
+ private void resolveTypesIn(RankProfile profile, boolean validate) {
+ TypeContext<Reference> context = profile.typeContext(queryProfiles);
+ for (Map.Entry<String, RankProfile.RankingExpressionFunction> function : profile.getFunctions().entrySet()) {
+ if ( ! function.getValue().function().arguments().isEmpty()) continue;
+ TensorType type = resolveType(function.getValue().function().getBody(),
+ "function '" + function.getKey() + "'",
+ context);
+ function.getValue().setType(type);
+ }
+
+ if (validate) {
+ profile.getSummaryFeatures().forEach(f -> resolveType(f, "summary feature " + f, context));
+ ensureValidDouble(profile.getFirstPhaseRanking(), "first-phase expression", context);
+ ensureValidDouble(profile.getSecondPhaseRanking(), "second-phase expression", context);
+ }
}
- private TensorType ensureValid(RankingExpression expression, String expressionDescription, TypeContext context) {
+ private TensorType resolveType(RankingExpression expression, String expressionDescription, TypeContext context) {
if (expression == null) return null;
- return ensureValid(expression.getRoot(), expressionDescription, context);
+ return resolveType(expression.getRoot(), expressionDescription, context);
}
- private TensorType ensureValid(ExpressionNode expression, String expressionDescription, TypeContext context) {
+ private TensorType resolveType(ExpressionNode expression, String expressionDescription, TypeContext context) {
TensorType type;
try {
type = expression.type(context);
@@ -75,7 +94,7 @@ public class RankingExpressionTypeValidator extends Processor {
private void ensureValidDouble(RankingExpression expression, String expressionDescription, TypeContext context) {
if (expression == null) return;
- TensorType type = ensureValid(expression, expressionDescription, context);
+ TensorType type = resolveType(expression, expressionDescription, context);
if ( ! type.equals(TensorType.empty))
throw new IllegalArgumentException("The " + expressionDescription + " must produce a double " +
"(a tensor with no dimensions), but produces " + type);
diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/processing/multifieldresolver/RankProfileTypeSettingsProcessor.java b/config-model/src/main/java/com/yahoo/searchdefinition/processing/multifieldresolver/RankProfileTypeSettingsProcessor.java
index ec4cbdfe58b..3bde76c1c79 100644
--- a/config-model/src/main/java/com/yahoo/searchdefinition/processing/multifieldresolver/RankProfileTypeSettingsProcessor.java
+++ b/config-model/src/main/java/com/yahoo/searchdefinition/processing/multifieldresolver/RankProfileTypeSettingsProcessor.java
@@ -44,6 +44,7 @@ public class RankProfileTypeSettingsProcessor extends Processor {
}
private void processAttributeFields() {
+ if (search == null) return; // we're processing global profiles
for (SDField field : search.allConcreteFields()) {
Attribute attribute = field.getAttributes().get(field.getName());
if (attribute != null && attribute.tensorType().isPresent()) {
@@ -53,6 +54,7 @@ public class RankProfileTypeSettingsProcessor extends Processor {
}
private void processImportedFields() {
+ if (search == null) return; // we're processing global profiles
Optional<ImportedFields> importedFields = search.importedFields();
if (importedFields.isPresent()) {
importedFields.get().fields().forEach((fieldName, field) -> processImportedField(field));
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/Service.java b/config-model/src/main/java/com/yahoo/vespa/model/Service.java
index 620e44bc11a..29ec26b06d2 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/Service.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/Service.java
@@ -7,7 +7,7 @@ import java.util.HashMap;
import java.util.Optional;
/**
- * Representation of a process which runs a service
+ * Representation of a markProcessed which runs a service
*
* @author gjoranv
*/
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/VespaModel.java b/config-model/src/main/java/com/yahoo/vespa/model/VespaModel.java
index 4b70b1b5ae2..f48fcb999ed 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/VespaModel.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/VespaModel.java
@@ -32,7 +32,9 @@ import com.yahoo.searchdefinition.RankProfileRegistry;
import com.yahoo.searchdefinition.RankingConstants;
import com.yahoo.searchdefinition.derived.AttributeFields;
import com.yahoo.searchdefinition.derived.RankProfileList;
+import com.yahoo.searchdefinition.processing.Processing;
import com.yahoo.searchlib.rankingexpression.ExpressionFunction;
+import com.yahoo.vespa.model.container.search.QueryProfiles;
import com.yahoo.vespa.model.ml.ConvertedModel;
import com.yahoo.searchlib.rankingexpression.RankingExpression;
import com.yahoo.searchlib.rankingexpression.integration.ml.ImportedModel;
@@ -168,7 +170,7 @@ public final class VespaModel extends AbstractConfigProducerRoot implements Seri
createGlobalRankProfiles(deployState.getImportedModels(),
deployState.rankProfileRegistry(),
- deployState.getQueryProfiles().getRegistry());
+ deployState.getQueryProfiles());
this.rankProfileList = new RankProfileList(null, // null search -> global
rankingConstants,
AttributeFields.empty,
@@ -219,23 +221,22 @@ public final class VespaModel extends AbstractConfigProducerRoot implements Seri
/** Adds generic application specific clusters of services */
private void addServiceClusters(ApplicationPackage app, VespaModelBuilder builder) {
- for (ServiceCluster sc : builder.getClusters(app, this))
- serviceClusters.add(sc);
+ serviceClusters.addAll(builder.getClusters(app, this));
}
/**
- * Creates a rank profile not attached to any search definition, for each imported model in the application package
+ * Creates a rank profile not attached to any search definition, for each imported model in the application package,
+ * and adds it to the given rank profile registry.
*/
- private ImmutableList<RankProfile> createGlobalRankProfiles(ImportedModels importedModels,
- RankProfileRegistry rankProfileRegistry,
- QueryProfileRegistry queryProfiles) {
- List<RankProfile> profiles = new ArrayList<>();
+ private void createGlobalRankProfiles(ImportedModels importedModels,
+ RankProfileRegistry rankProfileRegistry,
+ QueryProfiles queryProfiles) {
if ( ! importedModels.all().isEmpty()) { // models/ directory is available
for (ImportedModel model : importedModels.all()) {
RankProfile profile = new RankProfile(model.name(), this, rankProfileRegistry);
rankProfileRegistry.add(profile);
ConvertedModel convertedModel = ConvertedModel.fromSource(new ModelName(model.name()),
- model.name(), profile, queryProfiles, model);
+ model.name(), profile, queryProfiles.getRegistry(), model);
for (Map.Entry<String, RankingExpression> entry : convertedModel.expressions().entrySet()) {
profile.addFunction(new ExpressionFunction(entry.getKey(), entry.getValue()), false);
}
@@ -253,7 +254,9 @@ public final class VespaModel extends AbstractConfigProducerRoot implements Seri
}
}
}
- return ImmutableList.copyOf(profiles);
+ new Processing().processRankProfiles(deployState.getDeployLogger(),
+ rankProfileRegistry,
+ queryProfiles, true, false);
}
/** Returns the global rank profiles as a rank profile list */
diff --git a/config-model/src/test/derived/gemini2/gemini.sd b/config-model/src/test/derived/gemini2/gemini.sd
index 01e20c1b30a..8a570e58fa8 100644
--- a/config-model/src/test/derived/gemini2/gemini.sd
+++ b/config-model/src/test/derived/gemini2/gemini.sd
@@ -2,6 +2,12 @@
search gemini {
document gemini {
+ field right type string {
+ indexing: attribute
+ }
+ field wrong type string {
+ indexing: attribute
+ }
}
rank-profile test {
diff --git a/config-model/src/test/java/com/yahoo/searchdefinition/RankingExpressionLoopDetectionTestCase.java b/config-model/src/test/java/com/yahoo/searchdefinition/RankingExpressionLoopDetectionTestCase.java
index 17bebcba70e..0ff8a5cc7ca 100644
--- a/config-model/src/test/java/com/yahoo/searchdefinition/RankingExpressionLoopDetectionTestCase.java
+++ b/config-model/src/test/java/com/yahoo/searchdefinition/RankingExpressionLoopDetectionTestCase.java
@@ -40,7 +40,7 @@ public class RankingExpressionLoopDetectionTestCase {
fail("Excepted exception");
}
catch (IllegalArgumentException e) {
- assertEquals("In search definition 'test', rank profile 'test': The first-phase expression is invalid: Invocation loop: foo -> foo",
+ assertEquals("In search definition 'test', rank profile 'test': The function 'foo' is invalid: Invocation loop: foo -> foo",
Exceptions.toMessageString(e));
}
}
@@ -75,7 +75,7 @@ public class RankingExpressionLoopDetectionTestCase {
fail("Excepted exception");
}
catch (IllegalArgumentException e) {
- assertEquals("In search definition 'test', rank profile 'test': The first-phase expression is invalid: Invocation loop: foo -> arg(5) -> foo",
+ assertEquals("In search definition 'test', rank profile 'test': The function 'foo' is invalid: Invocation loop: arg(5) -> foo -> arg(5)",
Exceptions.toMessageString(e));
}
}
@@ -110,7 +110,7 @@ public class RankingExpressionLoopDetectionTestCase {
fail("Excepted exception");
}
catch (IllegalArgumentException e) {
- assertEquals("In search definition 'test', rank profile 'test': The first-phase expression is invalid: Invocation loop: foo -> arg(foo) -> foo",
+ assertEquals("In search definition 'test', rank profile 'test': The function 'foo' is invalid: Invocation loop: arg(foo) -> foo -> arg(foo)",
Exceptions.toMessageString(e));
}
}
diff --git a/config-model/src/test/java/com/yahoo/searchdefinition/processing/IntegerIndex2AttributeTestCase.java b/config-model/src/test/java/com/yahoo/searchdefinition/processing/IntegerIndex2AttributeTestCase.java
index 29bba224f46..31631b0dc74 100644
--- a/config-model/src/test/java/com/yahoo/searchdefinition/processing/IntegerIndex2AttributeTestCase.java
+++ b/config-model/src/test/java/com/yahoo/searchdefinition/processing/IntegerIndex2AttributeTestCase.java
@@ -23,7 +23,6 @@ public class IntegerIndex2AttributeTestCase extends SearchDefinitionTestCase {
@Test
public void testIntegerIndex2Attribute() throws IOException, ParseException {
Search search = UnprocessingSearchBuilder.buildUnprocessedFromFile("src/test/examples/integerindex2attribute.sd");
- search.process();
new IntegerIndex2Attribute(search, new BaseDeployLogger(), new RankProfileRegistry(), new QueryProfiles()).process(true, false);
SDField f;
diff --git a/config-model/src/test/java/com/yahoo/searchdefinition/processing/RankingExpressionTypeValidatorTestCase.java b/config-model/src/test/java/com/yahoo/searchdefinition/processing/RankingExpressionTypeResolverTestCase.java
index 0d8cbbf2e6a..1b917b6f3a3 100644
--- a/config-model/src/test/java/com/yahoo/searchdefinition/processing/RankingExpressionTypeValidatorTestCase.java
+++ b/config-model/src/test/java/com/yahoo/searchdefinition/processing/RankingExpressionTypeResolverTestCase.java
@@ -19,7 +19,7 @@ import static org.junit.Assert.fail;
/**
* @author bratseth
*/
-public class RankingExpressionTypeValidatorTestCase {
+public class RankingExpressionTypeResolverTestCase {
@Test
public void tensorFirstPhaseMustProduceDouble() throws Exception {
diff --git a/config-model/src/test/java/com/yahoo/searchdefinition/processing/SummaryFieldsMustHaveValidSourceTestCase.java b/config-model/src/test/java/com/yahoo/searchdefinition/processing/SummaryFieldsMustHaveValidSourceTestCase.java
index d0c1bf8b0ca..39ab7195892 100644
--- a/config-model/src/test/java/com/yahoo/searchdefinition/processing/SummaryFieldsMustHaveValidSourceTestCase.java
+++ b/config-model/src/test/java/com/yahoo/searchdefinition/processing/SummaryFieldsMustHaveValidSourceTestCase.java
@@ -11,7 +11,6 @@ import org.junit.Test;
import java.io.IOException;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
public class SummaryFieldsMustHaveValidSourceTestCase extends SearchDefinitionTestCase {
@@ -19,7 +18,6 @@ public class SummaryFieldsMustHaveValidSourceTestCase extends SearchDefinitionTe
@Test
public void requireThatInvalidSourceIsCaught() throws IOException, ParseException {
Search search = UnprocessingSearchBuilder.buildUnprocessedFromFile("src/test/examples/invalidsummarysource.sd");
- search.process();
try {
new SummaryFieldsMustHaveValidSource(search, new BaseDeployLogger(), new RankProfileRegistry(), new QueryProfiles()).process(true, false);
fail("This should throw and never get here");
@@ -31,7 +29,6 @@ public class SummaryFieldsMustHaveValidSourceTestCase extends SearchDefinitionTe
@Test
public void requireThatInvalidImplicitSourceIsCaught() throws IOException, ParseException {
Search search = UnprocessingSearchBuilder.buildUnprocessedFromFile("src/test/examples/invalidimplicitsummarysource.sd");
- search.process();
try {
new SummaryFieldsMustHaveValidSource(search, new BaseDeployLogger(), new RankProfileRegistry(), new QueryProfiles()).process(true, false);
fail("This should throw and never get here");
@@ -43,7 +40,6 @@ public class SummaryFieldsMustHaveValidSourceTestCase extends SearchDefinitionTe
@Test
public void requireThatInvalidSelfReferingSingleSource() throws IOException, ParseException {
Search search = UnprocessingSearchBuilder.buildUnprocessedFromFile("src/test/examples/invalidselfreferringsummary.sd");
- search.process();
try {
new SummaryFieldsMustHaveValidSource(search, new BaseDeployLogger(), new RankProfileRegistry(), new QueryProfiles()).process(true, false);
fail("This should throw and never get here");
@@ -55,7 +51,6 @@ public class SummaryFieldsMustHaveValidSourceTestCase extends SearchDefinitionTe
@Test
public void requireThatDocumentIdIsAllowedToPass() throws IOException, ParseException {
Search search = UnprocessingSearchBuilder.buildUnprocessedFromFile("src/test/examples/documentidinsummary.sd");
- search.process();
BaseDeployLogger deployLogger = new BaseDeployLogger();
RankProfileRegistry rankProfileRegistry = new RankProfileRegistry();
new SummaryFieldsMustHaveValidSource(search, deployLogger, rankProfileRegistry, new QueryProfiles()).process(true, false);
diff --git a/config-model/src/test/java/com/yahoo/searchdefinition/processing/TensorTransformTestCase.java b/config-model/src/test/java/com/yahoo/searchdefinition/processing/TensorTransformTestCase.java
index 8e721dbe503..6e3a227e2a9 100644
--- a/config-model/src/test/java/com/yahoo/searchdefinition/processing/TensorTransformTestCase.java
+++ b/config-model/src/test/java/com/yahoo/searchdefinition/processing/TensorTransformTestCase.java
@@ -58,8 +58,8 @@ public class TensorTransformTestCase extends SearchDefinitionTestCase {
"max(attribute(tensor_field_1),x)");
assertTransformedExpression("1+reduce(attribute(tensor_field_1),max,x)",
"1 + max(attribute(tensor_field_1),x)");
- assertTransformedExpression("if(attribute(double_field),1+reduce(attribute(tensor_field_1),max,x),0)",
- "if(attribute(double_field),1 + max(attribute(tensor_field_1),x),0)");
+ assertTransformedExpression("if(attribute(double_field),1+reduce(attribute(tensor_field_1),max,x),attribute(tensor_field_1))",
+ "if(attribute(double_field),1 + max(attribute(tensor_field_1),x),attribute(tensor_field_1))");
assertTransformedExpression("reduce(max(attribute(tensor_field_1),attribute(tensor_field_2)),max,x)",
"max(max(attribute(tensor_field_1),attribute(tensor_field_2)),x)");
assertTransformedExpression("reduce(if(attribute(double_field),attribute(tensor_field_2),attribute(tensor_field_2)),max,x)",