From 5e504b81ab84274db75f868cf1559cee015beddd Mon Sep 17 00:00:00 2001 From: David Storch Date: Fri, 1 Jul 2016 15:35:39 -0400 Subject: SERVER-24508 DocumentComparator and ValueComparator - Changes the Document/Value library to require comparisons to be made in the context of a comparator object. This is prep work for full collation support in the aggregation system. - Adds injectExpressionContext() to propagate the ExpressionContext containing the comparator object to all DocumentSource, Accumulator, and Expression instances involved in the Pipeline. --- src/mongo/db/pipeline/value_comparator.h | 177 +++++++++++++++++++++++++++++++ 1 file changed, 177 insertions(+) create mode 100644 src/mongo/db/pipeline/value_comparator.h (limited to 'src/mongo/db/pipeline/value_comparator.h') diff --git a/src/mongo/db/pipeline/value_comparator.h b/src/mongo/db/pipeline/value_comparator.h new file mode 100644 index 00000000000..cbf423ccf92 --- /dev/null +++ b/src/mongo/db/pipeline/value_comparator.h @@ -0,0 +1,177 @@ +/** + * Copyright (C) 2016 MongoDB Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the GNU Affero General Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + */ + +#pragma once + +#include +#include +#include +#include + +#include "mongo/base/string_data.h" +#include "mongo/db/pipeline/value.h" + +namespace mongo { + +class ValueComparator { +public: + /** + * Functor compatible for use with unordered STL containers. + * + * TODO SERVER-23349: Remove the no-arguments constructor. + */ + class EqualTo { + public: + EqualTo() = default; + + explicit EqualTo(const ValueComparator* comparator) : _comparator(comparator) {} + + bool operator()(const Value& lhs, const Value& rhs) const { + return _comparator ? _comparator->compare(lhs, rhs) == 0 + : ValueComparator().compare(lhs, rhs) == 0; + } + + private: + const ValueComparator* _comparator = nullptr; + }; + + /** + * Functor compatible for use with ordered STL containers. + */ + class LessThan { + public: + explicit LessThan(const ValueComparator* comparator) : _comparator(comparator) {} + + bool operator()(const Value& lhs, const Value& rhs) const { + return _comparator->compare(lhs, rhs) < 0; + } + + private: + const ValueComparator* _comparator; + }; + + /** + * Constructs a value comparator with simple comparison semantics. + */ + ValueComparator() = default; + + /** + * Constructs a value comparator with special string comparison semantics. + */ + ValueComparator(const StringData::ComparatorInterface* stringComparator) + : _stringComparator(stringComparator) {} + + /** + * Returns <0 if 'lhs' is less than 'rhs', 0 if 'lhs' is equal to 'rhs', and >0 if 'lhs' is + * greater than 'rhs'. + */ + int compare(const Value& lhs, const Value& rhs) const { + return Value::compare(lhs, rhs, _stringComparator); + } + + /** + * Evaluates a deferred comparison object that was generated by invoking one of the comparison + * operators on the Value class. + */ + bool evaluate(Value::DeferredComparison deferredComparison) const; + + /** + * Returns a function object which computes whether one Value is equal to another under this + * comparator. This comparator must outlive the returned function object. + */ + EqualTo getEqualTo() const { + return EqualTo(this); + } + + /** + * Returns a function object which computes whether one Value is less than another under this + * comparator. This comparator must outlive the returned function object. + */ + LessThan getLessThan() const { + return LessThan(this); + } + + /** + * Construct an empty ordered set of Value whose ordering and equivalence classes are given by + * this comparator. This comparator must outlive the returned set. + */ + std::set makeOrderedValueSet() const { + return std::set(LessThan(this)); + } + + /** + * Construct an empty unordered set of Value whose equivalence classes are given by this + * comparator. This comparator must outlive the returned set. + * + * TODO SERVER-23990: Make Value::Hash use the collation. The returned set won't be correctly + * collation-aware until this work is done. + */ + std::unordered_set makeUnorderedValueSet() const { + return std::unordered_set(0, Value::Hash(), EqualTo(this)); + } + + /** + * Construct an empty ordered map from Value to type T whose ordering and equivalence classes + * are given by this comparator. This comparator must outlive the returned set. + */ + template + std::map makeOrderedValueMap() const { + return std::map(LessThan(this)); + } + + /** + * Construct an empty unordered map from Value to type T whose equivalence classes are given by + * this comparator. This comparator must outlive the returned set. + * + * TODO SERVER-23990: Make Value::Hash use the collation. The returned map won't be correctly + * collation-aware until this work is done. + */ + template + std::unordered_map makeUnorderedValueMap() const { + return std::unordered_map(0, Value::Hash(), EqualTo(this)); + } + +private: + const StringData::ComparatorInterface* _stringComparator = nullptr; +}; + +// +// Type aliases for sets and maps of Value for use by clients of the Document/Value library. +// + +using ValueSet = std::set; + +using ValueUnorderedSet = std::unordered_set; + +template +using ValueMap = std::map; + +template +using ValueUnorderedMap = std::unordered_map; + +} // namespace mongo -- cgit v1.2.1