diff options
author | Nick Zolnierz <nicholas.zolnierz@mongodb.com> | 2018-02-26 16:33:48 -0500 |
---|---|---|
committer | Nick Zolnierz <nicholas.zolnierz@mongodb.com> | 2018-02-27 17:12:05 -0500 |
commit | ad0e38e91dea6b1e49807c6dc0e50197917d2804 (patch) | |
tree | 9a36b826dbb7f45c7706861206ac5f524078594d /src/mongo/db/pipeline/expression.cpp | |
parent | 9be3128cbba97456dd70647174a011c0a85ed88b (diff) | |
download | mongo-3.6.3.tar.gz |
SERVER-33169: Add string to date conversions to $convert3.6.3
Diffstat (limited to 'src/mongo/db/pipeline/expression.cpp')
-rw-r--r-- | src/mongo/db/pipeline/expression.cpp | 186 |
1 files changed, 109 insertions, 77 deletions
diff --git a/src/mongo/db/pipeline/expression.cpp b/src/mongo/db/pipeline/expression.cpp index 318933b3c20..a8d002e0c35 100644 --- a/src/mongo/db/pipeline/expression.cpp +++ b/src/mongo/db/pipeline/expression.cpp @@ -4849,22 +4849,24 @@ namespace { */ class ConversionTable { public: - using ConversionFunc = std::function<Value(Value)>; + using ConversionFunc = + std::function<Value(const boost::intrusive_ptr<ExpressionContext>&, Value)>; ConversionTable() { // // Conversions from NumberDouble // table[BSONType::NumberDouble][BSONType::NumberDouble] = &performIdentityConversion; - table[BSONType::NumberDouble][BSONType::Bool] = [](Value inputValue) { - return Value(inputValue.coerceToBool()); - }; + table[BSONType::NumberDouble] + [BSONType::Bool] = [](const boost::intrusive_ptr<ExpressionContext>& expCtx, + Value inputValue) { return Value(inputValue.coerceToBool()); }; table[BSONType::NumberDouble][BSONType::Date] = &performCastNumberToDate; table[BSONType::NumberDouble][BSONType::NumberInt] = &performCastDoubleToInt; table[BSONType::NumberDouble][BSONType::NumberLong] = &performCastDoubleToLong; - table[BSONType::NumberDouble][BSONType::NumberDecimal] = [](Value inputValue) { - return Value(inputValue.coerceToDecimal()); - }; + table[BSONType::NumberDouble][BSONType::NumberDecimal] = + [](const boost::intrusive_ptr<ExpressionContext>& expCtx, Value inputValue) { + return Value(inputValue.coerceToDecimal()); + }; // // Conversions from String @@ -4872,7 +4874,14 @@ public: table[BSONType::String][BSONType::NumberDouble] = &parseStringToNumber<double, 0>; table[BSONType::String][BSONType::String] = &performIdentityConversion; table[BSONType::String][BSONType::jstOID] = &parseStringToOID; - table[BSONType::String][BSONType::Bool] = [](Value inputValue) { return Value(true); }; + table[BSONType::String] + [BSONType::Bool] = [](const boost::intrusive_ptr<ExpressionContext>& expCtx, + Value inputValue) { return Value(true); }; + table[BSONType::String][BSONType::Date] = []( + const boost::intrusive_ptr<ExpressionContext>& expCtx, Value inputValue) { + return Value(expCtx->timeZoneDatabase->fromString(inputValue.getStringData(), + mongo::TimeZoneDatabase::utcZone())); + }; table[BSONType::String][BSONType::NumberInt] = &parseStringToNumber<int, 10>; table[BSONType::String][BSONType::NumberLong] = &parseStringToNumber<long long, 10>; table[BSONType::String][BSONType::NumberDecimal] = &parseStringToNumber<Decimal128, 0>; @@ -4880,92 +4889,107 @@ public: // // Conversions from jstOID // - table[BSONType::jstOID][BSONType::Date] = [](Value inputValue) { - return Value(inputValue.getOid().asDateT()); - }; + table[BSONType::jstOID][BSONType::Date] = + [](const boost::intrusive_ptr<ExpressionContext>& expCtx, Value inputValue) { + return Value(inputValue.getOid().asDateT()); + }; // // Conversions from Bool // - table[BSONType::Bool][BSONType::NumberDouble] = [](Value inputValue) { - return inputValue.getBool() ? Value(1.0) : Value(0.0); - }; + table[BSONType::Bool][BSONType::NumberDouble] = + [](const boost::intrusive_ptr<ExpressionContext>& expCtx, Value inputValue) { + return inputValue.getBool() ? Value(1.0) : Value(0.0); + }; table[BSONType::Bool][BSONType::Bool] = &performIdentityConversion; - table[BSONType::Bool][BSONType::NumberInt] = [](Value inputValue) { - return inputValue.getBool() ? Value(int{1}) : Value(int{0}); - }; - table[BSONType::Bool][BSONType::NumberLong] = [](Value inputValue) { - return inputValue.getBool() ? Value(1LL) : Value(0LL); - }; - table[BSONType::Bool][BSONType::NumberDecimal] = [](Value inputValue) { - return inputValue.getBool() ? Value(Decimal128(1)) : Value(Decimal128(0)); - }; + table[BSONType::Bool][BSONType::NumberInt] = + [](const boost::intrusive_ptr<ExpressionContext>& expCtx, Value inputValue) { + return inputValue.getBool() ? Value(int{1}) : Value(int{0}); + }; + table[BSONType::Bool][BSONType::NumberLong] = + [](const boost::intrusive_ptr<ExpressionContext>& expCtx, Value inputValue) { + return inputValue.getBool() ? Value(1LL) : Value(0LL); + }; + table[BSONType::Bool][BSONType::NumberDecimal] = + [](const boost::intrusive_ptr<ExpressionContext>& expCtx, Value inputValue) { + return inputValue.getBool() ? Value(Decimal128(1)) : Value(Decimal128(0)); + }; // // Conversions from Date // - table[BSONType::Date][BSONType::NumberDouble] = [](Value inputValue) { - return Value(static_cast<double>(inputValue.getDate().toMillisSinceEpoch())); - }; - table[BSONType::Date][BSONType::Bool] = [](Value inputValue) { - return Value(inputValue.coerceToBool()); - }; + table[BSONType::Date][BSONType::NumberDouble] = + [](const boost::intrusive_ptr<ExpressionContext>& expCtx, Value inputValue) { + return Value(static_cast<double>(inputValue.getDate().toMillisSinceEpoch())); + }; + table[BSONType::Date] + [BSONType::Bool] = [](const boost::intrusive_ptr<ExpressionContext>& expCtx, + Value inputValue) { return Value(inputValue.coerceToBool()); }; table[BSONType::Date][BSONType::Date] = &performIdentityConversion; - table[BSONType::Date][BSONType::NumberLong] = [](Value inputValue) { - return Value(inputValue.getDate().toMillisSinceEpoch()); - }; - table[BSONType::Date][BSONType::NumberDecimal] = [](Value inputValue) { - return Value( - Decimal128(static_cast<int64_t>(inputValue.getDate().toMillisSinceEpoch()))); - }; + table[BSONType::Date][BSONType::NumberLong] = + [](const boost::intrusive_ptr<ExpressionContext>& expCtx, Value inputValue) { + return Value(inputValue.getDate().toMillisSinceEpoch()); + }; + table[BSONType::Date][BSONType::NumberDecimal] = + [](const boost::intrusive_ptr<ExpressionContext>& expCtx, Value inputValue) { + return Value( + Decimal128(static_cast<int64_t>(inputValue.getDate().toMillisSinceEpoch()))); + }; // // Conversions from NumberInt // - table[BSONType::NumberInt][BSONType::NumberDouble] = [](Value inputValue) { - return Value(inputValue.coerceToDouble()); - }; - table[BSONType::NumberInt][BSONType::Bool] = [](Value inputValue) { - return Value(inputValue.coerceToBool()); - }; + table[BSONType::NumberInt][BSONType::NumberDouble] = + [](const boost::intrusive_ptr<ExpressionContext>& expCtx, Value inputValue) { + return Value(inputValue.coerceToDouble()); + }; + table[BSONType::NumberInt] + [BSONType::Bool] = [](const boost::intrusive_ptr<ExpressionContext>& expCtx, + Value inputValue) { return Value(inputValue.coerceToBool()); }; table[BSONType::NumberInt][BSONType::NumberInt] = &performIdentityConversion; - table[BSONType::NumberInt][BSONType::NumberLong] = [](Value inputValue) { - return Value(static_cast<long long>(inputValue.getInt())); - }; - table[BSONType::NumberInt][BSONType::NumberDecimal] = [](Value inputValue) { - return Value(inputValue.coerceToDecimal()); - }; + table[BSONType::NumberInt][BSONType::NumberLong] = + [](const boost::intrusive_ptr<ExpressionContext>& expCtx, Value inputValue) { + return Value(static_cast<long long>(inputValue.getInt())); + }; + table[BSONType::NumberInt][BSONType::NumberDecimal] = + [](const boost::intrusive_ptr<ExpressionContext>& expCtx, Value inputValue) { + return Value(inputValue.coerceToDecimal()); + }; // // Conversions from NumberLong // - table[BSONType::NumberLong][BSONType::NumberDouble] = [](Value inputValue) { - return Value(inputValue.coerceToDouble()); - }; - table[BSONType::NumberLong][BSONType::Bool] = [](Value inputValue) { - return Value(inputValue.coerceToBool()); - }; + table[BSONType::NumberLong][BSONType::NumberDouble] = + [](const boost::intrusive_ptr<ExpressionContext>& expCtx, Value inputValue) { + return Value(inputValue.coerceToDouble()); + }; + table[BSONType::NumberLong] + [BSONType::Bool] = [](const boost::intrusive_ptr<ExpressionContext>& expCtx, + Value inputValue) { return Value(inputValue.coerceToBool()); }; table[BSONType::NumberLong][BSONType::Date] = &performCastNumberToDate; table[BSONType::NumberLong][BSONType::NumberInt] = &performCastLongToInt; table[BSONType::NumberLong][BSONType::NumberLong] = &performIdentityConversion; - table[BSONType::NumberLong][BSONType::NumberDecimal] = [](Value inputValue) { - return Value(inputValue.coerceToDecimal()); - }; + table[BSONType::NumberLong][BSONType::NumberDecimal] = + [](const boost::intrusive_ptr<ExpressionContext>& expCtx, Value inputValue) { + return Value(inputValue.coerceToDecimal()); + }; // // Conversions from NumberDecimal // table[BSONType::NumberDecimal][BSONType::NumberDouble] = &performCastDecimalToDouble; - table[BSONType::NumberDecimal][BSONType::Bool] = [](Value inputValue) { - return Value(inputValue.coerceToBool()); - }; + table[BSONType::NumberDecimal] + [BSONType::Bool] = [](const boost::intrusive_ptr<ExpressionContext>& expCtx, + Value inputValue) { return Value(inputValue.coerceToBool()); }; table[BSONType::NumberDecimal][BSONType::Date] = &performCastNumberToDate; - table[BSONType::NumberDecimal][BSONType::NumberInt] = [](Value inputValue) { - return performCastDecimalToInt(BSONType::NumberInt, inputValue); - }; - table[BSONType::NumberDecimal][BSONType::NumberLong] = [](Value inputValue) { - return performCastDecimalToInt(BSONType::NumberLong, inputValue); - }; + table[BSONType::NumberDecimal][BSONType::NumberInt] = + [](const boost::intrusive_ptr<ExpressionContext>& expCtx, Value inputValue) { + return performCastDecimalToInt(BSONType::NumberInt, inputValue); + }; + table[BSONType::NumberDecimal][BSONType::NumberLong] = + [](const boost::intrusive_ptr<ExpressionContext>& expCtx, Value inputValue) { + return performCastDecimalToInt(BSONType::NumberLong, inputValue); + }; table[BSONType::NumberDecimal][BSONType::NumberDecimal] = &performIdentityConversion; } @@ -4995,7 +5019,8 @@ private: std::isfinite(inputDouble)); } - static Value performCastDoubleToInt(Value inputValue) { + static Value performCastDoubleToInt(const boost::intrusive_ptr<ExpressionContext>& expCtx, + Value inputValue) { double inputDouble = inputValue.getDouble(); validateDoubleValueIsFinite(inputDouble); @@ -5009,7 +5034,8 @@ private: return Value(static_cast<int>(inputDouble)); } - static Value performCastDoubleToLong(Value inputValue) { + static Value performCastDoubleToLong(const boost::intrusive_ptr<ExpressionContext>& expCtx, + Value inputValue) { double inputDouble = inputValue.getDouble(); validateDoubleValueIsFinite(inputDouble); @@ -5064,7 +5090,8 @@ private: return result; } - static Value performCastDecimalToDouble(Value inputValue) { + static Value performCastDecimalToDouble(const boost::intrusive_ptr<ExpressionContext>& expCtx, + Value inputValue) { Decimal128 inputDecimal = inputValue.getDecimal(); std::uint32_t signalingFlags = Decimal128::SignalingFlag::kNoFlag; @@ -5081,7 +5108,8 @@ private: return Value(result); } - static Value performCastLongToInt(Value inputValue) { + static Value performCastLongToInt(const boost::intrusive_ptr<ExpressionContext>& expCtx, + Value inputValue) { long long longValue = inputValue.getLong(); uassert(ErrorCodes::ConversionFailure, @@ -5093,7 +5121,8 @@ private: return Value(static_cast<int>(longValue)); } - static Value performCastNumberToDate(Value inputValue) { + static Value performCastNumberToDate(const boost::intrusive_ptr<ExpressionContext>& expCtx, + Value inputValue) { long long millisSinceEpoch; switch (inputValue.getType()) { @@ -5101,7 +5130,7 @@ private: millisSinceEpoch = inputValue.getLong(); break; case BSONType::NumberDouble: - millisSinceEpoch = performCastDoubleToLong(inputValue).getLong(); + millisSinceEpoch = performCastDoubleToLong(expCtx, inputValue).getLong(); break; case BSONType::NumberDecimal: millisSinceEpoch = @@ -5115,7 +5144,8 @@ private: } template <class targetType, int base> - static Value parseStringToNumber(Value inputValue) { + static Value parseStringToNumber(const boost::intrusive_ptr<ExpressionContext>& expCtx, + Value inputValue) { auto stringValue = inputValue.getStringData(); targetType result; @@ -5137,7 +5167,8 @@ private: return Value(result); } - static Value parseStringToOID(Value inputValue) { + static Value parseStringToOID(const boost::intrusive_ptr<ExpressionContext>& expCtx, + Value inputValue) { try { return Value(OID::createFromString(inputValue.getStringData())); } catch (const DBException& ex) { @@ -5150,7 +5181,8 @@ private: } } - static Value performIdentityConversion(Value inputValue) { + static Value performIdentityConversion(const boost::intrusive_ptr<ExpressionContext>& expCtx, + Value inputValue) { return inputValue; } }; @@ -5318,9 +5350,9 @@ BSONType ExpressionConvert::computeTargetType(Value targetTypeName) const { Value ExpressionConvert::performConversion(BSONType targetType, Value inputValue) const { invariant(!inputValue.nullish()); - static ConversionTable table; + static const ConversionTable table; BSONType inputType = inputValue.getType(); - return table.findConversionFunc(inputType, targetType)(inputValue); + return table.findConversionFunc(inputType, targetType)(getExpressionContext(), inputValue); } } // namespace mongo |