summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--document/src/tests/documentselectparsertest.cpp1
-rw-r--r--document/src/vespa/document/bucket/bucketdistribution.h2
-rw-r--r--document/src/vespa/document/bucket/bucketselector.cpp2
-rw-r--r--document/src/vespa/document/select/CMakeLists.txt21
-rw-r--r--document/src/vespa/document/select/bodyfielddetector.cpp13
-rw-r--r--document/src/vespa/document/select/cloningvisitor.cpp2
-rw-r--r--document/src/vespa/document/select/gid_filter.cpp9
-rw-r--r--document/src/vespa/document/select/orderingselector.cpp6
-rw-r--r--document/src/vespa/document/select/simpleparser.h17
-rw-r--r--document/src/vespa/document/select/traversingvisitor.cpp8
-rw-r--r--document/src/vespa/document/select/valuenode.cpp1180
-rw-r--r--document/src/vespa/document/select/valuenode.h343
-rw-r--r--document/src/vespa/document/select/valuenodes.cpp1183
-rw-r--r--document/src/vespa/document/select/valuenodes.h348
-rw-r--r--fastos/src/vespa/fastos/time.h19
-rw-r--r--fastos/src/vespa/fastos/unix_time.cpp8
-rw-r--r--fastos/src/vespa/fastos/unix_time.h3
-rw-r--r--messagebus/src/vespa/messagebus/callstack.cpp1
-rw-r--r--searchcore/src/tests/proton/common/selectpruner_test.cpp1
-rw-r--r--searchcore/src/vespa/searchcore/proton/common/attributefieldvaluenode.cpp11
-rw-r--r--searchcore/src/vespa/searchcore/proton/common/attributefieldvaluenode.h32
-rw-r--r--searchcore/src/vespa/searchcore/proton/common/cachedselect.cpp7
-rw-r--r--searchcore/src/vespa/searchcore/proton/common/selectpruner.cpp1
-rw-r--r--searchcore/src/vespa/searchcore/proton/common/selectpruner.h127
-rw-r--r--storage/src/vespa/storage/persistence/fieldvisitor.cpp4
25 files changed, 1643 insertions, 1706 deletions
diff --git a/document/src/tests/documentselectparsertest.cpp b/document/src/tests/documentselectparsertest.cpp
index 6957634cbde..7fb7703c04a 100644
--- a/document/src/tests/documentselectparsertest.cpp
+++ b/document/src/tests/documentselectparsertest.cpp
@@ -6,6 +6,7 @@
#include <vespa/document/repo/configbuilder.h>
#include <vespa/document/repo/documenttyperepo.h>
#include <vespa/document/update/assignvalueupdate.h>
+#include <vespa/document/update/documentupdate.h>
#include <vespa/document/base/testdocman.h>
#include <vespa/document/select/parser.h>
#include <vespa/document/select/visitor.h>
diff --git a/document/src/vespa/document/bucket/bucketdistribution.h b/document/src/vespa/document/bucket/bucketdistribution.h
index cc7232c81e6..aabc615bdda 100644
--- a/document/src/vespa/document/bucket/bucketdistribution.h
+++ b/document/src/vespa/document/bucket/bucketdistribution.h
@@ -12,8 +12,8 @@
*/
#pragma once
+#include "bucketid.h"
#include <vector>
-#include <vespa/document/bucket/bucketid.h>
#include <vespa/vespalib/util/sync.h>
namespace document {
diff --git a/document/src/vespa/document/bucket/bucketselector.cpp b/document/src/vespa/document/bucket/bucketselector.cpp
index b41b1c284a6..7eb3821e283 100644
--- a/document/src/vespa/document/bucket/bucketselector.cpp
+++ b/document/src/vespa/document/bucket/bucketselector.cpp
@@ -4,7 +4,7 @@
#include "bucketidfactory.h"
#include <vespa/document/base/documentid.h>
#include <vespa/document/select/node.h>
-#include <vespa/document/select/valuenode.h>
+#include <vespa/document/select/valuenodes.h>
#include <vespa/document/select/visitor.h>
#include <vespa/document/select/branch.h>
#include <vespa/document/select/compare.h>
diff --git a/document/src/vespa/document/select/CMakeLists.txt b/document/src/vespa/document/select/CMakeLists.txt
index 8521c525171..5077c9f0494 100644
--- a/document/src/vespa/document/select/CMakeLists.txt
+++ b/document/src/vespa/document/select/CMakeLists.txt
@@ -1,26 +1,27 @@
# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
vespa_add_library(document_select OBJECT
SOURCES
+ bodyfielddetector.cpp
branch.cpp
+ cloningvisitor.cpp
compare.cpp
constant.cpp
+ context.cpp
doctype.cpp
+ gid_filter.cpp
+ invalidconstant.cpp
operator.cpp
- parser.cpp
- result.cpp
- value.cpp
- valuenode.cpp
orderingselector.cpp
orderingspecification.cpp
+ parser.cpp
+ result.cpp
+ resultset.cpp
resultlist.cpp
- invalidconstant.cpp
- bodyfielddetector.cpp
simpleparser.cpp
- resultset.cpp
traversingvisitor.cpp
- cloningvisitor.cpp
- context.cpp
- gid_filter.cpp
+ value.cpp
+ valuenode.cpp
+ valuenodes.cpp
AFTER
document_documentconfig
)
diff --git a/document/src/vespa/document/select/bodyfielddetector.cpp b/document/src/vespa/document/select/bodyfielddetector.cpp
index d0ddd0043ef..2b4c9890e45 100644
--- a/document/src/vespa/document/select/bodyfielddetector.cpp
+++ b/document/src/vespa/document/select/bodyfielddetector.cpp
@@ -1,15 +1,12 @@
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include "bodyfielddetector.h"
+#include "valuenodes.h"
#include <vespa/document/base/exceptions.h>
#include <vespa/document/repo/documenttyperepo.h>
#include <vespa/document/datatype/documenttype.h>
-#include <vespa/vespalib/util/closure.h>
-#include "valuenode.h"
-namespace document {
-
-namespace select {
+namespace document::select {
void
BodyFieldDetector::detectFieldType(const FieldValueNode *expr,
@@ -35,10 +32,8 @@ BodyFieldDetector::detectFieldType(const FieldValueNode *expr,
void
BodyFieldDetector::visitFieldValueNode(const FieldValueNode& expr)
{
- _repo.forEachDocumentType(
- *makeClosure(this, &BodyFieldDetector::detectFieldType, &expr));
+ _repo.forEachDocumentType(*makeClosure(this, &BodyFieldDetector::detectFieldType, &expr));
}
-} // namespace select
-} // namespace document
+}
diff --git a/document/src/vespa/document/select/cloningvisitor.cpp b/document/src/vespa/document/select/cloningvisitor.cpp
index 84188788416..c0a45b758d5 100644
--- a/document/src/vespa/document/select/cloningvisitor.cpp
+++ b/document/src/vespa/document/select/cloningvisitor.cpp
@@ -1,7 +1,7 @@
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include "cloningvisitor.h"
-#include "valuenode.h"
+#include "valuenodes.h"
#include "branch.h"
#include "compare.h"
#include "constant.h"
diff --git a/document/src/vespa/document/select/gid_filter.cpp b/document/src/vespa/document/select/gid_filter.cpp
index cb194452ead..7630053c16f 100644
--- a/document/src/vespa/document/select/gid_filter.cpp
+++ b/document/src/vespa/document/select/gid_filter.cpp
@@ -1,15 +1,13 @@
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include "gid_filter.h"
#include "node.h"
-#include "parser.h"
#include "visitor.h"
-#include "valuenode.h"
+#include "valuenodes.h"
#include "compare.h"
#include "branch.h"
#include <vespa/document/base/idstring.h>
-namespace document {
-namespace select {
+namespace document::select {
namespace {
@@ -156,5 +154,4 @@ GidFilter::GidFilter(const Node& ast_root)
{
}
-} // select
-} // document
+}
diff --git a/document/src/vespa/document/select/orderingselector.cpp b/document/src/vespa/document/select/orderingselector.cpp
index 32a1f0a8adf..4195a6c28a2 100644
--- a/document/src/vespa/document/select/orderingselector.cpp
+++ b/document/src/vespa/document/select/orderingselector.cpp
@@ -2,18 +2,16 @@
#include "orderingselector.h"
#include "node.h"
-#include "valuenode.h"
+#include "valuenodes.h"
#include "visitor.h"
#include "compare.h"
#include "branch.h"
-#include <algorithm>
#include <vespa/document/base/documentid.h>
-#include <vespa/document/base/idstring.h>
namespace document {
-using namespace document::select;
+using namespace select;
namespace {
/**
diff --git a/document/src/vespa/document/select/simpleparser.h b/document/src/vespa/document/select/simpleparser.h
index e6457c3dec7..c52aed0f367 100644
--- a/document/src/vespa/document/select/simpleparser.h
+++ b/document/src/vespa/document/select/simpleparser.h
@@ -2,17 +2,11 @@
#pragma once
-#include <vespa/vespalib/stllike/string.h>
#include "node.h"
-#include "valuenode.h"
+#include "valuenodes.h"
#include "operator.h"
-#include <vespa/document/bucket/bucketidfactory.h>
-namespace document {
-
-namespace select {
-
-namespace simple {
+namespace document::select::simple {
class Parser {
public:
@@ -89,9 +83,4 @@ private:
const BucketIdFactory & _bucketIdFactory;
};
-
-
-} // simple
-} // select
-} // parser
-
+}
diff --git a/document/src/vespa/document/select/traversingvisitor.cpp b/document/src/vespa/document/select/traversingvisitor.cpp
index 7f85d8b7ebb..2f2468e5afc 100644
--- a/document/src/vespa/document/select/traversingvisitor.cpp
+++ b/document/src/vespa/document/select/traversingvisitor.cpp
@@ -1,13 +1,11 @@
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include "traversingvisitor.h"
-#include "valuenode.h"
+#include "valuenodes.h"
#include "branch.h"
#include "compare.h"
-namespace document {
-
-namespace select {
+namespace document::select {
void
TraversingVisitor::visitAndBranch(const And &expr)
@@ -127,5 +125,3 @@ TraversingVisitor::visitInvalidValueNode(const InvalidValueNode &)
}
}
-
-}
diff --git a/document/src/vespa/document/select/valuenode.cpp b/document/src/vespa/document/select/valuenode.cpp
index f463c0e3288..79b795ca76f 100644
--- a/document/src/vespa/document/select/valuenode.cpp
+++ b/document/src/vespa/document/select/valuenode.cpp
@@ -1,41 +1,12 @@
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include "valuenode.h"
-#include "visitor.h"
-#include "parser.h"
-#include <vespa/document/base/exceptions.h>
-#include <vespa/document/fieldvalue/fieldvalues.h>
-#include <vespa/document/fieldvalue/iteratorhandler.h>
-#include <vespa/document/datatype/documenttype.h>
-#include <vespa/vespalib/util/md5.h>
-#include <vespa/document/util/stringutil.h>
-#include <vespa/vespalib/text/lowercase.h>
-#include <regex>
-#include <iomanip>
+#include <ostream>
+namespace document::select {
-#include <vespa/log/log.h>
-LOG_SETUP(".document.select.valuenode");
-
-namespace document {
-
-namespace select {
-
-namespace {
- static const std::regex FIELD_NAME_REGEX("^([_A-Za-z][_A-Za-z0-9]*).*");
-}
-
-namespace {
- bool documentTypeEqualsName(const DocumentType& type, const vespalib::stringref& name)
- {
- if (type.getName() == name) return true;
- for (std::vector<const DocumentType *>::const_iterator it
- = type.getInheritedTypes().begin();
- it != type.getInheritedTypes().end(); ++it)
- {
- if (documentTypeEqualsName(**it, name)) return true;
- }
- return false;
- }
+std::unique_ptr<Value>
+ValueNode::traceValue(const Context &context, std::ostream &out) const {
+ return defaultTrace(getValue(context), out);
}
std::unique_ptr<Value>
@@ -45,1146 +16,5 @@ ValueNode::defaultTrace(std::unique_ptr<Value> val, std::ostream& out) const
return std::move(val);
}
-InvalidValueNode::InvalidValueNode(const vespalib::stringref & name)
- : _name(name)
-{ }
-
-
-void
-InvalidValueNode::visit(Visitor &visitor) const
-{
- visitor.visitInvalidValueNode(*this);
-}
-
-
-void
-InvalidValueNode::print(std::ostream& out, bool verbose,
- const std::string& indent) const
-{
- (void) verbose; (void) indent;
- if (hadParentheses()) out << '(';
- out << _name;
- if (hadParentheses()) out << ')';
-}
-
-NullValueNode::NullValueNode(const vespalib::stringref & name)
- : _name(name)
-{ }
-
-
-void
-NullValueNode::visit(Visitor &visitor) const
-{
- visitor.visitNullValueNode(*this);
-}
-
-
-void
-NullValueNode::print(std::ostream& out, bool verbose,
- const std::string& indent) const
-{
- (void) verbose; (void) indent;
- if (hadParentheses()) out << '(';
- out << _name;
- if (hadParentheses()) out << ')';
-}
-
-StringValueNode::StringValueNode(const vespalib::stringref & val)
- : _value(val)
-{
-}
-
-
-void
-StringValueNode::visit(Visitor &visitor) const
-{
- visitor.visitStringValueNode(*this);
-}
-
-
-void
-StringValueNode::print(std::ostream& out, bool verbose,
- const std::string& indent) const
-{
- (void) verbose; (void) indent;
- if (hadParentheses()) out << '(';
- out << "\"" << StringUtil::escape(_value) << "\"";
- if (hadParentheses()) out << ')';
-}
-
-
-void
-IntegerValueNode::visit(Visitor &visitor) const
-{
- visitor.visitIntegerValueNode(*this);
-}
-
-
-void
-IntegerValueNode::print(std::ostream& out, bool verbose,
- const std::string& indent) const
-{
- (void) verbose; (void) indent;
- if (hadParentheses()) out << '(';
- out << _value;
- if (hadParentheses()) out << ')';
-}
-
-int64_t
-CurrentTimeValueNode::getValue() const
-{
- struct timeval mytime;
- gettimeofday(&mytime, 0);
- return mytime.tv_sec;
-}
-
-
-void
-CurrentTimeValueNode::visit(Visitor &visitor) const
-{
- visitor.visitCurrentTimeValueNode(*this);
-}
-
-
-void
-CurrentTimeValueNode::print(std::ostream& out, bool verbose,
- const std::string& indent) const
-{
- (void) verbose; (void) indent;
- out << "now()";
-}
-
-std::unique_ptr<Value>
-VariableValueNode::getValue(const Context& context) const {
- return context.getValue(_value);
-}
-
-void
-VariableValueNode::visit(Visitor &visitor) const
-{
- visitor.visitVariableValueNode(*this);
-}
-
-
-void
-VariableValueNode::print(std::ostream& out, bool verbose,
- const std::string& indent) const
-{
- (void) verbose; (void) indent;
- if (hadParentheses()) out << '(';
- out << "$" << _value;
- if (hadParentheses()) out << ')';
-}
-
-
-void
-FloatValueNode::visit(Visitor &visitor) const
-{
- visitor.visitFloatValueNode(*this);
-}
-
-
-void
-FloatValueNode::print(std::ostream& out, bool verbose,
- const std::string& indent) const
-{
- (void) verbose; (void) indent;
- if (hadParentheses()) out << '(';
- out << _value;
- if (hadParentheses()) out << ')';
-}
-
-FieldValueNode::FieldValueNode(const vespalib::string& doctype,
- const vespalib::string& fieldExpression)
- : _doctype(doctype),
- _fieldExpression(fieldExpression),
- _fieldName(extractFieldName(fieldExpression))
-{
-}
-
-FieldValueNode::FieldValueNode(const FieldValueNode &) = default;
-FieldValueNode & FieldValueNode::operator = (const FieldValueNode &) = default;
-
-FieldValueNode::~FieldValueNode() {}
-vespalib::string
-FieldValueNode::extractFieldName(const std::string & fieldExpression) {
- std::smatch match;
-
- if (std::regex_match(fieldExpression, match, FIELD_NAME_REGEX) && match[1].matched) {
- return vespalib::string(match[1].first, match[1].second);
- }
-
- throw ParsingFailedException("Fatal: could not extract field name from field expression '" + fieldExpression + "'");
-}
-
-namespace {
-
-class IteratorHandler : public fieldvalue::IteratorHandler {
-public:
- IteratorHandler();
- ~IteratorHandler();
- bool hasSingleValue() const;
- std::unique_ptr<Value> getSingleValue();
- const std::vector<ArrayValue::VariableValue> &getValues();
-
-private:
- std::unique_ptr<Value> _firstValue;
- std::vector<ArrayValue::VariableValue> _values;
-
- void onPrimitive(uint32_t fid, const Content &fv) override;
- std::unique_ptr<Value> getInternalValue(const FieldValue &fval) const;
-};
-
-IteratorHandler::IteratorHandler() { }
-IteratorHandler::~IteratorHandler() { }
-
-bool
-IteratorHandler::hasSingleValue() const {
- return _firstValue.get() && (_values.size() == 0);
-}
-
-std::unique_ptr<Value>
-IteratorHandler::getSingleValue() {
- return std::move(_firstValue);
-}
-
-const std::vector<ArrayValue::VariableValue>&
-IteratorHandler::getValues() {
- if (_firstValue.get()) {
- _values.insert(_values.begin(), ArrayValue::VariableValue(fieldvalue::VariableMap(), Value::SP(_firstValue.release())));
- }
-
- return _values;
-}
-
-void
-IteratorHandler::onPrimitive(uint32_t fid, const Content& fv) {
- (void) fid;
- if (!_firstValue && getVariables().empty()) {
- _firstValue = getInternalValue(fv.getValue());
- } else {
- _values.emplace_back(getVariables(), Value::SP(getInternalValue(fv.getValue()).release()));
- }
-}
-
-std::unique_ptr<Value>
-IteratorHandler::getInternalValue(const FieldValue& fval) const
-{
- switch(fval.getClass().id()) {
- case document::IntFieldValue::classId:
- {
- const IntFieldValue& val(dynamic_cast<const IntFieldValue&>(fval));
- return std::make_unique<IntegerValue>(val.getAsInt(), false);
- }
- case document::ByteFieldValue::classId:
- {
- const ByteFieldValue& val(dynamic_cast<const ByteFieldValue&>(fval));
- return std::make_unique<IntegerValue>(val.getAsByte(), false);
- }
- case LongFieldValue::classId:
- {
- const LongFieldValue& val(dynamic_cast<const LongFieldValue&>(fval));
- return std::make_unique<IntegerValue>(val.getAsLong(), false);
- }
- case FloatFieldValue::classId:
- {
- const FloatFieldValue& val(dynamic_cast<const FloatFieldValue&>(fval));
- return std::make_unique<FloatValue>(val.getAsFloat());
- }
- case DoubleFieldValue::classId:
- {
- const DoubleFieldValue& val(dynamic_cast<const DoubleFieldValue&>(fval));
- return std::make_unique<FloatValue>(val.getAsDouble());
- }
- case StringFieldValue::classId:
- {
- const StringFieldValue& val(dynamic_cast<const StringFieldValue&>(fval));
- return std::make_unique<StringValue>(val.getAsString());
- }
- case ArrayFieldValue::classId:
- {
- const ArrayFieldValue& val(dynamic_cast<const ArrayFieldValue&>(fval));
- if (val.size() == 0) {
- return std::make_unique<NullValue>();
- } else {
- std::vector<ArrayValue::VariableValue> values;
- // TODO: Array comparison.
- return std::make_unique<ArrayValue>(values);
- }
- }
- case StructFieldValue::classId:
- {
- const StructFieldValue& val(dynamic_cast<const StructFieldValue&>(fval));
- if (val.empty()) {
- return std::make_unique<NullValue>();
- } else {
- StructValue::ValueMap values;
- for (StructFieldValue::const_iterator it(val.begin()); it != val.end(); ++it) {
- FieldValue::UP fv(val.getValue(it.field()));
- values[it.field().getName()] = Value::SP(getInternalValue(*fv).release());
- }
- return std::make_unique<StructValue>(values);
- }
- }
- case MapFieldValue::classId:
- {
- const MapFieldValue& val(static_cast<const MapFieldValue&>(fval));
- if (val.isEmpty()) {
- return std::make_unique<NullValue>();
- } else {
- std::vector<ArrayValue::VariableValue> values;
- // TODO: Map comparison
- return std::make_unique<ArrayValue>(values);
- }
- }
- }
- LOG(warning, "Tried to use unsupported datatype %s in field comparison",
- fval.getDataType()->toString().c_str());
- return std::make_unique<InvalidValue>();
-}
-
-}
-
-void
-FieldValueNode::initFieldPath(const DocumentType& type) const {
- if (_fieldPath.size() == 0) {
- FieldPath::UP path(type.buildFieldPath(_fieldExpression));
- if (!path.get()) {
- throw FieldNotFoundException(
- vespalib::make_string("Could not create field path for doc type: '%s' field: '%s'",
- type.toString().c_str(), _fieldExpression.c_str()),
- VESPA_STRLOC);
- }
- _fieldPath = *path;
- }
-}
-
-std::unique_ptr<Value>
-FieldValueNode::getValue(const Context& context) const
-{
- if (context._doc == NULL) {
- return std::unique_ptr<Value>(new InvalidValue());
- }
-
- const Document& doc = *context._doc;
-
- if (!documentTypeEqualsName(doc.getType(), _doctype)) {
- return std::unique_ptr<Value>(new InvalidValue());
- }
- try{
- initFieldPath(doc.getType());
-
- IteratorHandler handler;
- doc.iterateNested(_fieldPath.getFullRange(), handler);
-
- if (handler.hasSingleValue()) {
- return handler.getSingleValue();
- } else {
- const std::vector<ArrayValue::VariableValue>& values = handler.getValues();
-
- if (values.size() == 0) {
- return std::unique_ptr<Value>(new NullValue());
- } else {
- return std::unique_ptr<Value>(new ArrayValue(handler.getValues()));
- }
- }
- } catch (vespalib::IllegalArgumentException& e) {
- LOG(warning, "Caught exception while fetching field from document: %s", e.what());
- return std::unique_ptr<Value>(new InvalidValue());
- } catch (FieldNotFoundException& e) {
- LOG(warning, "Tried to compare to field %s, not found in document type", _fieldExpression.c_str());
- return std::unique_ptr<Value>(new InvalidValue());
- }
-}
-
-void
-FieldValueNode::visit(Visitor &visitor) const
-{
- visitor.visitFieldValueNode(*this);
-}
-
-
-void
-FieldValueNode::print(std::ostream& out, bool verbose,
- const std::string& indent) const
-{
- (void) verbose; (void) indent;
- if (hadParentheses()) out << '(';
- out << _doctype << "." << _fieldExpression;
- if (hadParentheses()) out << ')';
-}
-
-
-std::unique_ptr<Value>
-FieldValueNode::traceValue(const Context &context, std::ostream& out) const
-{
- if (context._doc == NULL) {
- return defaultTrace(getValue(context), out);
- }
- const Document &doc(*context._doc);
- if (!documentTypeEqualsName(doc.getType(), _doctype)) {
- out << "Document is of type " << doc.getType() << " which isn't a "
- << _doctype << " document, thus resolving invalid.\n";
- return std::unique_ptr<Value>(new InvalidValue());
- }
- try{
- initFieldPath(doc.getType());
-
- IteratorHandler handler;
- doc.iterateNested(_fieldPath.getFullRange(), handler);
-
- if (handler.hasSingleValue()) {
- return handler.getSingleValue();
- } else {
- const std::vector<ArrayValue::VariableValue>& values = handler.getValues();
-
- if (values.size() == 0) {
- return std::unique_ptr<Value>(new NullValue());
- } else {
- return std::unique_ptr<Value>(new ArrayValue(handler.getValues()));
- }
- }
- } catch (FieldNotFoundException& e) {
- LOG(warning, "Tried to compare to field %s, not found in document type",
- _fieldExpression.c_str());
- out << "Field not found in document type " << doc.getType()
- << ". Returning invalid.\n";
- return std::unique_ptr<Value>(new InvalidValue());
- }
-}
-
-IdValueNode::IdValueNode(const BucketIdFactory& bucketIdFactory,
- const vespalib::stringref & name, const vespalib::stringref & type,
- int widthBits, int divisionBits)
- : _bucketIdFactory(bucketIdFactory),
- _id(name),
- _typestring(type),
- _type(ALL),
- _widthBits(widthBits),
- _divisionBits(divisionBits)
-{
- if (type.length() > 2) switch (type[0]) {
- case 'b': _type = BUCKET;
- break;
- case 'n': _type = NS;
- break;
- case 'g':
- if (type[1] == 'r') {
- _type = GROUP;
- } else if (type[1] == 'i') {
- _type = GID;
- }
- break;
- case 's': {
- if (type[1] == 'c') { _type = SCHEME; } else { _type = SPEC; }
- break;
- }
- case 't':
- _type = TYPE;
- break;
- case 'u':
- _type = USER;
- break;
- case 'o':
- _type = ORDER;
- break;
- }
-}
-
-
-std::unique_ptr<Value>
-IdValueNode::getValue(const Context& context) const
-{
- if (context._doc != NULL) {
- return getValue(context._doc->getId());
- } else if (context._docId != NULL) {
- return getValue(*context._docId);
- } else {
- return getValue(context._docUpdate->getId());
- }
-}
-
-
-std::unique_ptr<Value>
-IdValueNode::getValue(const DocumentId& id) const
-{
- vespalib::string value;
- switch (_type) {
- case BUCKET:
- return std::unique_ptr<Value>(
- new IntegerValue(
- _bucketIdFactory.getBucketId(id).getId(), true));
- case NS:
- value = id.getScheme().getNamespace(); break;
- case SCHEME:
- value = id.getScheme().getTypeName(id.getScheme().getType());
- break;
- case TYPE:
- if (id.getScheme().hasDocType()) {
- value = id.getScheme().getDocType();
- } else {
- return std::unique_ptr<Value>(new InvalidValue);
- }
- break;
- case SPEC:
- value = id.getScheme().getNamespaceSpecific();
- break;
- case ALL:
- value = id.getScheme().toString();
- break;
- case GROUP:
- if (id.getScheme().hasGroup()) {
- value = id.getScheme().getGroup();
- } else {
- fprintf(stderr, "***** Returning invalid value for %s\n",
- id.toString().c_str());
- return std::unique_ptr<Value>(new InvalidValue);
- }
- break;
- case GID:
- value = id.getGlobalId().toString();
- break;
- case ORDER:
- if (id.getScheme().getType() == IdString::ORDERDOC) {
- const OrderDocIdString& ods(
- static_cast<const OrderDocIdString&>(id.getScheme()));
- if (ods.getWidthBits() == _widthBits
- && ods.getDivisionBits() == _divisionBits)
- {
- return std::unique_ptr<Value>(new IntegerValue(
- static_cast<const OrderDocIdString&>(id.getScheme())
- .getOrdering(), false));
- }
- }
- return std::unique_ptr<Value>(new InvalidValue());
- case USER:
- if (id.getScheme().hasNumber()) {
- return std::unique_ptr<Value>(
- new IntegerValue(id.getScheme().getNumber(), false));
- } else {
- return std::unique_ptr<Value>(new InvalidValue);
- }
- }
-
- return std::unique_ptr<Value>(new StringValue(value));
-}
-
-
-std::unique_ptr<Value>
-IdValueNode::traceValue(const Context& context,
- std::ostream &out) const
-{
- if (context._doc != NULL) {
- return traceValue(context._doc->getId(), out);
- } else if (context._docId != NULL) {
- return traceValue(*context._docId, out);
- } else {
- return traceValue(context._docUpdate->getId(), out);
- }
-}
-
-
-std::unique_ptr<Value>
-IdValueNode::traceValue(const DocumentId& id, std::ostream& out) const
-{
- vespalib::string value;
- switch (_type) {
- case BUCKET:
- {
- document::BucketId bucket(_bucketIdFactory.getBucketId(id));
- std::unique_ptr<Value> result(
- new IntegerValue(bucket.getId(), true));
- out << "Found id.bucket specification. Resolved to "
- << bucket.toString() << ".\n";
- return result;
- }
- case NS:
- value = id.getScheme().getNamespace();
- out << "Resolved id.namespace to value\"" << value << "\".\n";
- break;
- case SCHEME:
- value = id.getScheme().getTypeName(id.getScheme().getType());
- out << "Resolved id.scheme to value\"" << value << "\".\n";
- break;
- case TYPE:
- if (id.getScheme().hasDocType()) {
- value = id.getScheme().getDocType();
- out << "Resolved id.type to value\"" << value << "\".\n";
- } else {
- out << "Could not resolve type of doc " << id << ".\n";
- return std::unique_ptr<Value>(new InvalidValue);
- }
- break;
- case SPEC:
- value = id.getScheme().getNamespaceSpecific();
- out << "Resolved id.specific to value\"" << value << "\".\n";
- break;
- case ALL:
- value = id.getScheme().toString();
- out << "Resolved id to \"" << value << "\".\n";
- break;
- case GROUP:
- if (id.getScheme().hasGroup()) {
- value = id.getScheme().getGroup();
- out << "Resolved group of doc (type " << id.getScheme().getType()
- << ") to \"" << value << "\".\n";
- } else {
- out << "Can't resolve group of doc \"" << id << "\".\n";
- return std::unique_ptr<Value>(new InvalidValue);
- }
- break;
- case GID:
- value = id.getGlobalId().toString();
- out << "Resolved gid to \"" << value << "\".\n";
- break;
- case ORDER:
- if (id.getScheme().getType() == IdString::ORDERDOC) {
- const OrderDocIdString& ods(
- static_cast<const OrderDocIdString&>(id.getScheme()));
- if (ods.getWidthBits() == _widthBits
- && ods.getDivisionBits() == _divisionBits)
- {
- std::unique_ptr<Value> result(new IntegerValue(
- static_cast<const OrderDocIdString&>(id.getScheme())
- .getOrdering(), false));
- out << "Resolved id.order to int " << *result << "\n";
- return result;
- }
- }
- out << "Could not resolve id.order(" << _widthBits << ", "
- << _divisionBits << ") of doc " << id << ".\n";
- return std::unique_ptr<Value>(new InvalidValue());
- case USER:
- if (id.getScheme().hasNumber()) {
- std::unique_ptr<Value> result(
- new IntegerValue(id.getScheme().getNumber(), false));
- out << "Resolved user of doc type " << id.getScheme().getType()
- << " to " << *result << ".\n";
- return result;
- } else {
- out << "Could not resolve user of doc " << id << ".\n";
- return std::unique_ptr<Value>(new InvalidValue);
- }
- }
-
- return std::unique_ptr<Value>(new StringValue(value));
-}
-
-
-void
-IdValueNode::visit(Visitor &visitor) const
-{
- visitor.visitIdValueNode(*this);
-}
-
-
-void
-IdValueNode::print(std::ostream& out, bool verbose,
- const std::string& indent) const
-{
- (void) verbose; (void) indent;
- if (hadParentheses()) out << '(';
- out << _id;
- if (_type != ALL) {
- out << '.' << _typestring;
- }
- if (_type == ORDER) {
- out << "(" << _widthBits << "," << _divisionBits << ")";
- }
- if (hadParentheses()) out << ')';
-}
-
-SearchColumnValueNode::SearchColumnValueNode(
- const BucketIdFactory& bucketIdFactory,
- const vespalib::stringref & name, int numColumns)
- : _bucketIdFactory(bucketIdFactory),
- _id(name),
- _numColumns(numColumns),
- _distribution(_numColumns, 16)
-{
-}
-
-int64_t
-SearchColumnValueNode::getValue(const BucketId& id) const
-{
- return _distribution.getColumn(id);
-}
-
-
-std::unique_ptr<Value>
-SearchColumnValueNode::getValue(const Context& context) const
-{
- if (context._doc != NULL) {
- return getValue(context._doc->getId());
- } else if (context._docId != NULL) {
- return getValue(*context._docId);
- } else {
- return getValue(context._docUpdate->getId());
- }
-}
-
-
-std::unique_ptr<Value>
-SearchColumnValueNode::getValue(const DocumentId& id) const
-{
- return std::unique_ptr<Value>(new IntegerValue(
- getValue(_bucketIdFactory.getBucketId(id)), false));
-}
-
-
-std::unique_ptr<Value>
-SearchColumnValueNode::traceValue(const Context& context,
- std::ostream &out) const
-{
- if (context._doc != NULL) {
- return traceValue(context._doc->getId(), out);
- } else if (context._docId != NULL) {
- return traceValue(*context._docId, out);
- } else {
- return traceValue(context._docUpdate->getId(), out);
- }
-}
-
-
-std::unique_ptr<Value>
-SearchColumnValueNode::traceValue(const DocumentId& id,
- std::ostream& out) const
-{
- std::unique_ptr<Value> result(new IntegerValue(
- getValue(_bucketIdFactory.getBucketId(id)), false));
- out << "Resolved search column of doc \"" << id << "\" to " << *result
- << "\n";
- return result;
-}
-
-
-void
-SearchColumnValueNode::visit(Visitor &visitor) const
-{
- visitor.visitSearchColumnValueNode(*this);
-}
-
-
-void
-SearchColumnValueNode::print(std::ostream& out, bool verbose,
- const std::string& indent) const
-{
- (void) verbose; (void) indent;
- if (hadParentheses()) out << '(';
- out << _id;
- out << '.' << _numColumns;
- if (hadParentheses()) out << ')';
-}
-
-namespace {
- union HashUnion {
- unsigned char _key[16];
- int64_t _hash[2];
- };
- int64_t hash(const void* data, uint32_t len) {
- HashUnion hash;
- fastc_md5sum((const unsigned char*) data, len, hash._key);
- return hash._hash[0];
- }
-}
-
-FunctionValueNode::FunctionValueNode(const vespalib::stringref & name,
- std::unique_ptr<ValueNode> src)
- : _function(),
- _funcname(name),
- _source(std::move(src))
-{
- if (name == "lowercase") {
- _function = LOWERCASE;
- } else if (name == "hash") {
- _function = HASH;
- } else if (name == "abs") {
- _function = ABS;
- } else {
- throw ParsingFailedException("No function '"+name+"' exist.",
- VESPA_STRLOC);
- }
-}
-
-std::unique_ptr<Value>
-FunctionValueNode::getValue(std::unique_ptr<Value> val) const
-{
- switch (val->getType()) {
- case Value::String:
- {
- StringValue& sval(static_cast<StringValue&>(*val));
- if (_function == LOWERCASE) {
- return std::unique_ptr<Value>(new StringValue(
- vespalib::LowerCase::convert(sval.getValue())));
- } else if (_function == HASH) {
- return std::unique_ptr<Value>(new IntegerValue(
- hash(sval.getValue().c_str(), sval.getValue().size()),
- false));
- }
- break;
- }
- case Value::Float:
- {
- FloatValue& fval(static_cast<FloatValue&>(*val));
- if (_function == HASH) {
- FloatValue::ValueType ffval = fval.getValue();
- return std::unique_ptr<Value>(new IntegerValue(
- hash(&ffval, sizeof(ffval)), false));
- } else if (_function == ABS) {
- FloatValue::ValueType ffval = fval.getValue();
- if (ffval < 0) ffval *= -1;
- return std::unique_ptr<Value>(new FloatValue(ffval));
- }
- break;
- }
- case Value::Integer:
- {
- IntegerValue& ival(static_cast<IntegerValue&>(*val));
- if (_function == HASH) {
- IntegerValue::ValueType iival = ival.getValue();
- return std::unique_ptr<Value>(new IntegerValue(
- hash(&iival, sizeof(iival)), false));
- } else if (_function == ABS) {
- IntegerValue::ValueType iival = ival.getValue();
- if (iival < 0) iival *= -1;
- return std::unique_ptr<Value>(new IntegerValue(iival, false));
- }
- break;
- }
- case Value::Bucket:
- {
- throw ParsingFailedException(
- "No functioncalls are allowed on value of type bucket",
- VESPA_STRLOC);
- break;
- }
-
- case Value::Array: break;
- case Value::Struct: break;
- case Value::Invalid: break;
- case Value::Null: break;
- }
- return std::unique_ptr<Value>(new InvalidValue);
-}
-
-std::unique_ptr<Value>
-FunctionValueNode::traceValue(std::unique_ptr<Value> val,
- std::ostream& out) const
-{
- switch (val->getType()) {
- case Value::String:
- {
- StringValue& sval(static_cast<StringValue&>(*val));
- if (_function == LOWERCASE) {
- std::unique_ptr<Value> result(new StringValue(
- vespalib::LowerCase::convert(sval.getValue())));
- out << "Performed lowercase function on '" << sval
- << "' => '" << *result << "'.\n";
- return result;
- } else if (_function == HASH) {
- std::unique_ptr<Value> result(new IntegerValue(
- hash(sval.getValue().c_str(), sval.getValue().size()),
- false));
- out << "Performed hash on string '" << sval << "' -> "
- << *result << "\n";
- return result;
- }
- break;
- }
- case Value::Float:
- {
- FloatValue& fval(static_cast<FloatValue&>(*val));
- if (_function == HASH) {
- FloatValue::ValueType ffval = fval.getValue();
- std::unique_ptr<Value> result(new IntegerValue(
- hash(&ffval, sizeof(ffval)), false));
- out << "Performed hash on float " << ffval << " -> " << *result
- << "\n";
- return result;
- } else if (_function == ABS) {
- FloatValue::ValueType ffval = fval.getValue();
- if (ffval < 0) ffval *= -1;
- out << "Performed abs on float " << fval.getValue() << " -> "
- << ffval << "\n";
- return std::unique_ptr<Value>(new FloatValue(ffval));
- }
- break;
- }
- case Value::Integer:
- {
- IntegerValue& ival(static_cast<IntegerValue&>(*val));
- if (_function == HASH) {
- IntegerValue::ValueType iival = ival.getValue();
- std::unique_ptr<Value> result(new IntegerValue(
- hash(&iival, sizeof(iival)), false));
- out << "Performed hash on float " << iival << " -> " << *result
- << "\n";
- return result;
- } else if (_function == ABS) {
- IntegerValue::ValueType iival = ival.getValue();
- if (iival < 0) iival *= -1;
- out << "Performed abs on integer " << ival.getValue() << " -> "
- << iival << "\n";
- return std::unique_ptr<Value>(new IntegerValue(iival, false));
- }
- break;
- }
- case Value::Bucket: break;
- case Value::Array: break;
- case Value::Struct: break;
- case Value::Invalid: break;
- case Value::Null: break;
- }
- out << "Cannot use function " << _function << " on a value of type "
- << val->getType() << ". Resolving invalid.\n";
- return std::unique_ptr<Value>(new InvalidValue);
-}
-
-
-void
-FunctionValueNode::visit(Visitor &visitor) const
-{
- visitor.visitFunctionValueNode(*this);
-}
-
-
-void
-FunctionValueNode::print(std::ostream& out, bool verbose,
- const std::string& indent) const
-{
- if (hadParentheses()) out << '(';
- _source->print(out, verbose, indent);
- out << '.' << _funcname << "()";
- if (hadParentheses()) out << ')';
-}
-
-ArithmeticValueNode::ArithmeticValueNode(
- std::unique_ptr<ValueNode> left, const vespalib::stringref & op,
- std::unique_ptr<ValueNode> right)
- : _operator(),
- _left(std::move(left)),
- _right(std::move(right))
-{
- if (op.size() == 1) switch (op[0]) {
- case '+': _operator = ADD; return;
- case '-': _operator = SUB; return;
- case '*': _operator = MUL; return;
- case '/': _operator = DIV; return;
- case '%': _operator = MOD; return;
- }
- throw ParsingFailedException(
- "Arithmetic operator '"+op+"' does not exist.", VESPA_STRLOC);
-}
-
-const char*
-ArithmeticValueNode::getOperatorName() const
-{
- switch (_operator) {
- case ADD: return "+";
- case SUB: return "-";
- case MUL: return "*";
- case DIV: return "/";
- case MOD: return "%";
- }
- return "UNKNOWN";
-}
-
-
-
-std::unique_ptr<Value>
-ArithmeticValueNode::getValue(std::unique_ptr<Value> lval,
- std::unique_ptr<Value> rval) const
-{
- switch (_operator) {
- case ADD:
- {
- if (lval->getType() == Value::String &&
- rval->getType() == Value::String)
- {
- StringValue& slval(static_cast<StringValue&>(*lval));
- StringValue& srval(static_cast<StringValue&>(*rval));
- return std::unique_ptr<Value>(new StringValue(
- slval.getValue() + srval.getValue()));
- }
- }
- case SUB:
- case MUL:
- case DIV:
- {
- if (lval->getType() == Value::Integer &&
- rval->getType() == Value::Integer)
- {
- IntegerValue& ilval(static_cast<IntegerValue&>(*lval));
- IntegerValue& irval(static_cast<IntegerValue&>(*rval));
- IntegerValue::ValueType res = 0;
- switch (_operator) {
- case ADD: res = ilval.getValue() + irval.getValue(); break;
- case SUB: res = ilval.getValue() - irval.getValue(); break;
- case MUL: res = ilval.getValue() * irval.getValue(); break;
- case DIV:
- if (irval.getValue() != 0) {
- res = ilval.getValue() / irval.getValue();
- } else {
- throw vespalib::IllegalArgumentException("Division by zero");
- }
- break;
- case MOD: assert(0);
- }
- return std::unique_ptr<Value>(new IntegerValue(res, false));
- }
- NumberValue* nlval(dynamic_cast<NumberValue*>(lval.get()));
- NumberValue* nrval(dynamic_cast<NumberValue*>(rval.get()));
- if (nlval != 0 && nrval != 0) {
- NumberValue::CommonValueType res = 0;
- switch (_operator) {
- case ADD: res = nlval->getCommonValue()
- + nrval->getCommonValue(); break;
- case SUB: res = nlval->getCommonValue()
- - nrval->getCommonValue(); break;
- case MUL: res = nlval->getCommonValue()
- * nrval->getCommonValue(); break;
- case DIV:
- if (nrval->getCommonValue() != 0) {
- res = nlval->getCommonValue()
- / nrval->getCommonValue();
- } else {
- throw vespalib::IllegalArgumentException("Division by zero");
- }
- break;
- case MOD: assert(0);
- }
- return std::unique_ptr<Value>(new FloatValue(res));
- }
- }
- case MOD:
- {
- if (lval->getType() == Value::Integer &&
- rval->getType() == Value::Integer)
- {
- IntegerValue& ilval(static_cast<IntegerValue&>(*lval));
- IntegerValue& irval(static_cast<IntegerValue&>(*rval));
- if (irval.getValue() != 0) {
- return std::unique_ptr<Value>(new IntegerValue(ilval.getValue() % irval.getValue(), false));
- } else {
- throw vespalib::IllegalArgumentException("Division by zero");
- }
- }
- }
- }
- return std::unique_ptr<Value>(new InvalidValue);
-}
-
-std::unique_ptr<Value>
-ArithmeticValueNode::traceValue(std::unique_ptr<Value> lval,
- std::unique_ptr<Value> rval,
- std::ostream& out) const
-{
- switch (_operator) {
- case ADD:
- {
- if (lval->getType() == Value::String &&
- rval->getType() == Value::String)
- {
- StringValue& slval(static_cast<StringValue&>(*lval));
- StringValue& srval(static_cast<StringValue&>(*rval));
- std::unique_ptr<Value> result(new StringValue(
- slval.getValue() + srval.getValue()));
- out << "Appended strings '" << slval << "' + '" << srval
- << "' -> '" << *result << "'.\n";
- return result;
- }
- }
- case SUB:
- case MUL:
- case DIV:
- {
- if (lval->getType() == Value::Integer &&
- rval->getType() == Value::Integer)
- {
- IntegerValue& ilval(static_cast<IntegerValue&>(*lval));
- IntegerValue& irval(static_cast<IntegerValue&>(*rval));
- IntegerValue::ValueType res = 0;
- switch (_operator) {
- case ADD: res = ilval.getValue() + irval.getValue(); break;
- case SUB: res = ilval.getValue() - irval.getValue(); break;
- case MUL: res = ilval.getValue() * irval.getValue(); break;
- case DIV: res = ilval.getValue() / irval.getValue(); break;
- case MOD: assert(0);
- }
- std::unique_ptr<Value> result(new IntegerValue(res, false));
- out << "Performed integer operation " << ilval << " "
- << getOperatorName() << " " << irval << " = " << *result
- << "\n";
- return result;
- }
- NumberValue* nlval(dynamic_cast<NumberValue*>(lval.get()));
- NumberValue* nrval(dynamic_cast<NumberValue*>(lval.get()));
- if (nlval != 0 && nrval != 0) {
- NumberValue::CommonValueType res = 0;
- switch (_operator) {
- case ADD: res = nlval->getCommonValue()
- + nrval->getCommonValue(); break;
- case SUB: res = nlval->getCommonValue()
- - nrval->getCommonValue(); break;
- case MUL: res = nlval->getCommonValue()
- * nrval->getCommonValue(); break;
- case DIV: res = nlval->getCommonValue()
- / nrval->getCommonValue(); break;
- case MOD: assert(0);
- }
- std::unique_ptr<Value> result(new FloatValue(res));
- out << "Performed float operation " << nlval << " "
- << getOperatorName() << " " << nrval << " = " << *result
- << "\n";
- return result;
- }
- }
- case MOD:
- {
- if (lval->getType() == Value::Integer &&
- rval->getType() == Value::Integer)
- {
- IntegerValue& ilval(static_cast<IntegerValue&>(*lval));
- IntegerValue& irval(static_cast<IntegerValue&>(*rval));
- std::unique_ptr<Value> result(new IntegerValue(
- ilval.getValue() % irval.getValue(), false));
- out << "Performed integer operation " << ilval << " "
- << getOperatorName() << " " << irval << " = " << *result
- << "\n";
- return result;
- }
- }
- }
- out << "Failed to do operation " << getOperatorName()
- << " on values of type " << lval->getType() << " and "
- << rval->getType() << ". Resolving invalid.\n";
- return std::unique_ptr<Value>(new InvalidValue);
-}
-
-
-void
-ArithmeticValueNode::visit(Visitor &visitor) const
-{
- visitor.visitArithmeticValueNode(*this);
-}
-
-
-void
-ArithmeticValueNode::print(std::ostream& out, bool verbose,
- const std::string& indent) const
-{
- if (hadParentheses()) out << '(';
- _left->print(out, verbose, indent);
- switch (_operator) {
- case ADD: out << " + "; break;
- case SUB: out << " - "; break;
- case MUL: out << " * "; break;
- case DIV: out << " / "; break;
- case MOD: out << " % "; break;
- }
- _right->print(out, verbose, indent);
- if (hadParentheses()) out << ')';
}
-} // select
-} // document
diff --git a/document/src/vespa/document/select/valuenode.h b/document/src/vespa/document/select/valuenode.h
index 8aae23cb1e4..f36085f769d 100644
--- a/document/src/vespa/document/select/valuenode.h
+++ b/document/src/vespa/document/select/valuenode.h
@@ -13,18 +13,11 @@
#pragma once
#include "value.h"
-#include "context.h"
-#include <vespa/document/fieldvalue/document.h>
-#include <vespa/document/update/documentupdate.h>
-#include <vespa/document/bucket/bucketdistribution.h>
-#include <vespa/document/bucket/bucketidfactory.h>
-namespace document {
+namespace document::select {
-class Document;
-class Field;
-
-namespace select {
+class Context;
+class Visitor;
class ValueNode : public Printable
{
@@ -38,17 +31,10 @@ public:
void clearParentheses() { _parentheses = false; }
bool hadParentheses() const { return _parentheses; }
- virtual std::unique_ptr<Value>
- getValue(const Context& context) const = 0;
-
- virtual std::unique_ptr<Value>
- traceValue(const Context &context, std::ostream &out) const {
- return defaultTrace(getValue(context), out);
- }
-
- virtual void print(std::ostream& out, bool verbose, const std::string& indent) const override = 0;
+ virtual std::unique_ptr<Value> getValue(const Context& context) const = 0;
virtual void visit(Visitor&) const = 0;
virtual ValueNode::UP clone() const = 0;
+ virtual std::unique_ptr<Value> traceValue(const Context &context, std::ostream &out) const;
private:
bool _parentheses; // Set to true if parentheses was used around this part
// Set such that we can recreate original query in print.
@@ -64,324 +50,5 @@ protected:
std::unique_ptr<Value> defaultTrace(std::unique_ptr<Value> val, std::ostream& out) const;
};
-class InvalidValueNode : public ValueNode
-{
- vespalib::string _name;
-public:
- InvalidValueNode(const vespalib::stringref & name);
-
- std::unique_ptr<Value> getValue(const Context&) const override {
- return std::unique_ptr<Value>(new InvalidValue());
- }
-
- void print(std::ostream& out, bool verbose, const std::string& indent) const override;
- void visit(Visitor& visitor) const override;
-
- ValueNode::UP clone() const override {
- return wrapParens(new InvalidValueNode(_name));
- }
-};
-
-class NullValueNode : public ValueNode
-{
- vespalib::string _name;
-public:
- NullValueNode(const vespalib::stringref & name);
-
- std::unique_ptr<Value> getValue(const Context&) const override {
- return std::unique_ptr<Value>(new NullValue());
- }
-
- void print(std::ostream& out, bool verbose, const std::string& indent) const override;
-
- void visit(Visitor& visitor) const override;
-
- ValueNode::UP clone() const override {
- return wrapParens(new NullValueNode(_name));
- }
-};
-
-class StringValueNode : public ValueNode
-{
- vespalib::string _value;
-public:
- StringValueNode(const vespalib::stringref & val);
-
- const vespalib::string& getValue() const { return _value; }
-
- std::unique_ptr<Value> getValue(const Context&) const override {
- return std::unique_ptr<Value>(new StringValue(_value));
- }
-
- void print(std::ostream& out, bool verbose, const std::string& indent) const override;
- void visit(Visitor& visitor) const override;
-
- ValueNode::UP clone() const override {
- return wrapParens(new StringValueNode(_value));
- }
-};
-
-class IntegerValueNode : public ValueNode
-{
- int64_t _value;
- bool _isBucketValue;
-public:
- IntegerValueNode(int64_t val, bool isBucketValue)
- : _value(val), _isBucketValue(isBucketValue) {}
-
- int64_t getValue() const { return _value; }
-
- virtual std::unique_ptr<Value> getValue(const Context&) const override {
- return std::unique_ptr<Value>(new IntegerValue(_value, _isBucketValue));
- }
-
- void print(std::ostream& out, bool verbose, const std::string& indent) const override;
- void visit(Visitor& visitor) const override;
-
- ValueNode::UP clone() const override {
- return wrapParens(new IntegerValueNode(_value, _isBucketValue));
- }
-};
-
-class CurrentTimeValueNode : public ValueNode
-{
-public:
- int64_t getValue() const;
-
- std::unique_ptr<Value> getValue(const Context&) const override {
- return std::unique_ptr<Value>(new IntegerValue(getValue(), false));
- }
-
- void print(std::ostream& out, bool verbose, const std::string& indent) const override;
- void visit(Visitor& visitor) const override;
-
- ValueNode::UP clone() const override {
- return wrapParens(new CurrentTimeValueNode);
- }
-};
-
-class VariableValueNode : public ValueNode
-{
- vespalib::string _value;
-public:
- VariableValueNode(const vespalib::string & variableName) : _value(variableName) {}
-
- const vespalib::string& getVariableName() const { return _value; }
-
- std::unique_ptr<Value> getValue(const Context& context) const override;
- void print(std::ostream& out, bool verbose, const std::string& indent) const override;
- void visit(Visitor& visitor) const override;
-
- ValueNode::UP clone() const override {
- return wrapParens(new VariableValueNode(_value));
- }
-};
-
-class FloatValueNode : public ValueNode
-{
- double _value;
-public:
- FloatValueNode(double val) : _value(val) {}
-
- double getValue() const { return _value; }
-
- std::unique_ptr<Value> getValue(const Context&) const override {
- return std::unique_ptr<Value>(new FloatValue(_value));
- }
-
- void print(std::ostream& out, bool verbose, const std::string& indent) const override;
- void visit(Visitor& visitor) const override;
-
- ValueNode::UP clone() const override {
- return wrapParens(new FloatValueNode(_value));
- }
-};
-
-class FieldValueNode : public ValueNode
-{
- vespalib::string _doctype;
- vespalib::string _fieldExpression;
- vespalib::string _fieldName;
- mutable FieldPath _fieldPath;
-
-public:
- FieldValueNode(const vespalib::string& doctype, const vespalib::string& fieldExpression);
- FieldValueNode(const FieldValueNode &);
- FieldValueNode & operator = (const FieldValueNode &);
- FieldValueNode(FieldValueNode &&) = default;
- FieldValueNode & operator = (FieldValueNode &&) = default;
- ~FieldValueNode();
-
- const vespalib::string& getDocType() const { return _doctype; }
- const vespalib::string& getRealFieldName() const { return _fieldName; }
- const vespalib::string& getFieldName() const { return _fieldExpression; }
-
- std::unique_ptr<Value> getValue(const Context& context) const override;
- std::unique_ptr<Value> traceValue(const Context &context, std::ostream& out) const override;
- void print(std::ostream& out, bool verbose, const std::string& indent) const override;
- void visit(Visitor& visitor) const override;
-
- ValueNode::UP clone() const override {
- return wrapParens(new FieldValueNode(_doctype, _fieldExpression));
- }
-
- static vespalib::string extractFieldName(const std::string & fieldExpression);
-
-private:
-
- void initFieldPath(const DocumentType&) const;
-};
-
-class IdValueNode : public ValueNode
-{
-public:
- enum Type { SCHEME, NS, TYPE, USER, GROUP, GID, SPEC, BUCKET, ORDER, ALL };
-
- IdValueNode(const BucketIdFactory& bucketIdFactory,
- const vespalib::stringref & name, const vespalib::stringref & type,
- int widthBits = -1, int divisionBits = -1);
-
- Type getType() const { return _type; }
-
- std::unique_ptr<Value> getValue(const Context& context) const override;
-
- std::unique_ptr<Value> getValue(const DocumentId& id) const;
-
- std::unique_ptr<Value> traceValue(const Context& context, std::ostream &out) const override;
-
- std::unique_ptr<Value> traceValue(const DocumentId& val, std::ostream& out) const;
-
- void print(std::ostream& out, bool verbose, const std::string& indent) const override;
-
- void visit(Visitor& visitor) const override;
-
- ValueNode::UP clone() const override {
- return wrapParens(new IdValueNode(_bucketIdFactory, _id, _typestring, _widthBits, _divisionBits));
- }
-
- int getWidthBits() const { return _widthBits; }
- int getDivisionBits() const { return _divisionBits; }
-
-private:
- const BucketIdFactory& _bucketIdFactory;
- vespalib::string _id;
- vespalib::string _typestring;
- Type _type;
- int _widthBits;
- int _divisionBits;
-};
-
-class SearchColumnValueNode : public ValueNode
-{
-public:
- SearchColumnValueNode(const BucketIdFactory& bucketIdFactory,
- const vespalib::stringref & name,
- int numColumns);
-
- int getColumns() { return _numColumns; }
-
- std::unique_ptr<Value> getValue(const Context& context) const override;
- std::unique_ptr<Value> getValue(const DocumentId& id) const;
- std::unique_ptr<Value> traceValue(const Context& context, std::ostream &out) const override;
- std::unique_ptr<Value> traceValue(const DocumentId& val, std::ostream& out) const;
-
- int64_t getValue(const BucketId& bucketId) const;
- void print(std::ostream& out, bool verbose, const std::string& indent) const override;
- void visit(Visitor& visitor) const override;
-
- ValueNode::UP clone() const override {
- return wrapParens(new SearchColumnValueNode(_bucketIdFactory, _id, _numColumns));
}
-private:
- const BucketIdFactory& _bucketIdFactory;
- vespalib::string _id;
- int _numColumns;
- BucketDistribution _distribution;
-};
-
-class FunctionValueNode : public ValueNode
-{
-public:
- enum Function { LOWERCASE, HASH, ABS };
-
- FunctionValueNode(const vespalib::stringref & name, std::unique_ptr<ValueNode> src);
-
- Function getFunction() const { return _function; }
- const vespalib::string &getFunctionName(void) const { return _funcname; }
-
- std::unique_ptr<Value> getValue(const Context& context) const override {
- return getValue(_source->getValue(context));
- }
-
- std::unique_ptr<Value> traceValue(const Context &context, std::ostream& out) const override {
- return traceValue(_source->getValue(context), out);
- }
-
- void print(std::ostream& out, bool verbose, const std::string& indent) const override;
- void visit(Visitor& visitor) const override;
-
- ValueNode::UP clone() const override {
- return wrapParens(new FunctionValueNode(_funcname, _source->clone()));
- }
-
- const ValueNode& getChild() const { return *_source; }
-
-private:
- Function _function;
- vespalib::string _funcname;
- std::unique_ptr<ValueNode> _source;
-
- virtual std::unique_ptr<Value> getValue(std::unique_ptr<Value> val) const;
- virtual std::unique_ptr<Value> traceValue(std::unique_ptr<Value> val,
- std::ostream& out) const;
-};
-
-class ArithmeticValueNode : public ValueNode
-{
-public:
- enum Operator { ADD, SUB, MUL, DIV, MOD };
-
- ArithmeticValueNode(std::unique_ptr<ValueNode> left,
- const vespalib::stringref & op,
- std::unique_ptr<ValueNode> right);
-
- Operator getOperator() const { return _operator; }
- const char* getOperatorName() const;
-
- std::unique_ptr<Value>
- getValue(const Context& context) const override {
- return getValue(_left->getValue(context), _right->getValue(context));
- }
-
- std::unique_ptr<Value>
- traceValue(const Context &context, std::ostream& out) const override {
- return traceValue(_left->getValue(context), _right->getValue(context), out);
- }
-
- void print(std::ostream& out, bool verbose, const std::string& indent) const override;
- void visit(Visitor& visitor) const override;
-
- ValueNode::UP clone() const override {
- return wrapParens(new ArithmeticValueNode(_left->clone(),
- getOperatorName(),
- _right->clone()));
- }
-
- const ValueNode& getLeft() const { return *_left; }
- const ValueNode& getRight() const { return *_right; }
-
-private:
- Operator _operator;
- std::unique_ptr<ValueNode> _left;
- std::unique_ptr<ValueNode> _right;
-
- virtual std::unique_ptr<Value> getValue(std::unique_ptr<Value> lval,
- std::unique_ptr<Value> rval) const;
- virtual std::unique_ptr<Value> traceValue(std::unique_ptr<Value> lval,
- std::unique_ptr<Value> rval,
- std::ostream&) const;
-};
-
-} // select
-} // document
diff --git a/document/src/vespa/document/select/valuenodes.cpp b/document/src/vespa/document/select/valuenodes.cpp
new file mode 100644
index 00000000000..3a4edbef093
--- /dev/null
+++ b/document/src/vespa/document/select/valuenodes.cpp
@@ -0,0 +1,1183 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include "valuenodes.h"
+#include "visitor.h"
+#include "parser.h"
+#include <vespa/document/bucket/bucketdistribution.h>
+#include <vespa/document/base/exceptions.h>
+#include <vespa/document/update/documentupdate.h>
+#include <vespa/document/fieldvalue/fieldvalues.h>
+#include <vespa/document/fieldvalue/iteratorhandler.h>
+#include <vespa/document/datatype/documenttype.h>
+#include <vespa/vespalib/util/md5.h>
+#include <vespa/document/util/stringutil.h>
+#include <vespa/vespalib/text/lowercase.h>
+#include <regex>
+#include <iomanip>
+
+
+#include <vespa/log/log.h>
+LOG_SETUP(".document.select.valuenode");
+
+namespace document::select {
+
+namespace {
+ static const std::regex FIELD_NAME_REGEX("^([_A-Za-z][_A-Za-z0-9]*).*");
+}
+
+namespace {
+ bool documentTypeEqualsName(const DocumentType& type, const vespalib::stringref& name)
+ {
+ if (type.getName() == name) return true;
+ for (std::vector<const DocumentType *>::const_iterator it
+ = type.getInheritedTypes().begin();
+ it != type.getInheritedTypes().end(); ++it)
+ {
+ if (documentTypeEqualsName(**it, name)) return true;
+ }
+ return false;
+ }
+}
+
+InvalidValueNode::InvalidValueNode(const vespalib::stringref & name)
+ : _name(name)
+{ }
+
+
+void
+InvalidValueNode::visit(Visitor &visitor) const
+{
+ visitor.visitInvalidValueNode(*this);
+}
+
+
+void
+InvalidValueNode::print(std::ostream& out, bool verbose,
+ const std::string& indent) const
+{
+ (void) verbose; (void) indent;
+ if (hadParentheses()) out << '(';
+ out << _name;
+ if (hadParentheses()) out << ')';
+}
+
+NullValueNode::NullValueNode(const vespalib::stringref & name)
+ : _name(name)
+{ }
+
+
+void
+NullValueNode::visit(Visitor &visitor) const
+{
+ visitor.visitNullValueNode(*this);
+}
+
+
+void
+NullValueNode::print(std::ostream& out, bool verbose,
+ const std::string& indent) const
+{
+ (void) verbose; (void) indent;
+ if (hadParentheses()) out << '(';
+ out << _name;
+ if (hadParentheses()) out << ')';
+}
+
+StringValueNode::StringValueNode(const vespalib::stringref & val)
+ : _value(val)
+{
+}
+
+
+void
+StringValueNode::visit(Visitor &visitor) const
+{
+ visitor.visitStringValueNode(*this);
+}
+
+
+void
+StringValueNode::print(std::ostream& out, bool verbose,
+ const std::string& indent) const
+{
+ (void) verbose; (void) indent;
+ if (hadParentheses()) out << '(';
+ out << "\"" << StringUtil::escape(_value) << "\"";
+ if (hadParentheses()) out << ')';
+}
+
+
+void
+IntegerValueNode::visit(Visitor &visitor) const
+{
+ visitor.visitIntegerValueNode(*this);
+}
+
+
+void
+IntegerValueNode::print(std::ostream& out, bool verbose,
+ const std::string& indent) const
+{
+ (void) verbose; (void) indent;
+ if (hadParentheses()) out << '(';
+ out << _value;
+ if (hadParentheses()) out << ')';
+}
+
+int64_t
+CurrentTimeValueNode::getValue() const
+{
+ struct timeval mytime;
+ gettimeofday(&mytime, 0);
+ return mytime.tv_sec;
+}
+
+
+void
+CurrentTimeValueNode::visit(Visitor &visitor) const
+{
+ visitor.visitCurrentTimeValueNode(*this);
+}
+
+
+void
+CurrentTimeValueNode::print(std::ostream& out, bool verbose,
+ const std::string& indent) const
+{
+ (void) verbose; (void) indent;
+ out << "now()";
+}
+
+std::unique_ptr<Value>
+VariableValueNode::getValue(const Context& context) const {
+ return context.getValue(_value);
+}
+
+void
+VariableValueNode::visit(Visitor &visitor) const
+{
+ visitor.visitVariableValueNode(*this);
+}
+
+
+void
+VariableValueNode::print(std::ostream& out, bool verbose,
+ const std::string& indent) const
+{
+ (void) verbose; (void) indent;
+ if (hadParentheses()) out << '(';
+ out << "$" << _value;
+ if (hadParentheses()) out << ')';
+}
+
+
+void
+FloatValueNode::visit(Visitor &visitor) const
+{
+ visitor.visitFloatValueNode(*this);
+}
+
+
+void
+FloatValueNode::print(std::ostream& out, bool verbose,
+ const std::string& indent) const
+{
+ (void) verbose; (void) indent;
+ if (hadParentheses()) out << '(';
+ out << _value;
+ if (hadParentheses()) out << ')';
+}
+
+FieldValueNode::FieldValueNode(const vespalib::string& doctype,
+ const vespalib::string& fieldExpression)
+ : _doctype(doctype),
+ _fieldExpression(fieldExpression),
+ _fieldName(extractFieldName(fieldExpression))
+{
+}
+
+FieldValueNode::FieldValueNode(const FieldValueNode &) = default;
+FieldValueNode & FieldValueNode::operator = (const FieldValueNode &) = default;
+
+FieldValueNode::~FieldValueNode() {}
+vespalib::string
+FieldValueNode::extractFieldName(const std::string & fieldExpression) {
+ std::smatch match;
+
+ if (std::regex_match(fieldExpression, match, FIELD_NAME_REGEX) && match[1].matched) {
+ return vespalib::string(match[1].first, match[1].second);
+ }
+
+ throw ParsingFailedException("Fatal: could not extract field name from field expression '" + fieldExpression + "'");
+}
+
+namespace {
+
+class IteratorHandler : public fieldvalue::IteratorHandler {
+public:
+ IteratorHandler();
+ ~IteratorHandler();
+ bool hasSingleValue() const;
+ std::unique_ptr<Value> getSingleValue();
+ const std::vector<ArrayValue::VariableValue> &getValues();
+
+private:
+ std::unique_ptr<Value> _firstValue;
+ std::vector<ArrayValue::VariableValue> _values;
+
+ void onPrimitive(uint32_t fid, const Content &fv) override;
+ std::unique_ptr<Value> getInternalValue(const FieldValue &fval) const;
+};
+
+IteratorHandler::IteratorHandler() { }
+IteratorHandler::~IteratorHandler() { }
+
+bool
+IteratorHandler::hasSingleValue() const {
+ return _firstValue.get() && (_values.size() == 0);
+}
+
+std::unique_ptr<Value>
+IteratorHandler::getSingleValue() {
+ return std::move(_firstValue);
+}
+
+const std::vector<ArrayValue::VariableValue>&
+IteratorHandler::getValues() {
+ if (_firstValue.get()) {
+ _values.insert(_values.begin(), ArrayValue::VariableValue(fieldvalue::VariableMap(), Value::SP(_firstValue.release())));
+ }
+
+ return _values;
+}
+
+void
+IteratorHandler::onPrimitive(uint32_t fid, const Content& fv) {
+ (void) fid;
+ if (!_firstValue && getVariables().empty()) {
+ _firstValue = getInternalValue(fv.getValue());
+ } else {
+ _values.emplace_back(getVariables(), Value::SP(getInternalValue(fv.getValue()).release()));
+ }
+}
+
+std::unique_ptr<Value>
+IteratorHandler::getInternalValue(const FieldValue& fval) const
+{
+ switch(fval.getClass().id()) {
+ case document::IntFieldValue::classId:
+ {
+ const IntFieldValue& val(dynamic_cast<const IntFieldValue&>(fval));
+ return std::make_unique<IntegerValue>(val.getAsInt(), false);
+ }
+ case document::ByteFieldValue::classId:
+ {
+ const ByteFieldValue& val(dynamic_cast<const ByteFieldValue&>(fval));
+ return std::make_unique<IntegerValue>(val.getAsByte(), false);
+ }
+ case LongFieldValue::classId:
+ {
+ const LongFieldValue& val(dynamic_cast<const LongFieldValue&>(fval));
+ return std::make_unique<IntegerValue>(val.getAsLong(), false);
+ }
+ case FloatFieldValue::classId:
+ {
+ const FloatFieldValue& val(dynamic_cast<const FloatFieldValue&>(fval));
+ return std::make_unique<FloatValue>(val.getAsFloat());
+ }
+ case DoubleFieldValue::classId:
+ {
+ const DoubleFieldValue& val(dynamic_cast<const DoubleFieldValue&>(fval));
+ return std::make_unique<FloatValue>(val.getAsDouble());
+ }
+ case StringFieldValue::classId:
+ {
+ const StringFieldValue& val(dynamic_cast<const StringFieldValue&>(fval));
+ return std::make_unique<StringValue>(val.getAsString());
+ }
+ case ArrayFieldValue::classId:
+ {
+ const ArrayFieldValue& val(dynamic_cast<const ArrayFieldValue&>(fval));
+ if (val.size() == 0) {
+ return std::make_unique<NullValue>();
+ } else {
+ std::vector<ArrayValue::VariableValue> values;
+ // TODO: Array comparison.
+ return std::make_unique<ArrayValue>(values);
+ }
+ }
+ case StructFieldValue::classId:
+ {
+ const StructFieldValue& val(dynamic_cast<const StructFieldValue&>(fval));
+ if (val.empty()) {
+ return std::make_unique<NullValue>();
+ } else {
+ StructValue::ValueMap values;
+ for (StructFieldValue::const_iterator it(val.begin()); it != val.end(); ++it) {
+ FieldValue::UP fv(val.getValue(it.field()));
+ values[it.field().getName()] = Value::SP(getInternalValue(*fv).release());
+ }
+ return std::make_unique<StructValue>(values);
+ }
+ }
+ case MapFieldValue::classId:
+ {
+ const MapFieldValue& val(static_cast<const MapFieldValue&>(fval));
+ if (val.isEmpty()) {
+ return std::make_unique<NullValue>();
+ } else {
+ std::vector<ArrayValue::VariableValue> values;
+ // TODO: Map comparison
+ return std::make_unique<ArrayValue>(values);
+ }
+ }
+ }
+ LOG(warning, "Tried to use unsupported datatype %s in field comparison",
+ fval.getDataType()->toString().c_str());
+ return std::make_unique<InvalidValue>();
+}
+
+}
+
+void
+FieldValueNode::initFieldPath(const DocumentType& type) const {
+ if (_fieldPath.size() == 0) {
+ FieldPath::UP path(type.buildFieldPath(_fieldExpression));
+ if (!path.get()) {
+ throw FieldNotFoundException(
+ vespalib::make_string("Could not create field path for doc type: '%s' field: '%s'",
+ type.toString().c_str(), _fieldExpression.c_str()),
+ VESPA_STRLOC);
+ }
+ _fieldPath = *path;
+ }
+}
+
+std::unique_ptr<Value>
+FieldValueNode::getValue(const Context& context) const
+{
+ if (context._doc == NULL) {
+ return std::unique_ptr<Value>(new InvalidValue());
+ }
+
+ const Document& doc = *context._doc;
+
+ if (!documentTypeEqualsName(doc.getType(), _doctype)) {
+ return std::unique_ptr<Value>(new InvalidValue());
+ }
+ try{
+ initFieldPath(doc.getType());
+
+ IteratorHandler handler;
+ doc.iterateNested(_fieldPath.getFullRange(), handler);
+
+ if (handler.hasSingleValue()) {
+ return handler.getSingleValue();
+ } else {
+ const std::vector<ArrayValue::VariableValue>& values = handler.getValues();
+
+ if (values.size() == 0) {
+ return std::unique_ptr<Value>(new NullValue());
+ } else {
+ return std::unique_ptr<Value>(new ArrayValue(handler.getValues()));
+ }
+ }
+ } catch (vespalib::IllegalArgumentException& e) {
+ LOG(warning, "Caught exception while fetching field from document: %s", e.what());
+ return std::unique_ptr<Value>(new InvalidValue());
+ } catch (FieldNotFoundException& e) {
+ LOG(warning, "Tried to compare to field %s, not found in document type", _fieldExpression.c_str());
+ return std::unique_ptr<Value>(new InvalidValue());
+ }
+}
+
+void
+FieldValueNode::visit(Visitor &visitor) const
+{
+ visitor.visitFieldValueNode(*this);
+}
+
+
+void
+FieldValueNode::print(std::ostream& out, bool verbose,
+ const std::string& indent) const
+{
+ (void) verbose; (void) indent;
+ if (hadParentheses()) out << '(';
+ out << _doctype << "." << _fieldExpression;
+ if (hadParentheses()) out << ')';
+}
+
+
+std::unique_ptr<Value>
+FieldValueNode::traceValue(const Context &context, std::ostream& out) const
+{
+ if (context._doc == NULL) {
+ return defaultTrace(getValue(context), out);
+ }
+ const Document &doc(*context._doc);
+ if (!documentTypeEqualsName(doc.getType(), _doctype)) {
+ out << "Document is of type " << doc.getType() << " which isn't a "
+ << _doctype << " document, thus resolving invalid.\n";
+ return std::unique_ptr<Value>(new InvalidValue());
+ }
+ try{
+ initFieldPath(doc.getType());
+
+ IteratorHandler handler;
+ doc.iterateNested(_fieldPath.getFullRange(), handler);
+
+ if (handler.hasSingleValue()) {
+ return handler.getSingleValue();
+ } else {
+ const std::vector<ArrayValue::VariableValue>& values = handler.getValues();
+
+ if (values.size() == 0) {
+ return std::unique_ptr<Value>(new NullValue());
+ } else {
+ return std::unique_ptr<Value>(new ArrayValue(handler.getValues()));
+ }
+ }
+ } catch (FieldNotFoundException& e) {
+ LOG(warning, "Tried to compare to field %s, not found in document type",
+ _fieldExpression.c_str());
+ out << "Field not found in document type " << doc.getType()
+ << ". Returning invalid.\n";
+ return std::unique_ptr<Value>(new InvalidValue());
+ }
+}
+
+IdValueNode::IdValueNode(const BucketIdFactory& bucketIdFactory,
+ const vespalib::stringref & name, const vespalib::stringref & type,
+ int widthBits, int divisionBits)
+ : _bucketIdFactory(bucketIdFactory),
+ _id(name),
+ _typestring(type),
+ _type(ALL),
+ _widthBits(widthBits),
+ _divisionBits(divisionBits)
+{
+ if (type.length() > 2) switch (type[0]) {
+ case 'b': _type = BUCKET;
+ break;
+ case 'n': _type = NS;
+ break;
+ case 'g':
+ if (type[1] == 'r') {
+ _type = GROUP;
+ } else if (type[1] == 'i') {
+ _type = GID;
+ }
+ break;
+ case 's': {
+ if (type[1] == 'c') { _type = SCHEME; } else { _type = SPEC; }
+ break;
+ }
+ case 't':
+ _type = TYPE;
+ break;
+ case 'u':
+ _type = USER;
+ break;
+ case 'o':
+ _type = ORDER;
+ break;
+ }
+}
+
+
+std::unique_ptr<Value>
+IdValueNode::getValue(const Context& context) const
+{
+ if (context._doc != NULL) {
+ return getValue(context._doc->getId());
+ } else if (context._docId != NULL) {
+ return getValue(*context._docId);
+ } else {
+ return getValue(context._docUpdate->getId());
+ }
+}
+
+
+std::unique_ptr<Value>
+IdValueNode::getValue(const DocumentId& id) const
+{
+ vespalib::string value;
+ switch (_type) {
+ case BUCKET:
+ return std::unique_ptr<Value>(
+ new IntegerValue(
+ _bucketIdFactory.getBucketId(id).getId(), true));
+ case NS:
+ value = id.getScheme().getNamespace(); break;
+ case SCHEME:
+ value = id.getScheme().getTypeName(id.getScheme().getType());
+ break;
+ case TYPE:
+ if (id.getScheme().hasDocType()) {
+ value = id.getScheme().getDocType();
+ } else {
+ return std::unique_ptr<Value>(new InvalidValue);
+ }
+ break;
+ case SPEC:
+ value = id.getScheme().getNamespaceSpecific();
+ break;
+ case ALL:
+ value = id.getScheme().toString();
+ break;
+ case GROUP:
+ if (id.getScheme().hasGroup()) {
+ value = id.getScheme().getGroup();
+ } else {
+ fprintf(stderr, "***** Returning invalid value for %s\n",
+ id.toString().c_str());
+ return std::unique_ptr<Value>(new InvalidValue);
+ }
+ break;
+ case GID:
+ value = id.getGlobalId().toString();
+ break;
+ case ORDER:
+ if (id.getScheme().getType() == IdString::ORDERDOC) {
+ const OrderDocIdString& ods(
+ static_cast<const OrderDocIdString&>(id.getScheme()));
+ if (ods.getWidthBits() == _widthBits
+ && ods.getDivisionBits() == _divisionBits)
+ {
+ return std::unique_ptr<Value>(new IntegerValue(
+ static_cast<const OrderDocIdString&>(id.getScheme())
+ .getOrdering(), false));
+ }
+ }
+ return std::unique_ptr<Value>(new InvalidValue());
+ case USER:
+ if (id.getScheme().hasNumber()) {
+ return std::unique_ptr<Value>(
+ new IntegerValue(id.getScheme().getNumber(), false));
+ } else {
+ return std::unique_ptr<Value>(new InvalidValue);
+ }
+ }
+
+ return std::unique_ptr<Value>(new StringValue(value));
+}
+
+
+std::unique_ptr<Value>
+IdValueNode::traceValue(const Context& context,
+ std::ostream &out) const
+{
+ if (context._doc != NULL) {
+ return traceValue(context._doc->getId(), out);
+ } else if (context._docId != NULL) {
+ return traceValue(*context._docId, out);
+ } else {
+ return traceValue(context._docUpdate->getId(), out);
+ }
+}
+
+
+std::unique_ptr<Value>
+IdValueNode::traceValue(const DocumentId& id, std::ostream& out) const
+{
+ vespalib::string value;
+ switch (_type) {
+ case BUCKET:
+ {
+ document::BucketId bucket(_bucketIdFactory.getBucketId(id));
+ std::unique_ptr<Value> result(
+ new IntegerValue(bucket.getId(), true));
+ out << "Found id.bucket specification. Resolved to "
+ << bucket.toString() << ".\n";
+ return result;
+ }
+ case NS:
+ value = id.getScheme().getNamespace();
+ out << "Resolved id.namespace to value\"" << value << "\".\n";
+ break;
+ case SCHEME:
+ value = id.getScheme().getTypeName(id.getScheme().getType());
+ out << "Resolved id.scheme to value\"" << value << "\".\n";
+ break;
+ case TYPE:
+ if (id.getScheme().hasDocType()) {
+ value = id.getScheme().getDocType();
+ out << "Resolved id.type to value\"" << value << "\".\n";
+ } else {
+ out << "Could not resolve type of doc " << id << ".\n";
+ return std::unique_ptr<Value>(new InvalidValue);
+ }
+ break;
+ case SPEC:
+ value = id.getScheme().getNamespaceSpecific();
+ out << "Resolved id.specific to value\"" << value << "\".\n";
+ break;
+ case ALL:
+ value = id.getScheme().toString();
+ out << "Resolved id to \"" << value << "\".\n";
+ break;
+ case GROUP:
+ if (id.getScheme().hasGroup()) {
+ value = id.getScheme().getGroup();
+ out << "Resolved group of doc (type " << id.getScheme().getType()
+ << ") to \"" << value << "\".\n";
+ } else {
+ out << "Can't resolve group of doc \"" << id << "\".\n";
+ return std::unique_ptr<Value>(new InvalidValue);
+ }
+ break;
+ case GID:
+ value = id.getGlobalId().toString();
+ out << "Resolved gid to \"" << value << "\".\n";
+ break;
+ case ORDER:
+ if (id.getScheme().getType() == IdString::ORDERDOC) {
+ const OrderDocIdString& ods(
+ static_cast<const OrderDocIdString&>(id.getScheme()));
+ if (ods.getWidthBits() == _widthBits
+ && ods.getDivisionBits() == _divisionBits)
+ {
+ std::unique_ptr<Value> result(new IntegerValue(
+ static_cast<const OrderDocIdString&>(id.getScheme())
+ .getOrdering(), false));
+ out << "Resolved id.order to int " << *result << "\n";
+ return result;
+ }
+ }
+ out << "Could not resolve id.order(" << _widthBits << ", "
+ << _divisionBits << ") of doc " << id << ".\n";
+ return std::unique_ptr<Value>(new InvalidValue());
+ case USER:
+ if (id.getScheme().hasNumber()) {
+ std::unique_ptr<Value> result(
+ new IntegerValue(id.getScheme().getNumber(), false));
+ out << "Resolved user of doc type " << id.getScheme().getType()
+ << " to " << *result << ".\n";
+ return result;
+ } else {
+ out << "Could not resolve user of doc " << id << ".\n";
+ return std::unique_ptr<Value>(new InvalidValue);
+ }
+ }
+
+ return std::unique_ptr<Value>(new StringValue(value));
+}
+
+
+void
+IdValueNode::visit(Visitor &visitor) const
+{
+ visitor.visitIdValueNode(*this);
+}
+
+
+void
+IdValueNode::print(std::ostream& out, bool verbose,
+ const std::string& indent) const
+{
+ (void) verbose; (void) indent;
+ if (hadParentheses()) out << '(';
+ out << _id;
+ if (_type != ALL) {
+ out << '.' << _typestring;
+ }
+ if (_type == ORDER) {
+ out << "(" << _widthBits << "," << _divisionBits << ")";
+ }
+ if (hadParentheses()) out << ')';
+}
+
+SearchColumnValueNode::SearchColumnValueNode(
+ const BucketIdFactory& bucketIdFactory,
+ const vespalib::stringref & name, int numColumns)
+ : _bucketIdFactory(bucketIdFactory),
+ _id(name),
+ _numColumns(numColumns),
+ _distribution(std::make_unique<BucketDistribution>(_numColumns, 16))
+{
+}
+
+int64_t
+SearchColumnValueNode::getValue(const BucketId& id) const
+{
+ return _distribution->getColumn(id);
+}
+
+
+std::unique_ptr<Value>
+SearchColumnValueNode::getValue(const Context& context) const
+{
+ if (context._doc != NULL) {
+ return getValue(context._doc->getId());
+ } else if (context._docId != NULL) {
+ return getValue(*context._docId);
+ } else {
+ return getValue(context._docUpdate->getId());
+ }
+}
+
+
+std::unique_ptr<Value>
+SearchColumnValueNode::getValue(const DocumentId& id) const
+{
+ return std::unique_ptr<Value>(new IntegerValue(
+ getValue(_bucketIdFactory.getBucketId(id)), false));
+}
+
+
+std::unique_ptr<Value>
+SearchColumnValueNode::traceValue(const Context& context,
+ std::ostream &out) const
+{
+ if (context._doc != NULL) {
+ return traceValue(context._doc->getId(), out);
+ } else if (context._docId != NULL) {
+ return traceValue(*context._docId, out);
+ } else {
+ return traceValue(context._docUpdate->getId(), out);
+ }
+}
+
+
+std::unique_ptr<Value>
+SearchColumnValueNode::traceValue(const DocumentId& id,
+ std::ostream& out) const
+{
+ std::unique_ptr<Value> result(new IntegerValue(
+ getValue(_bucketIdFactory.getBucketId(id)), false));
+ out << "Resolved search column of doc \"" << id << "\" to " << *result
+ << "\n";
+ return result;
+}
+
+
+void
+SearchColumnValueNode::visit(Visitor &visitor) const
+{
+ visitor.visitSearchColumnValueNode(*this);
+}
+
+
+void
+SearchColumnValueNode::print(std::ostream& out, bool verbose,
+ const std::string& indent) const
+{
+ (void) verbose; (void) indent;
+ if (hadParentheses()) out << '(';
+ out << _id;
+ out << '.' << _numColumns;
+ if (hadParentheses()) out << ')';
+}
+
+namespace {
+ union HashUnion {
+ unsigned char _key[16];
+ int64_t _hash[2];
+ };
+ int64_t hash(const void* data, uint32_t len) {
+ HashUnion hash;
+ fastc_md5sum((const unsigned char*) data, len, hash._key);
+ return hash._hash[0];
+ }
+}
+
+FunctionValueNode::FunctionValueNode(const vespalib::stringref & name,
+ std::unique_ptr<ValueNode> src)
+ : _function(),
+ _funcname(name),
+ _source(std::move(src))
+{
+ if (name == "lowercase") {
+ _function = LOWERCASE;
+ } else if (name == "hash") {
+ _function = HASH;
+ } else if (name == "abs") {
+ _function = ABS;
+ } else {
+ throw ParsingFailedException("No function '"+name+"' exist.",
+ VESPA_STRLOC);
+ }
+}
+
+std::unique_ptr<Value>
+FunctionValueNode::getValue(std::unique_ptr<Value> val) const
+{
+ switch (val->getType()) {
+ case Value::String:
+ {
+ StringValue& sval(static_cast<StringValue&>(*val));
+ if (_function == LOWERCASE) {
+ return std::unique_ptr<Value>(new StringValue(
+ vespalib::LowerCase::convert(sval.getValue())));
+ } else if (_function == HASH) {
+ return std::unique_ptr<Value>(new IntegerValue(
+ hash(sval.getValue().c_str(), sval.getValue().size()),
+ false));
+ }
+ break;
+ }
+ case Value::Float:
+ {
+ FloatValue& fval(static_cast<FloatValue&>(*val));
+ if (_function == HASH) {
+ FloatValue::ValueType ffval = fval.getValue();
+ return std::unique_ptr<Value>(new IntegerValue(
+ hash(&ffval, sizeof(ffval)), false));
+ } else if (_function == ABS) {
+ FloatValue::ValueType ffval = fval.getValue();
+ if (ffval < 0) ffval *= -1;
+ return std::unique_ptr<Value>(new FloatValue(ffval));
+ }
+ break;
+ }
+ case Value::Integer:
+ {
+ IntegerValue& ival(static_cast<IntegerValue&>(*val));
+ if (_function == HASH) {
+ IntegerValue::ValueType iival = ival.getValue();
+ return std::unique_ptr<Value>(new IntegerValue(
+ hash(&iival, sizeof(iival)), false));
+ } else if (_function == ABS) {
+ IntegerValue::ValueType iival = ival.getValue();
+ if (iival < 0) iival *= -1;
+ return std::unique_ptr<Value>(new IntegerValue(iival, false));
+ }
+ break;
+ }
+ case Value::Bucket:
+ {
+ throw ParsingFailedException(
+ "No functioncalls are allowed on value of type bucket",
+ VESPA_STRLOC);
+ break;
+ }
+
+ case Value::Array: break;
+ case Value::Struct: break;
+ case Value::Invalid: break;
+ case Value::Null: break;
+ }
+ return std::unique_ptr<Value>(new InvalidValue);
+}
+
+std::unique_ptr<Value>
+FunctionValueNode::traceValue(std::unique_ptr<Value> val,
+ std::ostream& out) const
+{
+ switch (val->getType()) {
+ case Value::String:
+ {
+ StringValue& sval(static_cast<StringValue&>(*val));
+ if (_function == LOWERCASE) {
+ std::unique_ptr<Value> result(new StringValue(
+ vespalib::LowerCase::convert(sval.getValue())));
+ out << "Performed lowercase function on '" << sval
+ << "' => '" << *result << "'.\n";
+ return result;
+ } else if (_function == HASH) {
+ std::unique_ptr<Value> result(new IntegerValue(
+ hash(sval.getValue().c_str(), sval.getValue().size()),
+ false));
+ out << "Performed hash on string '" << sval << "' -> "
+ << *result << "\n";
+ return result;
+ }
+ break;
+ }
+ case Value::Float:
+ {
+ FloatValue& fval(static_cast<FloatValue&>(*val));
+ if (_function == HASH) {
+ FloatValue::ValueType ffval = fval.getValue();
+ std::unique_ptr<Value> result(new IntegerValue(
+ hash(&ffval, sizeof(ffval)), false));
+ out << "Performed hash on float " << ffval << " -> " << *result
+ << "\n";
+ return result;
+ } else if (_function == ABS) {
+ FloatValue::ValueType ffval = fval.getValue();
+ if (ffval < 0) ffval *= -1;
+ out << "Performed abs on float " << fval.getValue() << " -> "
+ << ffval << "\n";
+ return std::unique_ptr<Value>(new FloatValue(ffval));
+ }
+ break;
+ }
+ case Value::Integer:
+ {
+ IntegerValue& ival(static_cast<IntegerValue&>(*val));
+ if (_function == HASH) {
+ IntegerValue::ValueType iival = ival.getValue();
+ std::unique_ptr<Value> result(new IntegerValue(
+ hash(&iival, sizeof(iival)), false));
+ out << "Performed hash on float " << iival << " -> " << *result
+ << "\n";
+ return result;
+ } else if (_function == ABS) {
+ IntegerValue::ValueType iival = ival.getValue();
+ if (iival < 0) iival *= -1;
+ out << "Performed abs on integer " << ival.getValue() << " -> "
+ << iival << "\n";
+ return std::unique_ptr<Value>(new IntegerValue(iival, false));
+ }
+ break;
+ }
+ case Value::Bucket: break;
+ case Value::Array: break;
+ case Value::Struct: break;
+ case Value::Invalid: break;
+ case Value::Null: break;
+ }
+ out << "Cannot use function " << _function << " on a value of type "
+ << val->getType() << ". Resolving invalid.\n";
+ return std::unique_ptr<Value>(new InvalidValue);
+}
+
+
+void
+FunctionValueNode::visit(Visitor &visitor) const
+{
+ visitor.visitFunctionValueNode(*this);
+}
+
+
+void
+FunctionValueNode::print(std::ostream& out, bool verbose,
+ const std::string& indent) const
+{
+ if (hadParentheses()) out << '(';
+ _source->print(out, verbose, indent);
+ out << '.' << _funcname << "()";
+ if (hadParentheses()) out << ')';
+}
+
+ArithmeticValueNode::ArithmeticValueNode(
+ std::unique_ptr<ValueNode> left, const vespalib::stringref & op,
+ std::unique_ptr<ValueNode> right)
+ : _operator(),
+ _left(std::move(left)),
+ _right(std::move(right))
+{
+ if (op.size() == 1) switch (op[0]) {
+ case '+': _operator = ADD; return;
+ case '-': _operator = SUB; return;
+ case '*': _operator = MUL; return;
+ case '/': _operator = DIV; return;
+ case '%': _operator = MOD; return;
+ }
+ throw ParsingFailedException(
+ "Arithmetic operator '"+op+"' does not exist.", VESPA_STRLOC);
+}
+
+const char*
+ArithmeticValueNode::getOperatorName() const
+{
+ switch (_operator) {
+ case ADD: return "+";
+ case SUB: return "-";
+ case MUL: return "*";
+ case DIV: return "/";
+ case MOD: return "%";
+ }
+ return "UNKNOWN";
+}
+
+
+
+std::unique_ptr<Value>
+ArithmeticValueNode::getValue(std::unique_ptr<Value> lval,
+ std::unique_ptr<Value> rval) const
+{
+ switch (_operator) {
+ case ADD:
+ {
+ if (lval->getType() == Value::String &&
+ rval->getType() == Value::String)
+ {
+ StringValue& slval(static_cast<StringValue&>(*lval));
+ StringValue& srval(static_cast<StringValue&>(*rval));
+ return std::unique_ptr<Value>(new StringValue(
+ slval.getValue() + srval.getValue()));
+ }
+ }
+ case SUB:
+ case MUL:
+ case DIV:
+ {
+ if (lval->getType() == Value::Integer &&
+ rval->getType() == Value::Integer)
+ {
+ IntegerValue& ilval(static_cast<IntegerValue&>(*lval));
+ IntegerValue& irval(static_cast<IntegerValue&>(*rval));
+ IntegerValue::ValueType res = 0;
+ switch (_operator) {
+ case ADD: res = ilval.getValue() + irval.getValue(); break;
+ case SUB: res = ilval.getValue() - irval.getValue(); break;
+ case MUL: res = ilval.getValue() * irval.getValue(); break;
+ case DIV:
+ if (irval.getValue() != 0) {
+ res = ilval.getValue() / irval.getValue();
+ } else {
+ throw vespalib::IllegalArgumentException("Division by zero");
+ }
+ break;
+ case MOD: assert(0);
+ }
+ return std::unique_ptr<Value>(new IntegerValue(res, false));
+ }
+ NumberValue* nlval(dynamic_cast<NumberValue*>(lval.get()));
+ NumberValue* nrval(dynamic_cast<NumberValue*>(rval.get()));
+ if (nlval != 0 && nrval != 0) {
+ NumberValue::CommonValueType res = 0;
+ switch (_operator) {
+ case ADD: res = nlval->getCommonValue()
+ + nrval->getCommonValue(); break;
+ case SUB: res = nlval->getCommonValue()
+ - nrval->getCommonValue(); break;
+ case MUL: res = nlval->getCommonValue()
+ * nrval->getCommonValue(); break;
+ case DIV:
+ if (nrval->getCommonValue() != 0) {
+ res = nlval->getCommonValue()
+ / nrval->getCommonValue();
+ } else {
+ throw vespalib::IllegalArgumentException("Division by zero");
+ }
+ break;
+ case MOD: assert(0);
+ }
+ return std::unique_ptr<Value>(new FloatValue(res));
+ }
+ }
+ case MOD:
+ {
+ if (lval->getType() == Value::Integer &&
+ rval->getType() == Value::Integer)
+ {
+ IntegerValue& ilval(static_cast<IntegerValue&>(*lval));
+ IntegerValue& irval(static_cast<IntegerValue&>(*rval));
+ if (irval.getValue() != 0) {
+ return std::unique_ptr<Value>(new IntegerValue(ilval.getValue() % irval.getValue(), false));
+ } else {
+ throw vespalib::IllegalArgumentException("Division by zero");
+ }
+ }
+ }
+ }
+ return std::unique_ptr<Value>(new InvalidValue);
+}
+
+std::unique_ptr<Value>
+ArithmeticValueNode::traceValue(std::unique_ptr<Value> lval,
+ std::unique_ptr<Value> rval,
+ std::ostream& out) const
+{
+ switch (_operator) {
+ case ADD:
+ {
+ if (lval->getType() == Value::String &&
+ rval->getType() == Value::String)
+ {
+ StringValue& slval(static_cast<StringValue&>(*lval));
+ StringValue& srval(static_cast<StringValue&>(*rval));
+ std::unique_ptr<Value> result(new StringValue(
+ slval.getValue() + srval.getValue()));
+ out << "Appended strings '" << slval << "' + '" << srval
+ << "' -> '" << *result << "'.\n";
+ return result;
+ }
+ }
+ case SUB:
+ case MUL:
+ case DIV:
+ {
+ if (lval->getType() == Value::Integer &&
+ rval->getType() == Value::Integer)
+ {
+ IntegerValue& ilval(static_cast<IntegerValue&>(*lval));
+ IntegerValue& irval(static_cast<IntegerValue&>(*rval));
+ IntegerValue::ValueType res = 0;
+ switch (_operator) {
+ case ADD: res = ilval.getValue() + irval.getValue(); break;
+ case SUB: res = ilval.getValue() - irval.getValue(); break;
+ case MUL: res = ilval.getValue() * irval.getValue(); break;
+ case DIV: res = ilval.getValue() / irval.getValue(); break;
+ case MOD: assert(0);
+ }
+ std::unique_ptr<Value> result(new IntegerValue(res, false));
+ out << "Performed integer operation " << ilval << " "
+ << getOperatorName() << " " << irval << " = " << *result
+ << "\n";
+ return result;
+ }
+ NumberValue* nlval(dynamic_cast<NumberValue*>(lval.get()));
+ NumberValue* nrval(dynamic_cast<NumberValue*>(lval.get()));
+ if (nlval != 0 && nrval != 0) {
+ NumberValue::CommonValueType res = 0;
+ switch (_operator) {
+ case ADD: res = nlval->getCommonValue()
+ + nrval->getCommonValue(); break;
+ case SUB: res = nlval->getCommonValue()
+ - nrval->getCommonValue(); break;
+ case MUL: res = nlval->getCommonValue()
+ * nrval->getCommonValue(); break;
+ case DIV: res = nlval->getCommonValue()
+ / nrval->getCommonValue(); break;
+ case MOD: assert(0);
+ }
+ std::unique_ptr<Value> result(new FloatValue(res));
+ out << "Performed float operation " << nlval << " "
+ << getOperatorName() << " " << nrval << " = " << *result
+ << "\n";
+ return result;
+ }
+ }
+ case MOD:
+ {
+ if (lval->getType() == Value::Integer &&
+ rval->getType() == Value::Integer)
+ {
+ IntegerValue& ilval(static_cast<IntegerValue&>(*lval));
+ IntegerValue& irval(static_cast<IntegerValue&>(*rval));
+ std::unique_ptr<Value> result(new IntegerValue(
+ ilval.getValue() % irval.getValue(), false));
+ out << "Performed integer operation " << ilval << " "
+ << getOperatorName() << " " << irval << " = " << *result
+ << "\n";
+ return result;
+ }
+ }
+ }
+ out << "Failed to do operation " << getOperatorName()
+ << " on values of type " << lval->getType() << " and "
+ << rval->getType() << ". Resolving invalid.\n";
+ return std::unique_ptr<Value>(new InvalidValue);
+}
+
+
+void
+ArithmeticValueNode::visit(Visitor &visitor) const
+{
+ visitor.visitArithmeticValueNode(*this);
+}
+
+
+void
+ArithmeticValueNode::print(std::ostream& out, bool verbose,
+ const std::string& indent) const
+{
+ if (hadParentheses()) out << '(';
+ _left->print(out, verbose, indent);
+ switch (_operator) {
+ case ADD: out << " + "; break;
+ case SUB: out << " - "; break;
+ case MUL: out << " * "; break;
+ case DIV: out << " / "; break;
+ case MOD: out << " % "; break;
+ }
+ _right->print(out, verbose, indent);
+ if (hadParentheses()) out << ')';
+}
+
+}
+
diff --git a/document/src/vespa/document/select/valuenodes.h b/document/src/vespa/document/select/valuenodes.h
new file mode 100644
index 00000000000..98f80e2904a
--- /dev/null
+++ b/document/src/vespa/document/select/valuenodes.h
@@ -0,0 +1,348 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+/**
+ * @class document::select::ValueNode
+ * @ingroup select
+ *
+ * @brief Node representing a value in the tree
+ *
+ * @author H�kon Humberset
+ * @date 2007-04-20
+ * @version $Id$
+ */
+
+#pragma once
+
+#include "valuenode.h"
+#include <vespa/document/base/fieldpath.h>
+
+namespace document {
+
+class BucketDistribution;
+class BucketIdFactory;
+class DocumentId;
+class BucketId;
+class DocumentType;
+
+namespace select {
+
+class InvalidValueNode : public ValueNode
+{
+ vespalib::string _name;
+public:
+ InvalidValueNode(const vespalib::stringref & name);
+
+ std::unique_ptr<Value> getValue(const Context&) const override {
+ return std::unique_ptr<Value>(new InvalidValue());
+ }
+
+ void print(std::ostream& out, bool verbose, const std::string& indent) const override;
+ void visit(Visitor& visitor) const override;
+
+ ValueNode::UP clone() const override {
+ return wrapParens(new InvalidValueNode(_name));
+ }
+};
+
+class NullValueNode : public ValueNode
+{
+ vespalib::string _name;
+public:
+ NullValueNode(const vespalib::stringref & name);
+
+ std::unique_ptr<Value> getValue(const Context&) const override {
+ return std::unique_ptr<Value>(new NullValue());
+ }
+
+ void print(std::ostream& out, bool verbose, const std::string& indent) const override;
+
+ void visit(Visitor& visitor) const override;
+
+ ValueNode::UP clone() const override {
+ return wrapParens(new NullValueNode(_name));
+ }
+};
+
+class StringValueNode : public ValueNode
+{
+ vespalib::string _value;
+public:
+ StringValueNode(const vespalib::stringref & val);
+
+ const vespalib::string& getValue() const { return _value; }
+
+ std::unique_ptr<Value> getValue(const Context&) const override {
+ return std::unique_ptr<Value>(new StringValue(_value));
+ }
+
+ void print(std::ostream& out, bool verbose, const std::string& indent) const override;
+ void visit(Visitor& visitor) const override;
+
+ ValueNode::UP clone() const override {
+ return wrapParens(new StringValueNode(_value));
+ }
+};
+
+class IntegerValueNode : public ValueNode
+{
+ int64_t _value;
+ bool _isBucketValue;
+public:
+ IntegerValueNode(int64_t val, bool isBucketValue)
+ : _value(val), _isBucketValue(isBucketValue) {}
+
+ int64_t getValue() const { return _value; }
+
+ virtual std::unique_ptr<Value> getValue(const Context&) const override {
+ return std::unique_ptr<Value>(new IntegerValue(_value, _isBucketValue));
+ }
+
+ void print(std::ostream& out, bool verbose, const std::string& indent) const override;
+ void visit(Visitor& visitor) const override;
+
+ ValueNode::UP clone() const override {
+ return wrapParens(new IntegerValueNode(_value, _isBucketValue));
+ }
+};
+
+class CurrentTimeValueNode : public ValueNode
+{
+public:
+ int64_t getValue() const;
+
+ std::unique_ptr<Value> getValue(const Context&) const override {
+ return std::unique_ptr<Value>(new IntegerValue(getValue(), false));
+ }
+
+ void print(std::ostream& out, bool verbose, const std::string& indent) const override;
+ void visit(Visitor& visitor) const override;
+
+ ValueNode::UP clone() const override {
+ return wrapParens(new CurrentTimeValueNode);
+ }
+};
+
+class VariableValueNode : public ValueNode
+{
+ vespalib::string _value;
+public:
+ VariableValueNode(const vespalib::string & variableName) : _value(variableName) {}
+
+ const vespalib::string& getVariableName() const { return _value; }
+
+ std::unique_ptr<Value> getValue(const Context& context) const override;
+ void print(std::ostream& out, bool verbose, const std::string& indent) const override;
+ void visit(Visitor& visitor) const override;
+
+ ValueNode::UP clone() const override {
+ return wrapParens(new VariableValueNode(_value));
+ }
+};
+
+class FloatValueNode : public ValueNode
+{
+ double _value;
+public:
+ FloatValueNode(double val) : _value(val) {}
+
+ double getValue() const { return _value; }
+
+ std::unique_ptr<Value> getValue(const Context&) const override {
+ return std::unique_ptr<Value>(new FloatValue(_value));
+ }
+
+ void print(std::ostream& out, bool verbose, const std::string& indent) const override;
+ void visit(Visitor& visitor) const override;
+
+ ValueNode::UP clone() const override {
+ return wrapParens(new FloatValueNode(_value));
+ }
+};
+
+class FieldValueNode : public ValueNode
+{
+ vespalib::string _doctype;
+ vespalib::string _fieldExpression;
+ vespalib::string _fieldName;
+ mutable FieldPath _fieldPath;
+
+public:
+ FieldValueNode(const vespalib::string& doctype, const vespalib::string& fieldExpression);
+ FieldValueNode(const FieldValueNode &);
+ FieldValueNode & operator = (const FieldValueNode &);
+ FieldValueNode(FieldValueNode &&) = default;
+ FieldValueNode & operator = (FieldValueNode &&) = default;
+ ~FieldValueNode();
+
+ const vespalib::string& getDocType() const { return _doctype; }
+ const vespalib::string& getRealFieldName() const { return _fieldName; }
+ const vespalib::string& getFieldName() const { return _fieldExpression; }
+
+ std::unique_ptr<Value> getValue(const Context& context) const override;
+ std::unique_ptr<Value> traceValue(const Context &context, std::ostream& out) const override;
+ void print(std::ostream& out, bool verbose, const std::string& indent) const override;
+ void visit(Visitor& visitor) const override;
+
+ ValueNode::UP clone() const override {
+ return wrapParens(new FieldValueNode(_doctype, _fieldExpression));
+ }
+
+ static vespalib::string extractFieldName(const std::string & fieldExpression);
+
+private:
+
+ void initFieldPath(const DocumentType&) const;
+};
+
+class IdValueNode : public ValueNode
+{
+public:
+ enum Type { SCHEME, NS, TYPE, USER, GROUP, GID, SPEC, BUCKET, ORDER, ALL };
+
+ IdValueNode(const BucketIdFactory& bucketIdFactory,
+ const vespalib::stringref & name, const vespalib::stringref & type,
+ int widthBits = -1, int divisionBits = -1);
+
+ Type getType() const { return _type; }
+
+ std::unique_ptr<Value> getValue(const Context& context) const override;
+
+ std::unique_ptr<Value> getValue(const DocumentId& id) const;
+
+ std::unique_ptr<Value> traceValue(const Context& context, std::ostream &out) const override;
+
+ std::unique_ptr<Value> traceValue(const DocumentId& val, std::ostream& out) const;
+
+ void print(std::ostream& out, bool verbose, const std::string& indent) const override;
+
+ void visit(Visitor& visitor) const override;
+
+ ValueNode::UP clone() const override {
+ return wrapParens(new IdValueNode(_bucketIdFactory, _id, _typestring, _widthBits, _divisionBits));
+ }
+
+ int getWidthBits() const { return _widthBits; }
+ int getDivisionBits() const { return _divisionBits; }
+
+private:
+ const BucketIdFactory& _bucketIdFactory;
+ vespalib::string _id;
+ vespalib::string _typestring;
+ Type _type;
+ int _widthBits;
+ int _divisionBits;
+};
+
+class SearchColumnValueNode : public ValueNode
+{
+public:
+ SearchColumnValueNode(const BucketIdFactory& bucketIdFactory,
+ const vespalib::stringref & name,
+ int numColumns);
+
+ int getColumns() { return _numColumns; }
+
+ std::unique_ptr<Value> getValue(const Context& context) const override;
+ std::unique_ptr<Value> getValue(const DocumentId& id) const;
+ std::unique_ptr<Value> traceValue(const Context& context, std::ostream &out) const override;
+ std::unique_ptr<Value> traceValue(const DocumentId& val, std::ostream& out) const;
+
+ int64_t getValue(const BucketId& bucketId) const;
+ void print(std::ostream& out, bool verbose, const std::string& indent) const override;
+ void visit(Visitor& visitor) const override;
+
+ ValueNode::UP clone() const override {
+ return wrapParens(new SearchColumnValueNode(_bucketIdFactory, _id, _numColumns));
+}
+
+private:
+ const BucketIdFactory& _bucketIdFactory;
+ vespalib::string _id;
+ int _numColumns;
+ std::unique_ptr<BucketDistribution> _distribution;
+};
+
+class FunctionValueNode : public ValueNode
+{
+public:
+ enum Function { LOWERCASE, HASH, ABS };
+
+ FunctionValueNode(const vespalib::stringref & name, std::unique_ptr<ValueNode> src);
+
+ Function getFunction() const { return _function; }
+ const vespalib::string &getFunctionName(void) const { return _funcname; }
+
+ std::unique_ptr<Value> getValue(const Context& context) const override {
+ return getValue(_source->getValue(context));
+ }
+
+ std::unique_ptr<Value> traceValue(const Context &context, std::ostream& out) const override {
+ return traceValue(_source->getValue(context), out);
+ }
+
+ void print(std::ostream& out, bool verbose, const std::string& indent) const override;
+ void visit(Visitor& visitor) const override;
+
+ ValueNode::UP clone() const override {
+ return wrapParens(new FunctionValueNode(_funcname, _source->clone()));
+ }
+
+ const ValueNode& getChild() const { return *_source; }
+
+private:
+ Function _function;
+ vespalib::string _funcname;
+ std::unique_ptr<ValueNode> _source;
+
+ virtual std::unique_ptr<Value> getValue(std::unique_ptr<Value> val) const;
+ virtual std::unique_ptr<Value> traceValue(std::unique_ptr<Value> val,
+ std::ostream& out) const;
+};
+
+class ArithmeticValueNode : public ValueNode
+{
+public:
+ enum Operator { ADD, SUB, MUL, DIV, MOD };
+
+ ArithmeticValueNode(std::unique_ptr<ValueNode> left,
+ const vespalib::stringref & op,
+ std::unique_ptr<ValueNode> right);
+
+ Operator getOperator() const { return _operator; }
+ const char* getOperatorName() const;
+
+ std::unique_ptr<Value>
+ getValue(const Context& context) const override {
+ return getValue(_left->getValue(context), _right->getValue(context));
+ }
+
+ std::unique_ptr<Value>
+ traceValue(const Context &context, std::ostream& out) const override {
+ return traceValue(_left->getValue(context), _right->getValue(context), out);
+ }
+
+ void print(std::ostream& out, bool verbose, const std::string& indent) const override;
+ void visit(Visitor& visitor) const override;
+
+ ValueNode::UP clone() const override {
+ return wrapParens(new ArithmeticValueNode(_left->clone(),
+ getOperatorName(),
+ _right->clone()));
+ }
+
+ const ValueNode& getLeft() const { return *_left; }
+ const ValueNode& getRight() const { return *_right; }
+
+private:
+ Operator _operator;
+ std::unique_ptr<ValueNode> _left;
+ std::unique_ptr<ValueNode> _right;
+
+ virtual std::unique_ptr<Value> getValue(std::unique_ptr<Value> lval,
+ std::unique_ptr<Value> rval) const;
+ virtual std::unique_ptr<Value> traceValue(std::unique_ptr<Value> lval,
+ std::unique_ptr<Value> rval,
+ std::ostream&) const;
+};
+
+} // select
+} // document
diff --git a/fastos/src/vespa/fastos/time.h b/fastos/src/vespa/fastos/time.h
index 97ebe21a3b5..1e37813a072 100644
--- a/fastos/src/vespa/fastos/time.h
+++ b/fastos/src/vespa/fastos/time.h
@@ -1,8 +1,6 @@
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#pragma once
-#include <vespa/fastos/types.h>
-
/**
* Interface to OS time functions.
*/
@@ -12,7 +10,7 @@ protected:
/**
* Destructor. No cleanup needed for base class.
*/
- virtual ~FastOS_TimeInterface(void) { }
+ virtual ~FastOS_TimeInterface() { }
public:
/**
@@ -49,30 +47,26 @@ public:
* Note: Only millisecond accuracy is guaranteed.
* @param microsecs Number of microseconds to add.
*/
- void AddMicroSecs(double microsecs)
- { SetMicroSecs(MicroSecs() + microsecs); }
+ void AddMicroSecs(double microsecs) { SetMicroSecs(MicroSecs() + microsecs); }
/**
* Add a specified number of milliseconds to the time.
* @param millisecs Number of milliseconds to add.
*/
- void AddMilliSecs(double millisecs)
- { SetMilliSecs(MilliSecs() + millisecs); }
+ void AddMilliSecs(double millisecs) { SetMilliSecs(MilliSecs() + millisecs); }
/**
* Subtract a specified number of microseconds from the time.
* Note: Only millisecond accuracy is guaranteed.
* @param microsecs Number of microseconds to subtract.
*/
- void SubtractMicroSecs(double microsecs)
- { SetMicroSecs(MicroSecs() - microsecs); }
+ void SubtractMicroSecs(double microsecs) { SetMicroSecs(MicroSecs() - microsecs); }
/**
* Subtract a specified number of milliseconds from the time.
* @param millisecs Number of milliseconds to subtract.
*/
- void SubtractMilliSecs(double millisecs)
- { SetMilliSecs(MilliSecs() - millisecs); }
+ void SubtractMilliSecs(double millisecs) { SetMilliSecs(MilliSecs() - millisecs); }
/**
* Return the time in microseconds.
@@ -133,7 +127,6 @@ public:
virtual long int GetMicroSeconds() const = 0;
};
-
#include <vespa/fastos/unix_time.h>
-typedef FastOS_UNIX_Time FASTOS_PREFIX(Time);
+using FastOS_Time = FastOS_UNIX_Time;
diff --git a/fastos/src/vespa/fastos/unix_time.cpp b/fastos/src/vespa/fastos/unix_time.cpp
index 202ffe6d82a..6b6a8e58ffb 100644
--- a/fastos/src/vespa/fastos/unix_time.cpp
+++ b/fastos/src/vespa/fastos/unix_time.cpp
@@ -1,6 +1,7 @@
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-#include <vespa/fastos/time.h>
+#include "time.h"
+#include "types.h"
double
FastOS_UNIX_Time::MicroSecs() const
@@ -96,3 +97,8 @@ FastOS_UNIX_Time::SetSecs(double secs)
_time.tv_usec = - static_cast<int>((- secs - (-_time.tv_sec)) * 1000000);
}
}
+
+void FastOS_UNIX_Time::SetNow() {
+ gettimeofday(&_time, NULL);
+}
+
diff --git a/fastos/src/vespa/fastos/unix_time.h b/fastos/src/vespa/fastos/unix_time.h
index dd6122bc463..5ae4916418a 100644
--- a/fastos/src/vespa/fastos/unix_time.h
+++ b/fastos/src/vespa/fastos/unix_time.h
@@ -89,9 +89,8 @@ public:
void SetMilliSecs(double millisecs) override;
void SetSecs(double secs) override;
- void SetNow() override { gettimeofday(&_time, NULL); }
+ void SetNow() override;
long int GetSeconds() const override { return _time.tv_sec; }
long int GetMicroSeconds() const override { return _time.tv_usec; }
};
-
diff --git a/messagebus/src/vespa/messagebus/callstack.cpp b/messagebus/src/vespa/messagebus/callstack.cpp
index 5311a75c3c5..44ae4190698 100644
--- a/messagebus/src/vespa/messagebus/callstack.cpp
+++ b/messagebus/src/vespa/messagebus/callstack.cpp
@@ -4,6 +4,7 @@
#include "message.h"
#include "reply.h"
#include "idiscardhandler.h"
+#include <cassert>
namespace mbus {
diff --git a/searchcore/src/tests/proton/common/selectpruner_test.cpp b/searchcore/src/tests/proton/common/selectpruner_test.cpp
index 29ef6ef016c..0a181de39ec 100644
--- a/searchcore/src/tests/proton/common/selectpruner_test.cpp
+++ b/searchcore/src/tests/proton/common/selectpruner_test.cpp
@@ -7,6 +7,7 @@
#include <vespa/searchcore/proton/common/selectpruner.h>
#include <vespa/document/select/parser.h>
#include <vespa/document/select/cloningvisitor.h>
+#include <vespa/document/fieldvalue/document.h>
#include <vespa/searchlib/attribute/attributefactory.h>
#include <vespa/searchlib/test/mock_attribute_manager.h>
diff --git a/searchcore/src/vespa/searchcore/proton/common/attributefieldvaluenode.cpp b/searchcore/src/vespa/searchcore/proton/common/attributefieldvaluenode.cpp
index d15eddb3ac4..10c2adfd1f2 100644
--- a/searchcore/src/vespa/searchcore/proton/common/attributefieldvaluenode.cpp
+++ b/searchcore/src/vespa/searchcore/proton/common/attributefieldvaluenode.cpp
@@ -3,6 +3,8 @@
#include "attributefieldvaluenode.h"
#include "selectcontext.h"
#include <vespa/searchcommon/attribute/attributecontent.h>
+#include <vespa/searchlib/attribute/attributevector.h>
+
namespace proton {
@@ -20,11 +22,10 @@ using search::attribute::BasicType;
using search::attribute::CollectionType;
using search::attribute::IAttributeVector;
-
AttributeFieldValueNode::
AttributeFieldValueNode(const vespalib::string& doctype,
const vespalib::string& field,
- const search::AttributeVector::SP &attribute)
+ const std::shared_ptr<search::AttributeVector> &attribute)
: FieldValueNode(doctype, field),
_attribute(attribute)
{
@@ -94,5 +95,11 @@ AttributeFieldValueNode::traceValue(const Context &context,
}
+document::select::ValueNode::UP
+AttributeFieldValueNode::clone() const
+{
+ return wrapParens(new AttributeFieldValueNode(getDocType(), getFieldName(), _attribute));
+}
+
} // namespace proton
diff --git a/searchcore/src/vespa/searchcore/proton/common/attributefieldvaluenode.h b/searchcore/src/vespa/searchcore/proton/common/attributefieldvaluenode.h
index 38e532053d4..c0ffbaea987 100644
--- a/searchcore/src/vespa/searchcore/proton/common/attributefieldvaluenode.h
+++ b/searchcore/src/vespa/searchcore/proton/common/attributefieldvaluenode.h
@@ -1,38 +1,24 @@
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#pragma once
-#include <vespa/document/select/valuenode.h>
-#include <vespa/searchlib/attribute/attributevector.h>
-
-namespace proton
-{
+#include <vespa/document/select/valuenodes.h>
+namespace search { class AttributeVector; }
+namespace proton {
class AttributeFieldValueNode : public document::select::FieldValueNode
{
- search::AttributeVector::SP _attribute;
+ using Context = document::select::Context;
+ std::shared_ptr<search::AttributeVector> _attribute;
public:
AttributeFieldValueNode(const vespalib::string& doctype,
const vespalib::string& field,
- const search::AttributeVector::SP &attribute);
-
- virtual std::unique_ptr<document::select::Value>
- getValue(const document::select::Context &context) const override;
+ const std::shared_ptr<search::AttributeVector> &attribute);
- virtual std::unique_ptr<document::select::Value>
- traceValue(const document::select::Context &context,
- std::ostream& out) const override;
-
- document::select::ValueNode::UP
- clone() const override
- {
- return wrapParens(new AttributeFieldValueNode(getDocType(),
- getFieldName(),
- _attribute));
- }
+ std::unique_ptr<document::select::Value> getValue(const Context &context) const override;
+ std::unique_ptr<document::select::Value> traceValue(const Context &context, std::ostream& out) const override;
+ document::select::ValueNode::UP clone() const override;
};
} // namespace proton
-
-
diff --git a/searchcore/src/vespa/searchcore/proton/common/cachedselect.cpp b/searchcore/src/vespa/searchcore/proton/common/cachedselect.cpp
index 861131642e4..9a15c257dcc 100644
--- a/searchcore/src/vespa/searchcore/proton/common/cachedselect.cpp
+++ b/searchcore/src/vespa/searchcore/proton/common/cachedselect.cpp
@@ -1,12 +1,11 @@
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include "cachedselect.h"
-#include <vespa/document/select/valuenode.h>
-#include <vespa/document/select/cloningvisitor.h>
#include "attributefieldvaluenode.h"
+#include "selectpruner.h"
#include <vespa/searchlib/attribute/iattributemanager.h>
+#include <vespa/searchlib/attribute/attributevector.h>
#include <vespa/document/select/parser.h>
-#include "selectpruner.h"
#include <vespa/log/log.h>
LOG_SETUP(".proton.common.cachedselect");
@@ -85,7 +84,7 @@ AttrVisitor::visitFieldValueNode(const FieldValueNode &expr)
_valueNode = expr.clone();
return;
}
- AttributeVector::SP av(ag->getSP());
+ std::shared_ptr<search::AttributeVector> av(ag->getSP());
if (av->getCollectionType() == CollectionType::SINGLE) {
++_svAttrs;
AttrMap::iterator it(_amap.find(name));
diff --git a/searchcore/src/vespa/searchcore/proton/common/selectpruner.cpp b/searchcore/src/vespa/searchcore/proton/common/selectpruner.cpp
index 001eb7d16f3..7e92be7507e 100644
--- a/searchcore/src/vespa/searchcore/proton/common/selectpruner.cpp
+++ b/searchcore/src/vespa/searchcore/proton/common/selectpruner.cpp
@@ -9,6 +9,7 @@
#include <vespa/document/select/branch.h>
#include <vespa/document/select/doctype.h>
#include <vespa/document/select/invalidconstant.h>
+#include <vespa/document/select/valuenodes.h>
#include <vespa/searchlib/attribute/iattributemanager.h>
using document::select::And;
diff --git a/searchcore/src/vespa/searchcore/proton/common/selectpruner.h b/searchcore/src/vespa/searchcore/proton/common/selectpruner.h
index 5d4bbc038b9..7b6c9954124 100644
--- a/searchcore/src/vespa/searchcore/proton/common/selectpruner.h
+++ b/searchcore/src/vespa/searchcore/proton/common/selectpruner.h
@@ -9,8 +9,9 @@
namespace search { class IAttributeManager; }
-namespace proton
-{
+namespace document { class DocumentTypeRepo; }
+
+namespace proton {
class SelectPrunerBase
{
@@ -50,100 +51,36 @@ public:
bool hasFields);
SelectPruner(const SelectPruner *rhs);
-
- virtual
- ~SelectPruner();
-
- uint32_t
- getFieldNodes() const
- {
- return _fieldNodes;
- }
-
- uint32_t
- getAttrFieldNodes() const
- {
- return _attrFieldNodes;
- }
-
- const document::select::ResultSet &
- getResultSet() const
- {
- return _resultSet;
- }
-
- bool
- isFalse() const;
-
- bool
- isTrue() const;
-
- bool
- isInvalid() const;
-
- bool
- isConst() const;
-
- void
- trace(std::ostream &t);
-
- void
- process(const document::select::Node &node);
+ virtual ~SelectPruner();
+
+ uint32_t getFieldNodes() const { return _fieldNodes; }
+ uint32_t getAttrFieldNodes() const { return _attrFieldNodes; }
+ const document::select::ResultSet & getResultSet() const { return _resultSet; }
+ bool isFalse() const;
+ bool isTrue() const;
+ bool isInvalid() const;
+ bool isConst() const;
+ void trace(std::ostream &t);
+ void process(const document::select::Node &node);
private:
- virtual void
- visitAndBranch(const document::select::And &expr) override;
-
- virtual void
- visitComparison(const document::select::Compare &expr) override;
-
- virtual void
- visitDocumentType(const document::select::DocType &expr) override;
-
- virtual void
- visitNotBranch(const document::select::Not &expr) override;
-
- virtual void
- visitOrBranch(const document::select::Or &expr) override;
-
- virtual void
- visitArithmeticValueNode(const document::select::ArithmeticValueNode &expr) override;
-
- virtual void
- visitFunctionValueNode(const document::select::FunctionValueNode &expr) override;
-
- virtual void
- visitFieldValueNode(const document::select::FieldValueNode &expr) override;
-
- void
- invertNode();
-
- const document::select::Operator &
- getOperator(const document::select::Operator &op);
-
- void
- addNodeCount(const SelectPruner &rhs);
-
- void
- setInvalidVal();
-
- void
- setInvalidConst();
-
- void
- setTernaryConst(bool val);
-
- void
- resolveTernaryConst(bool wantInverted);
-
- bool
- isInvalidVal() const;
-
- bool
- isNullVal() const;
-
- void
- swap(SelectPruner &rhs);
+ void visitAndBranch(const document::select::And &expr) override;
+ void visitComparison(const document::select::Compare &expr) override;
+ void visitDocumentType(const document::select::DocType &expr) override;
+ void visitNotBranch(const document::select::Not &expr) override;
+ void visitOrBranch(const document::select::Or &expr) override;
+ void visitArithmeticValueNode(const document::select::ArithmeticValueNode &expr) override;
+ void visitFunctionValueNode(const document::select::FunctionValueNode &expr) override;
+ void visitFieldValueNode(const document::select::FieldValueNode &expr) override;
+ void invertNode();
+ const document::select::Operator &getOperator(const document::select::Operator &op);
+ void addNodeCount(const SelectPruner &rhs);
+ void setInvalidVal();
+ void setInvalidConst();
+ void setTernaryConst(bool val);
+ void resolveTernaryConst(bool wantInverted);
+ bool isInvalidVal() const;
+ bool isNullVal() const;
+ void swap(SelectPruner &rhs);
};
} // namespace proton
-
diff --git a/storage/src/vespa/storage/persistence/fieldvisitor.cpp b/storage/src/vespa/storage/persistence/fieldvisitor.cpp
index e67d15d4e91..6657a73543e 100644
--- a/storage/src/vespa/storage/persistence/fieldvisitor.cpp
+++ b/storage/src/vespa/storage/persistence/fieldvisitor.cpp
@@ -1,6 +1,8 @@
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
// @author Vegard Sjonfjell
-#include <vespa/storage/persistence/fieldvisitor.h>
+
+#include "fieldvisitor.h"
+#include <vespa/document/select/valuenodes.h>
namespace storage {