diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mongo/db/exec/sbe/expressions/expression.cpp | 12 | ||||
-rw-r--r-- | src/mongo/db/exec/sbe/expressions/sbe_date_expression_accepting_timezone_test.cpp | 512 | ||||
-rw-r--r-- | src/mongo/db/exec/sbe/vm/datetime.cpp | 252 | ||||
-rw-r--r-- | src/mongo/db/exec/sbe/vm/vm.cpp | 173 | ||||
-rw-r--r-- | src/mongo/db/exec/sbe/vm/vm.h | 109 | ||||
-rw-r--r-- | src/mongo/db/pipeline/expression.h | 27 | ||||
-rw-r--r-- | src/mongo/db/pipeline/expression_bm_fixture.cpp | 370 | ||||
-rw-r--r-- | src/mongo/db/pipeline/expression_bm_fixture.h | 324 | ||||
-rw-r--r-- | src/mongo/db/query/sbe_stage_builder_expression.cpp | 18 |
9 files changed, 1775 insertions, 22 deletions
diff --git a/src/mongo/db/exec/sbe/expressions/expression.cpp b/src/mongo/db/exec/sbe/expressions/expression.cpp index 37e7374b298..6288aba388f 100644 --- a/src/mongo/db/exec/sbe/expressions/expression.cpp +++ b/src/mongo/db/exec/sbe/expressions/expression.cpp @@ -602,6 +602,18 @@ static stdx::unordered_map<std::string, BuiltinFn> kBuiltinFunctions = { {"dayOfWeek", BuiltinFn{[](size_t n) { return n == 2 || n == 3; }, vm::Builtin::dayOfWeek, false}}, {"year", BuiltinFn{[](size_t n) { return n == 2 || n == 3; }, vm::Builtin::year, false}}, + {"month", BuiltinFn{[](size_t n) { return n == 2 || n == 3; }, vm::Builtin::month, false}}, + {"hour", BuiltinFn{[](size_t n) { return n == 2 || n == 3; }, vm::Builtin::hour, false}}, + {"minute", BuiltinFn{[](size_t n) { return n == 2 || n == 3; }, vm::Builtin::minute, false}}, + {"second", BuiltinFn{[](size_t n) { return n == 2 || n == 3; }, vm::Builtin::second, false}}, + {"millisecond", + BuiltinFn{[](size_t n) { return n == 2 || n == 3; }, vm::Builtin::millisecond, false}}, + {"week", BuiltinFn{[](size_t n) { return n == 2 || n == 3; }, vm::Builtin::week, false}}, + {"isoWeekYear", + BuiltinFn{[](size_t n) { return n == 2 || n == 3; }, vm::Builtin::isoWeekYear, false}}, + {"isoDayOfWeek", + BuiltinFn{[](size_t n) { return n == 2 || n == 3; }, vm::Builtin::isoDayOfWeek, false}}, + {"isoWeek", BuiltinFn{[](size_t n) { return n == 2 || n == 3; }, vm::Builtin::isoWeek, false}}, {"datePartsWeekYear", BuiltinFn{[](size_t n) { return n == 9; }, vm::Builtin::datePartsWeekYear, false}}, {"dateToString", BuiltinFn{[](size_t n) { return n == 4; }, vm::Builtin::dateToString, false}}, diff --git a/src/mongo/db/exec/sbe/expressions/sbe_date_expression_accepting_timezone_test.cpp b/src/mongo/db/exec/sbe/expressions/sbe_date_expression_accepting_timezone_test.cpp index 84ad2d3cee0..c49c7799bc6 100644 --- a/src/mongo/db/exec/sbe/expressions/sbe_date_expression_accepting_timezone_test.cpp +++ b/src/mongo/db/exec/sbe/expressions/sbe_date_expression_accepting_timezone_test.cpp @@ -308,4 +308,516 @@ TEST_F(SBEDateExpressionAcceptingTimezoneTest, BasicYear) { runAndAssertNothing(compiledYear.get()); } +TEST_F(SBEDateExpressionAcceptingTimezoneTest, BasicMonth) { + value::OwnedValueAccessor timezoneDBAccessor; + auto timezoneDBSlot = bindAccessor(&timezoneDBAccessor); + value::OwnedValueAccessor dateAccessor; + auto dateSlot = bindAccessor(&dateAccessor); + value::OwnedValueAccessor timezoneAccessor; + auto timezoneSlot = bindAccessor(&timezoneAccessor); + + auto monthExpr = sbe::makeE<sbe::EFunction>("month", + sbe::makeEs(makeE<EVariable>(dateSlot), + makeE<EVariable>(timezoneDBSlot), + makeE<EVariable>(timezoneSlot))); + auto compiledMonth = compileExpression(*monthExpr); + + // Test $month returns the correct value. + auto tzdb = std::make_unique<TimeZoneDatabase>(); + timezoneDBAccessor.reset( + false, value::TypeTags::timeZoneDB, value::bitcastFrom<TimeZoneDatabase*>(tzdb.get())); + dateAccessor.reset( + value::TypeTags::Date, + value::bitcastFrom<int64_t>( + kDefaultTimeZone.createFromDateParts(1996, 7, 18, 10, 10, 10, 0).toMillisSinceEpoch())); + auto [timezoneTag, timezoneVal] = value::makeNewString("UTC"); + timezoneAccessor.reset(timezoneTag, timezoneVal); + runAndAssertExpression(compiledMonth.get(), 7); + + // Test $month returns Nothing with invalid date. + dateAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(42)); + runAndAssertNothing(compiledMonth.get()); + + // Test $month returns Nothing with invalid timezone. + dateAccessor.reset(value::TypeTags::Date, value::bitcastFrom<int64_t>(21929999)); + timezoneAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(42)); + runAndAssertNothing(compiledMonth.get()); + + // Test $month returns Nothing with invalid timezoneDB. + timezoneAccessor.reset(timezoneTag, timezoneVal); + timezoneDBAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(42)); + runAndAssertNothing(compiledMonth.get()); + + // Test $month with constant timezone + value::OwnedValueAccessor timezoneObjAccessor; + auto timezoneObjSlot = bindAccessor(&timezoneObjAccessor); + monthExpr = sbe::makeE<sbe::EFunction>( + "month", sbe::makeEs(makeE<EVariable>(dateSlot), makeE<EVariable>(timezoneObjSlot))); + compiledMonth = compileExpression(*monthExpr); + + dateAccessor.reset( + value::TypeTags::Date, + value::bitcastFrom<int64_t>( + kDefaultTimeZone.createFromDateParts(1996, 7, 18, 10, 10, 10, 0).toMillisSinceEpoch())); + auto timezone = tzdb->utcZone(); + timezoneObjAccessor.reset( + false, value::TypeTags::timeZone, value::bitcastFrom<TimeZone*>(&timezone)); + runAndAssertExpression(compiledMonth.get(), 7); +} + +TEST_F(SBEDateExpressionAcceptingTimezoneTest, BasicHour) { + value::OwnedValueAccessor timezoneDBAccessor; + auto timezoneDBSlot = bindAccessor(&timezoneDBAccessor); + value::OwnedValueAccessor dateAccessor; + auto dateSlot = bindAccessor(&dateAccessor); + value::OwnedValueAccessor timezoneAccessor; + auto timezoneSlot = bindAccessor(&timezoneAccessor); + + auto hourExpr = sbe::makeE<sbe::EFunction>("hour", + sbe::makeEs(makeE<EVariable>(dateSlot), + makeE<EVariable>(timezoneDBSlot), + makeE<EVariable>(timezoneSlot))); + auto compiledHour = compileExpression(*hourExpr); + + // Test $hour returns the correct value. + auto tzdb = std::make_unique<TimeZoneDatabase>(); + timezoneDBAccessor.reset( + false, value::TypeTags::timeZoneDB, value::bitcastFrom<TimeZoneDatabase*>(tzdb.get())); + dateAccessor.reset(value::TypeTags::Date, + value::bitcastFrom<int64_t>( + kDefaultTimeZone.createFromDateParts(1996, 7, 18, 10, 11, 12, 123) + .toMillisSinceEpoch())); + auto [timezoneTag, timezoneVal] = value::makeNewString("UTC"); + timezoneAccessor.reset(timezoneTag, timezoneVal); + runAndAssertExpression(compiledHour.get(), 10); + + // Test $hour returns Nothing with invalid date. + dateAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(42)); + runAndAssertNothing(compiledHour.get()); + + // Test $hour returns Nothing with invalid timezone. + dateAccessor.reset(value::TypeTags::Date, value::bitcastFrom<int64_t>(21929999)); + timezoneAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(42)); + runAndAssertNothing(compiledHour.get()); + + // Test $hour returns Nothing with invalid timezoneDB. + timezoneAccessor.reset(timezoneTag, timezoneVal); + timezoneDBAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(42)); + runAndAssertNothing(compiledHour.get()); + + // Test $hour with constant timezone + value::OwnedValueAccessor timezoneObjAccessor; + auto timezoneObjSlot = bindAccessor(&timezoneObjAccessor); + hourExpr = sbe::makeE<sbe::EFunction>( + "hour", sbe::makeEs(makeE<EVariable>(dateSlot), makeE<EVariable>(timezoneObjSlot))); + compiledHour = compileExpression(*hourExpr); + + dateAccessor.reset(value::TypeTags::Date, + value::bitcastFrom<int64_t>( + kDefaultTimeZone.createFromDateParts(1996, 7, 18, 10, 11, 12, 123) + .toMillisSinceEpoch())); + auto timezone = tzdb->utcZone(); + timezoneObjAccessor.reset( + false, value::TypeTags::timeZone, value::bitcastFrom<TimeZone*>(&timezone)); + runAndAssertExpression(compiledHour.get(), 10); +} + +TEST_F(SBEDateExpressionAcceptingTimezoneTest, BasicMinute) { + value::OwnedValueAccessor timezoneDBAccessor; + auto timezoneDBSlot = bindAccessor(&timezoneDBAccessor); + value::OwnedValueAccessor dateAccessor; + auto dateSlot = bindAccessor(&dateAccessor); + value::OwnedValueAccessor timezoneAccessor; + auto timezoneSlot = bindAccessor(&timezoneAccessor); + + auto minuteExpr = sbe::makeE<sbe::EFunction>("minute", + sbe::makeEs(makeE<EVariable>(dateSlot), + makeE<EVariable>(timezoneDBSlot), + makeE<EVariable>(timezoneSlot))); + auto compiledMinute = compileExpression(*minuteExpr); + + // Test $minute returns the correct value. + auto tzdb = std::make_unique<TimeZoneDatabase>(); + timezoneDBAccessor.reset( + false, value::TypeTags::timeZoneDB, value::bitcastFrom<TimeZoneDatabase*>(tzdb.get())); + dateAccessor.reset(value::TypeTags::Date, + value::bitcastFrom<int64_t>( + kDefaultTimeZone.createFromDateParts(1996, 7, 18, 10, 11, 12, 123) + .toMillisSinceEpoch())); + auto [timezoneTag, timezoneVal] = value::makeNewString("UTC"); + timezoneAccessor.reset(timezoneTag, timezoneVal); + runAndAssertExpression(compiledMinute.get(), 11); + + // Test $minute returns Nothing with invalid date. + dateAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(42)); + runAndAssertNothing(compiledMinute.get()); + + // Test $minute returns Nothing with invalid timezone. + dateAccessor.reset(value::TypeTags::Date, value::bitcastFrom<int64_t>(21929999)); + timezoneAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(42)); + runAndAssertNothing(compiledMinute.get()); + + // Test $minute returns Nothing with invalid timezoneDB. + timezoneAccessor.reset(timezoneTag, timezoneVal); + timezoneDBAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(42)); + runAndAssertNothing(compiledMinute.get()); + + // Test $minute with constant timezone + value::OwnedValueAccessor timezoneObjAccessor; + auto timezoneObjSlot = bindAccessor(&timezoneObjAccessor); + minuteExpr = sbe::makeE<sbe::EFunction>( + "minute", sbe::makeEs(makeE<EVariable>(dateSlot), makeE<EVariable>(timezoneObjSlot))); + compiledMinute = compileExpression(*minuteExpr); + + dateAccessor.reset(value::TypeTags::Date, + value::bitcastFrom<int64_t>( + kDefaultTimeZone.createFromDateParts(1996, 7, 18, 10, 11, 12, 123) + .toMillisSinceEpoch())); + auto timezone = tzdb->utcZone(); + timezoneObjAccessor.reset( + false, value::TypeTags::timeZone, value::bitcastFrom<TimeZone*>(&timezone)); + runAndAssertExpression(compiledMinute.get(), 11); +} + +TEST_F(SBEDateExpressionAcceptingTimezoneTest, BasicSecond) { + value::OwnedValueAccessor timezoneDBAccessor; + auto timezoneDBSlot = bindAccessor(&timezoneDBAccessor); + value::OwnedValueAccessor dateAccessor; + auto dateSlot = bindAccessor(&dateAccessor); + value::OwnedValueAccessor timezoneAccessor; + auto timezoneSlot = bindAccessor(&timezoneAccessor); + + auto secondExpr = sbe::makeE<sbe::EFunction>("second", + sbe::makeEs(makeE<EVariable>(dateSlot), + makeE<EVariable>(timezoneDBSlot), + makeE<EVariable>(timezoneSlot))); + auto compiledSecond = compileExpression(*secondExpr); + + // Test $second returns the correct value. + auto tzdb = std::make_unique<TimeZoneDatabase>(); + timezoneDBAccessor.reset( + false, value::TypeTags::timeZoneDB, value::bitcastFrom<TimeZoneDatabase*>(tzdb.get())); + dateAccessor.reset(value::TypeTags::Date, + value::bitcastFrom<int64_t>( + kDefaultTimeZone.createFromDateParts(1996, 7, 18, 10, 11, 12, 123) + .toMillisSinceEpoch())); + auto [timezoneTag, timezoneVal] = value::makeNewString("UTC"); + timezoneAccessor.reset(timezoneTag, timezoneVal); + runAndAssertExpression(compiledSecond.get(), 12); + + // Test $second returns Nothing with invalid date. + dateAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(42)); + runAndAssertNothing(compiledSecond.get()); + + // Test $second returns Nothing with invalid timezone. + dateAccessor.reset(value::TypeTags::Date, value::bitcastFrom<int64_t>(21929999)); + timezoneAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(42)); + runAndAssertNothing(compiledSecond.get()); + + // Test $second returns Nothing with invalid timezoneDB. + timezoneAccessor.reset(timezoneTag, timezoneVal); + timezoneDBAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(42)); + runAndAssertNothing(compiledSecond.get()); + + // Test $second with constant timezone + value::OwnedValueAccessor timezoneObjAccessor; + auto timezoneObjSlot = bindAccessor(&timezoneObjAccessor); + secondExpr = sbe::makeE<sbe::EFunction>( + "second", sbe::makeEs(makeE<EVariable>(dateSlot), makeE<EVariable>(timezoneObjSlot))); + compiledSecond = compileExpression(*secondExpr); + + dateAccessor.reset(value::TypeTags::Date, + value::bitcastFrom<int64_t>( + kDefaultTimeZone.createFromDateParts(1996, 7, 18, 10, 11, 12, 123) + .toMillisSinceEpoch())); + auto timezone = tzdb->utcZone(); + timezoneObjAccessor.reset( + false, value::TypeTags::timeZone, value::bitcastFrom<TimeZone*>(&timezone)); + runAndAssertExpression(compiledSecond.get(), 12); +} + +TEST_F(SBEDateExpressionAcceptingTimezoneTest, BasicMillisecond) { + value::OwnedValueAccessor timezoneDBAccessor; + auto timezoneDBSlot = bindAccessor(&timezoneDBAccessor); + value::OwnedValueAccessor dateAccessor; + auto dateSlot = bindAccessor(&dateAccessor); + value::OwnedValueAccessor timezoneAccessor; + auto timezoneSlot = bindAccessor(&timezoneAccessor); + + auto millisecondExpr = sbe::makeE<sbe::EFunction>("millisecond", + sbe::makeEs(makeE<EVariable>(dateSlot), + makeE<EVariable>(timezoneDBSlot), + makeE<EVariable>(timezoneSlot))); + auto compiledMillisecond = compileExpression(*millisecondExpr); + + // Test $millisecond returns the correct value. + auto tzdb = std::make_unique<TimeZoneDatabase>(); + timezoneDBAccessor.reset( + false, value::TypeTags::timeZoneDB, value::bitcastFrom<TimeZoneDatabase*>(tzdb.get())); + dateAccessor.reset(value::TypeTags::Date, + value::bitcastFrom<int64_t>( + kDefaultTimeZone.createFromDateParts(1996, 7, 18, 10, 11, 12, 123) + .toMillisSinceEpoch())); + auto [timezoneTag, timezoneVal] = value::makeNewString("UTC"); + timezoneAccessor.reset(timezoneTag, timezoneVal); + runAndAssertExpression(compiledMillisecond.get(), 123); + + // Test $millisecond returns Nothing with invalid date. + dateAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(42)); + runAndAssertNothing(compiledMillisecond.get()); + + // Test $millisecond returns Nothing with invalid timezone. + dateAccessor.reset(value::TypeTags::Date, value::bitcastFrom<int64_t>(21929999)); + timezoneAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(42)); + runAndAssertNothing(compiledMillisecond.get()); + + // Test $millisecond returns Nothing with invalid timezoneDB. + timezoneAccessor.reset(timezoneTag, timezoneVal); + timezoneDBAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(42)); + runAndAssertNothing(compiledMillisecond.get()); + + // Test $millisecond with constant timezone + value::OwnedValueAccessor timezoneObjAccessor; + auto timezoneObjSlot = bindAccessor(&timezoneObjAccessor); + millisecondExpr = sbe::makeE<sbe::EFunction>( + "millisecond", sbe::makeEs(makeE<EVariable>(dateSlot), makeE<EVariable>(timezoneObjSlot))); + compiledMillisecond = compileExpression(*millisecondExpr); + + dateAccessor.reset(value::TypeTags::Date, + value::bitcastFrom<int64_t>( + kDefaultTimeZone.createFromDateParts(1996, 7, 18, 10, 11, 12, 123) + .toMillisSinceEpoch())); + auto timezone = tzdb->utcZone(); + timezoneObjAccessor.reset( + false, value::TypeTags::timeZone, value::bitcastFrom<TimeZone*>(&timezone)); + runAndAssertExpression(compiledMillisecond.get(), 123); +} + +TEST_F(SBEDateExpressionAcceptingTimezoneTest, BasicWeek) { + value::OwnedValueAccessor timezoneDBAccessor; + auto timezoneDBSlot = bindAccessor(&timezoneDBAccessor); + value::OwnedValueAccessor dateAccessor; + auto dateSlot = bindAccessor(&dateAccessor); + value::OwnedValueAccessor timezoneAccessor; + auto timezoneSlot = bindAccessor(&timezoneAccessor); + + auto weekExpr = sbe::makeE<sbe::EFunction>("week", + sbe::makeEs(makeE<EVariable>(dateSlot), + makeE<EVariable>(timezoneDBSlot), + makeE<EVariable>(timezoneSlot))); + auto compiledWeek = compileExpression(*weekExpr); + + // Test $week returns the correct value. + auto tzdb = std::make_unique<TimeZoneDatabase>(); + timezoneDBAccessor.reset( + false, value::TypeTags::timeZoneDB, value::bitcastFrom<TimeZoneDatabase*>(tzdb.get())); + dateAccessor.reset(value::TypeTags::Date, + value::bitcastFrom<int64_t>( + kDefaultTimeZone.createFromDateParts(1996, 1, 1, 10, 11, 12, 123) + .toMillisSinceEpoch())); + auto [timezoneTag, timezoneVal] = value::makeNewString("UTC"); + timezoneAccessor.reset(timezoneTag, timezoneVal); + runAndAssertExpression(compiledWeek.get(), 0); + + // Test $week returns Nothing with invalid date. + dateAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(42)); + runAndAssertNothing(compiledWeek.get()); + + // Test $week returns Nothing with invalid timezone. + dateAccessor.reset(value::TypeTags::Date, value::bitcastFrom<int64_t>(21929999)); + timezoneAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(42)); + runAndAssertNothing(compiledWeek.get()); + + // Test $week returns Nothing with invalid timezoneDB. + timezoneAccessor.reset(timezoneTag, timezoneVal); + timezoneDBAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(42)); + runAndAssertNothing(compiledWeek.get()); + + // Test $week with constant timezone + value::OwnedValueAccessor timezoneObjAccessor; + auto timezoneObjSlot = bindAccessor(&timezoneObjAccessor); + weekExpr = sbe::makeE<sbe::EFunction>( + "week", sbe::makeEs(makeE<EVariable>(dateSlot), makeE<EVariable>(timezoneObjSlot))); + compiledWeek = compileExpression(*weekExpr); + + dateAccessor.reset(value::TypeTags::Date, + value::bitcastFrom<int64_t>( + kDefaultTimeZone.createFromDateParts(1996, 1, 1, 10, 11, 12, 123) + .toMillisSinceEpoch())); + auto timezone = tzdb->utcZone(); + timezoneObjAccessor.reset( + false, value::TypeTags::timeZone, value::bitcastFrom<TimeZone*>(&timezone)); + runAndAssertExpression(compiledWeek.get(), 0); +} + +TEST_F(SBEDateExpressionAcceptingTimezoneTest, BasicISOWeekYear) { + value::OwnedValueAccessor timezoneDBAccessor; + auto timezoneDBSlot = bindAccessor(&timezoneDBAccessor); + value::OwnedValueAccessor dateAccessor; + auto dateSlot = bindAccessor(&dateAccessor); + value::OwnedValueAccessor timezoneAccessor; + auto timezoneSlot = bindAccessor(&timezoneAccessor); + + auto isoWeekYearExpr = sbe::makeE<sbe::EFunction>("isoWeekYear", + sbe::makeEs(makeE<EVariable>(dateSlot), + makeE<EVariable>(timezoneDBSlot), + makeE<EVariable>(timezoneSlot))); + auto compiledISOWeekYear = compileExpression(*isoWeekYearExpr); + + // Test $isoWeekYear returns the correct value. + auto tzdb = std::make_unique<TimeZoneDatabase>(); + timezoneDBAccessor.reset( + false, value::TypeTags::timeZoneDB, value::bitcastFrom<TimeZoneDatabase*>(tzdb.get())); + dateAccessor.reset(value::TypeTags::Date, + value::bitcastFrom<int64_t>( + kDefaultTimeZone.createFromDateParts(1996, 7, 18, 10, 11, 12, 123) + .toMillisSinceEpoch())); + auto [timezoneTag, timezoneVal] = value::makeNewString("UTC"); + timezoneAccessor.reset(timezoneTag, timezoneVal); + runAndAssertExpression(compiledISOWeekYear.get(), 1996); + + // Test $isoWeekYear returns Nothing with invalid date. + dateAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(42)); + runAndAssertNothing(compiledISOWeekYear.get()); + + // Test $isoWeekYear returns Nothing with invalid timezone. + dateAccessor.reset(value::TypeTags::Date, value::bitcastFrom<int64_t>(21929999)); + timezoneAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(42)); + runAndAssertNothing(compiledISOWeekYear.get()); + + // Test $isoWeekYear returns Nothing with invalid timezoneDB. + timezoneAccessor.reset(timezoneTag, timezoneVal); + timezoneDBAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(42)); + runAndAssertNothing(compiledISOWeekYear.get()); + + // Test $isoWeekYear with constant timezone + value::OwnedValueAccessor timezoneObjAccessor; + auto timezoneObjSlot = bindAccessor(&timezoneObjAccessor); + isoWeekYearExpr = sbe::makeE<sbe::EFunction>( + "isoWeekYear", sbe::makeEs(makeE<EVariable>(dateSlot), makeE<EVariable>(timezoneObjSlot))); + compiledISOWeekYear = compileExpression(*isoWeekYearExpr); + + dateAccessor.reset(value::TypeTags::Date, + value::bitcastFrom<int64_t>( + kDefaultTimeZone.createFromDateParts(1996, 7, 18, 10, 11, 12, 123) + .toMillisSinceEpoch())); + auto timezone = tzdb->utcZone(); + timezoneObjAccessor.reset( + false, value::TypeTags::timeZone, value::bitcastFrom<TimeZone*>(&timezone)); + runAndAssertExpression(compiledISOWeekYear.get(), 1996); +} + +TEST_F(SBEDateExpressionAcceptingTimezoneTest, BasicISODayOfWeek) { + value::OwnedValueAccessor timezoneDBAccessor; + auto timezoneDBSlot = bindAccessor(&timezoneDBAccessor); + value::OwnedValueAccessor dateAccessor; + auto dateSlot = bindAccessor(&dateAccessor); + value::OwnedValueAccessor timezoneAccessor; + auto timezoneSlot = bindAccessor(&timezoneAccessor); + + auto isoDayOfWeekExpr = sbe::makeE<sbe::EFunction>("isoDayOfWeek", + sbe::makeEs(makeE<EVariable>(dateSlot), + makeE<EVariable>(timezoneDBSlot), + makeE<EVariable>(timezoneSlot))); + auto compiledISODayOfWeek = compileExpression(*isoDayOfWeekExpr); + + // Test $isoDayOfWeek returns the correct value. + auto tzdb = std::make_unique<TimeZoneDatabase>(); + timezoneDBAccessor.reset( + false, value::TypeTags::timeZoneDB, value::bitcastFrom<TimeZoneDatabase*>(tzdb.get())); + dateAccessor.reset(value::TypeTags::Date, + value::bitcastFrom<int64_t>( + kDefaultTimeZone.createFromDateParts(1996, 7, 18, 10, 11, 12, 123) + .toMillisSinceEpoch())); + auto [timezoneTag, timezoneVal] = value::makeNewString("UTC"); + timezoneAccessor.reset(timezoneTag, timezoneVal); + runAndAssertExpression(compiledISODayOfWeek.get(), 4); + + // Test $isoDayOfWeek returns Nothing with invalid date. + dateAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(42)); + runAndAssertNothing(compiledISODayOfWeek.get()); + + // Test $isoDayOfWeek returns Nothing with invalid timezone. + dateAccessor.reset(value::TypeTags::Date, value::bitcastFrom<int64_t>(21929999)); + timezoneAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(42)); + runAndAssertNothing(compiledISODayOfWeek.get()); + + // Test $isoDayOfWeek returns Nothing with invalid timezoneDB. + timezoneAccessor.reset(timezoneTag, timezoneVal); + timezoneDBAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(42)); + runAndAssertNothing(compiledISODayOfWeek.get()); + + // Test $isoDayOfWeek with constant timezone + value::OwnedValueAccessor timezoneObjAccessor; + auto timezoneObjSlot = bindAccessor(&timezoneObjAccessor); + isoDayOfWeekExpr = sbe::makeE<sbe::EFunction>( + "isoDayOfWeek", sbe::makeEs(makeE<EVariable>(dateSlot), makeE<EVariable>(timezoneObjSlot))); + compiledISODayOfWeek = compileExpression(*isoDayOfWeekExpr); + + dateAccessor.reset(value::TypeTags::Date, + value::bitcastFrom<int64_t>( + kDefaultTimeZone.createFromDateParts(1996, 7, 18, 10, 11, 12, 123) + .toMillisSinceEpoch())); + auto timezone = tzdb->utcZone(); + timezoneObjAccessor.reset( + false, value::TypeTags::timeZone, value::bitcastFrom<TimeZone*>(&timezone)); + runAndAssertExpression(compiledISODayOfWeek.get(), 4); +} + +TEST_F(SBEDateExpressionAcceptingTimezoneTest, BasicISOWeek) { + value::OwnedValueAccessor timezoneDBAccessor; + auto timezoneDBSlot = bindAccessor(&timezoneDBAccessor); + value::OwnedValueAccessor dateAccessor; + auto dateSlot = bindAccessor(&dateAccessor); + value::OwnedValueAccessor timezoneAccessor; + auto timezoneSlot = bindAccessor(&timezoneAccessor); + + auto isoWeekExpr = sbe::makeE<sbe::EFunction>("isoWeek", + sbe::makeEs(makeE<EVariable>(dateSlot), + makeE<EVariable>(timezoneDBSlot), + makeE<EVariable>(timezoneSlot))); + auto compiledISOWeek = compileExpression(*isoWeekExpr); + + // Test $isoWeek returns the correct value. + auto tzdb = std::make_unique<TimeZoneDatabase>(); + timezoneDBAccessor.reset( + false, value::TypeTags::timeZoneDB, value::bitcastFrom<TimeZoneDatabase*>(tzdb.get())); + dateAccessor.reset(value::TypeTags::Date, + value::bitcastFrom<int64_t>( + kDefaultTimeZone.createFromDateParts(1996, 1, 1, 10, 11, 12, 123) + .toMillisSinceEpoch())); + auto [timezoneTag, timezoneVal] = value::makeNewString("UTC"); + timezoneAccessor.reset(timezoneTag, timezoneVal); + runAndAssertExpression(compiledISOWeek.get(), 1); + + // Test $isoWeek returns Nothing with invalid date. + dateAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(42)); + runAndAssertNothing(compiledISOWeek.get()); + + // Test $isoWeek returns Nothing with invalid timezone. + dateAccessor.reset(value::TypeTags::Date, value::bitcastFrom<int64_t>(21929999)); + timezoneAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(42)); + runAndAssertNothing(compiledISOWeek.get()); + + // Test $isoWeek returns Nothing with invalid timezoneDB. + timezoneAccessor.reset(timezoneTag, timezoneVal); + timezoneDBAccessor.reset(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(42)); + runAndAssertNothing(compiledISOWeek.get()); + + // Test $isoWeek with constant timezone + value::OwnedValueAccessor timezoneObjAccessor; + auto timezoneObjSlot = bindAccessor(&timezoneObjAccessor); + isoWeekExpr = sbe::makeE<sbe::EFunction>( + "isoWeek", sbe::makeEs(makeE<EVariable>(dateSlot), makeE<EVariable>(timezoneObjSlot))); + compiledISOWeek = compileExpression(*isoWeekExpr); + + dateAccessor.reset(value::TypeTags::Date, + value::bitcastFrom<int64_t>( + kDefaultTimeZone.createFromDateParts(1996, 1, 1, 10, 11, 12, 123) + .toMillisSinceEpoch())); + auto timezone = tzdb->utcZone(); + timezoneObjAccessor.reset( + false, value::TypeTags::timeZone, value::bitcastFrom<TimeZone*>(&timezone)); + runAndAssertExpression(compiledISOWeek.get(), 1); +} } // namespace mongo::sbe diff --git a/src/mongo/db/exec/sbe/vm/datetime.cpp b/src/mongo/db/exec/sbe/vm/datetime.cpp index 248b7528999..b4363ca0de4 100644 --- a/src/mongo/db/exec/sbe/vm/datetime.cpp +++ b/src/mongo/db/exec/sbe/vm/datetime.cpp @@ -125,6 +125,87 @@ struct Year { result = timezone.dateParts(date).year; } }; + +/** + * The month operation used by genericExtractFromDate. + */ +struct Month { + static void doOperation(const Date_t& date, const TimeZone& timezone, int32_t& result) { + result = timezone.dateParts(date).month; + } +}; + +/** + * The hour operation used by genericExtractFromDate. + */ +struct Hour { + static void doOperation(const Date_t& date, const TimeZone& timezone, int32_t& result) { + result = timezone.dateParts(date).hour; + } +}; + +/** + * The minute operation used by genericExtractFromDate. + */ +struct Minute { + static void doOperation(const Date_t& date, const TimeZone& timezone, int32_t& result) { + result = timezone.dateParts(date).minute; + } +}; + +/** + * The second operation used by genericExtractFromDate. + */ +struct Second { + static void doOperation(const Date_t& date, const TimeZone& timezone, int32_t& result) { + result = timezone.dateParts(date).second; + } +}; + +/** + * The millisecond operation used by genericExtractFromDate. + */ +struct Millisecond { + static void doOperation(const Date_t& date, const TimeZone& timezone, int32_t& result) { + result = timezone.dateParts(date).millisecond; + } +}; + +/** + * The week operation used by genericExtractFromDate. + */ +struct Week { + static void doOperation(const Date_t& date, const TimeZone& timezone, int32_t& result) { + result = timezone.week(date); + } +}; + +/** + * The ISOWeekYear operation used by genericExtractFromDate. + */ +struct ISOWeekYear { + static void doOperation(const Date_t& date, const TimeZone& timezone, int32_t& result) { + result = timezone.isoYear(date); + } +}; + +/** + * The ISODayOfWeek operation used by genericExtractFromDate. + */ +struct ISODayOfWeek { + static void doOperation(const Date_t& date, const TimeZone& timezone, int32_t& result) { + result = timezone.isoDayOfWeek(date); + } +}; + +/** + * The ISOWeek operation used by genericExtractFromDate. + */ +struct ISOWeek { + static void doOperation(const Date_t& date, const TimeZone& timezone, int32_t& result) { + result = timezone.isoWeek(date); + } +}; } // namespace /** @@ -269,6 +350,177 @@ FastTuple<bool, value::TypeTags, value::Value> ByteCode::genericYear(value::Type dateTag, dateValue, timezoneTag, timezoneValue); } +FastTuple<bool, value::TypeTags, value::Value> ByteCode::genericMonth(value::TypeTags timezoneDBTag, + value::Value timezoneDBValue, + value::TypeTags dateTag, + value::Value dateValue, + value::TypeTags timezoneTag, + value::Value timezoneValue) { + return genericDateExpressionAcceptingTimeZone<Month>( + timezoneDBTag, timezoneDBValue, dateTag, dateValue, timezoneTag, timezoneValue); +} + +FastTuple<bool, value::TypeTags, value::Value> ByteCode::genericMonth(value::TypeTags dateTag, + value::Value dateValue, + value::TypeTags timezoneTag, + value::Value timezoneValue) { + return genericDateExpressionAcceptingTimeZone<Month>( + dateTag, dateValue, timezoneTag, timezoneValue); +} + +FastTuple<bool, value::TypeTags, value::Value> ByteCode::genericHour(value::TypeTags timezoneDBTag, + value::Value timezoneDBValue, + value::TypeTags dateTag, + value::Value dateValue, + value::TypeTags timezoneTag, + value::Value timezoneValue) { + return genericDateExpressionAcceptingTimeZone<Hour>( + timezoneDBTag, timezoneDBValue, dateTag, dateValue, timezoneTag, timezoneValue); +} + +FastTuple<bool, value::TypeTags, value::Value> ByteCode::genericHour(value::TypeTags dateTag, + value::Value dateValue, + value::TypeTags timezoneTag, + value::Value timezoneValue) { + return genericDateExpressionAcceptingTimeZone<Hour>( + dateTag, dateValue, timezoneTag, timezoneValue); +} + +FastTuple<bool, value::TypeTags, value::Value> ByteCode::genericMinute( + value::TypeTags timezoneDBTag, + value::Value timezoneDBValue, + value::TypeTags dateTag, + value::Value dateValue, + value::TypeTags timezoneTag, + value::Value timezoneValue) { + return genericDateExpressionAcceptingTimeZone<Minute>( + timezoneDBTag, timezoneDBValue, dateTag, dateValue, timezoneTag, timezoneValue); +} + +FastTuple<bool, value::TypeTags, value::Value> ByteCode::genericMinute(value::TypeTags dateTag, + value::Value dateValue, + value::TypeTags timezoneTag, + value::Value timezoneValue) { + return genericDateExpressionAcceptingTimeZone<Minute>( + dateTag, dateValue, timezoneTag, timezoneValue); +} + +FastTuple<bool, value::TypeTags, value::Value> ByteCode::genericSecond( + value::TypeTags timezoneDBTag, + value::Value timezoneDBValue, + value::TypeTags dateTag, + value::Value dateValue, + value::TypeTags timezoneTag, + value::Value timezoneValue) { + return genericDateExpressionAcceptingTimeZone<Second>( + timezoneDBTag, timezoneDBValue, dateTag, dateValue, timezoneTag, timezoneValue); +} + +FastTuple<bool, value::TypeTags, value::Value> ByteCode::genericSecond(value::TypeTags dateTag, + value::Value dateValue, + value::TypeTags timezoneTag, + value::Value timezoneValue) { + return genericDateExpressionAcceptingTimeZone<Second>( + dateTag, dateValue, timezoneTag, timezoneValue); +} + +FastTuple<bool, value::TypeTags, value::Value> ByteCode::genericMillisecond( + value::TypeTags timezoneDBTag, + value::Value timezoneDBValue, + value::TypeTags dateTag, + value::Value dateValue, + value::TypeTags timezoneTag, + value::Value timezoneValue) { + return genericDateExpressionAcceptingTimeZone<Millisecond>( + timezoneDBTag, timezoneDBValue, dateTag, dateValue, timezoneTag, timezoneValue); +} + +FastTuple<bool, value::TypeTags, value::Value> ByteCode::genericMillisecond( + value::TypeTags dateTag, + value::Value dateValue, + value::TypeTags timezoneTag, + value::Value timezoneValue) { + return genericDateExpressionAcceptingTimeZone<Millisecond>( + dateTag, dateValue, timezoneTag, timezoneValue); +} + +FastTuple<bool, value::TypeTags, value::Value> ByteCode::genericWeek(value::TypeTags timezoneDBTag, + value::Value timezoneDBValue, + value::TypeTags dateTag, + value::Value dateValue, + value::TypeTags timezoneTag, + value::Value timezoneValue) { + return genericDateExpressionAcceptingTimeZone<Week>( + timezoneDBTag, timezoneDBValue, dateTag, dateValue, timezoneTag, timezoneValue); +} + +FastTuple<bool, value::TypeTags, value::Value> ByteCode::genericWeek(value::TypeTags dateTag, + value::Value dateValue, + value::TypeTags timezoneTag, + value::Value timezoneValue) { + return genericDateExpressionAcceptingTimeZone<Week>( + dateTag, dateValue, timezoneTag, timezoneValue); +} + +FastTuple<bool, value::TypeTags, value::Value> ByteCode::genericISOWeekYear( + value::TypeTags timezoneDBTag, + value::Value timezoneDBValue, + value::TypeTags dateTag, + value::Value dateValue, + value::TypeTags timezoneTag, + value::Value timezoneValue) { + return genericDateExpressionAcceptingTimeZone<ISOWeekYear>( + timezoneDBTag, timezoneDBValue, dateTag, dateValue, timezoneTag, timezoneValue); +} + +FastTuple<bool, value::TypeTags, value::Value> ByteCode::genericISOWeekYear( + value::TypeTags dateTag, + value::Value dateValue, + value::TypeTags timezoneTag, + value::Value timezoneValue) { + return genericDateExpressionAcceptingTimeZone<ISOWeekYear>( + dateTag, dateValue, timezoneTag, timezoneValue); +} + +FastTuple<bool, value::TypeTags, value::Value> ByteCode::genericISODayOfWeek( + value::TypeTags timezoneDBTag, + value::Value timezoneDBValue, + value::TypeTags dateTag, + value::Value dateValue, + value::TypeTags timezoneTag, + value::Value timezoneValue) { + return genericDateExpressionAcceptingTimeZone<ISODayOfWeek>( + timezoneDBTag, timezoneDBValue, dateTag, dateValue, timezoneTag, timezoneValue); +} + +FastTuple<bool, value::TypeTags, value::Value> ByteCode::genericISODayOfWeek( + value::TypeTags dateTag, + value::Value dateValue, + value::TypeTags timezoneTag, + value::Value timezoneValue) { + return genericDateExpressionAcceptingTimeZone<ISODayOfWeek>( + dateTag, dateValue, timezoneTag, timezoneValue); +} + +FastTuple<bool, value::TypeTags, value::Value> ByteCode::genericISOWeek( + value::TypeTags timezoneDBTag, + value::Value timezoneDBValue, + value::TypeTags dateTag, + value::Value dateValue, + value::TypeTags timezoneTag, + value::Value timezoneValue) { + return genericDateExpressionAcceptingTimeZone<ISOWeek>( + timezoneDBTag, timezoneDBValue, dateTag, dateValue, timezoneTag, timezoneValue); +} + +FastTuple<bool, value::TypeTags, value::Value> ByteCode::genericISOWeek( + value::TypeTags dateTag, + value::Value dateValue, + value::TypeTags timezoneTag, + value::Value timezoneValue) { + return genericDateExpressionAcceptingTimeZone<ISOWeek>( + dateTag, dateValue, timezoneTag, timezoneValue); +} } // namespace vm } // namespace sbe } // namespace mongo diff --git a/src/mongo/db/exec/sbe/vm/vm.cpp b/src/mongo/db/exec/sbe/vm/vm.cpp index cc298cfca86..7cd9727b008 100644 --- a/src/mongo/db/exec/sbe/vm/vm.cpp +++ b/src/mongo/db/exec/sbe/vm/vm.cpp @@ -3438,6 +3438,141 @@ FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinYear(ArityType a } } +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinMonth(ArityType arity) { + invariant(arity == 3 || arity == 2); + + auto [dateOwn, dateTag, dateValue] = getFromStack(0); + if (arity == 3) { + auto [timezoneDBOwn, timezoneDBTag, timezoneDBValue] = getFromStack(1); + auto [timezoneOwn, timezoneTag, timezoneValue] = getFromStack(2); + return genericMonth( + timezoneDBTag, timezoneDBValue, dateTag, dateValue, timezoneTag, timezoneValue); + } else { + auto [timezoneOwn, timezoneTag, timezoneValue] = getFromStack(1); + return genericMonth(dateTag, dateValue, timezoneTag, timezoneValue); + } +} + +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinHour(ArityType arity) { + invariant(arity == 3 || arity == 2); + + auto [dateOwn, dateTag, dateValue] = getFromStack(0); + if (arity == 3) { + auto [timezoneDBOwn, timezoneDBTag, timezoneDBValue] = getFromStack(1); + auto [timezoneOwn, timezoneTag, timezoneValue] = getFromStack(2); + return genericHour( + timezoneDBTag, timezoneDBValue, dateTag, dateValue, timezoneTag, timezoneValue); + } else { + auto [timezoneOwn, timezoneTag, timezoneValue] = getFromStack(1); + return genericHour(dateTag, dateValue, timezoneTag, timezoneValue); + } +} + +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinMinute(ArityType arity) { + invariant(arity == 3 || arity == 2); + + auto [dateOwn, dateTag, dateValue] = getFromStack(0); + if (arity == 3) { + auto [timezoneDBOwn, timezoneDBTag, timezoneDBValue] = getFromStack(1); + auto [timezoneOwn, timezoneTag, timezoneValue] = getFromStack(2); + return genericMinute( + timezoneDBTag, timezoneDBValue, dateTag, dateValue, timezoneTag, timezoneValue); + } else { + auto [timezoneOwn, timezoneTag, timezoneValue] = getFromStack(1); + return genericMinute(dateTag, dateValue, timezoneTag, timezoneValue); + } +} + +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinSecond(ArityType arity) { + invariant(arity == 3 || arity == 2); + + auto [dateOwn, dateTag, dateValue] = getFromStack(0); + if (arity == 3) { + auto [timezoneDBOwn, timezoneDBTag, timezoneDBValue] = getFromStack(1); + auto [timezoneOwn, timezoneTag, timezoneValue] = getFromStack(2); + return genericSecond( + timezoneDBTag, timezoneDBValue, dateTag, dateValue, timezoneTag, timezoneValue); + } else { + auto [timezoneOwn, timezoneTag, timezoneValue] = getFromStack(1); + return genericSecond(dateTag, dateValue, timezoneTag, timezoneValue); + } +} + +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinMillisecond(ArityType arity) { + invariant(arity == 3 || arity == 2); + + auto [dateOwn, dateTag, dateValue] = getFromStack(0); + if (arity == 3) { + auto [timezoneDBOwn, timezoneDBTag, timezoneDBValue] = getFromStack(1); + auto [timezoneOwn, timezoneTag, timezoneValue] = getFromStack(2); + return genericMillisecond( + timezoneDBTag, timezoneDBValue, dateTag, dateValue, timezoneTag, timezoneValue); + } else { + auto [timezoneOwn, timezoneTag, timezoneValue] = getFromStack(1); + return genericMillisecond(dateTag, dateValue, timezoneTag, timezoneValue); + } +} + +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinWeek(ArityType arity) { + invariant(arity == 3 || arity == 2); + + auto [dateOwn, dateTag, dateValue] = getFromStack(0); + if (arity == 3) { + auto [timezoneDBOwn, timezoneDBTag, timezoneDBValue] = getFromStack(1); + auto [timezoneOwn, timezoneTag, timezoneValue] = getFromStack(2); + return genericWeek( + timezoneDBTag, timezoneDBValue, dateTag, dateValue, timezoneTag, timezoneValue); + } else { + auto [timezoneOwn, timezoneTag, timezoneValue] = getFromStack(1); + return genericWeek(dateTag, dateValue, timezoneTag, timezoneValue); + } +} + +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinISOWeekYear(ArityType arity) { + invariant(arity == 3 || arity == 2); + + auto [dateOwn, dateTag, dateValue] = getFromStack(0); + if (arity == 3) { + auto [timezoneDBOwn, timezoneDBTag, timezoneDBValue] = getFromStack(1); + auto [timezoneOwn, timezoneTag, timezoneValue] = getFromStack(2); + return genericISOWeekYear( + timezoneDBTag, timezoneDBValue, dateTag, dateValue, timezoneTag, timezoneValue); + } else { + auto [timezoneOwn, timezoneTag, timezoneValue] = getFromStack(1); + return genericISOWeekYear(dateTag, dateValue, timezoneTag, timezoneValue); + } +} + +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinISODayOfWeek(ArityType arity) { + invariant(arity == 3 || arity == 2); + + auto [dateOwn, dateTag, dateValue] = getFromStack(0); + if (arity == 3) { + auto [timezoneDBOwn, timezoneDBTag, timezoneDBValue] = getFromStack(1); + auto [timezoneOwn, timezoneTag, timezoneValue] = getFromStack(2); + return genericISODayOfWeek( + timezoneDBTag, timezoneDBValue, dateTag, dateValue, timezoneTag, timezoneValue); + } else { + auto [timezoneOwn, timezoneTag, timezoneValue] = getFromStack(1); + return genericISODayOfWeek(dateTag, dateValue, timezoneTag, timezoneValue); + } +} + +FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinISOWeek(ArityType arity) { + invariant(arity == 3 || arity == 2); + + auto [dateOwn, dateTag, dateValue] = getFromStack(0); + if (arity == 3) { + auto [timezoneDBOwn, timezoneDBTag, timezoneDBValue] = getFromStack(1); + auto [timezoneOwn, timezoneTag, timezoneValue] = getFromStack(2); + return genericISOWeek( + timezoneDBTag, timezoneDBValue, dateTag, dateValue, timezoneTag, timezoneValue); + } else { + auto [timezoneOwn, timezoneTag, timezoneValue] = getFromStack(1); + return genericISOWeek(dateTag, dateValue, timezoneTag, timezoneValue); + } +} + FastTuple<bool, value::TypeTags, value::Value> ByteCode::builtinBitTestPosition(ArityType arity) { invariant(arity == 3); @@ -5866,6 +6001,24 @@ FastTuple<bool, value::TypeTags, value::Value> ByteCode::dispatchBuiltin(Builtin return builtinMinMaxFromArray(arity, f); case Builtin::year: return builtinYear(arity); + case Builtin::month: + return builtinMonth(arity); + case Builtin::hour: + return builtinHour(arity); + case Builtin::minute: + return builtinMinute(arity); + case Builtin::second: + return builtinSecond(arity); + case Builtin::millisecond: + return builtinMillisecond(arity); + case Builtin::week: + return builtinWeek(arity); + case Builtin::isoWeekYear: + return builtinISOWeekYear(arity); + case Builtin::isoDayOfWeek: + return builtinISODayOfWeek(arity); + case Builtin::isoWeek: + return builtinISOWeek(arity); } MONGO_UNREACHABLE; @@ -6112,6 +6265,26 @@ std::string builtinToString(Builtin b) { return "internalLeast"; case Builtin::internalGreatest: return "internalGreatest"; + case Builtin::year: + return "year"; + case Builtin::month: + return "month"; + case Builtin::hour: + return "hour"; + case Builtin::minute: + return "minute"; + case Builtin::second: + return "second"; + case Builtin::millisecond: + return "millisecond"; + case Builtin::week: + return "week"; + case Builtin::isoWeekYear: + return "isoWeekYear"; + case Builtin::isoDayOfWeek: + return "isoDayOfWeek"; + case Builtin::isoWeek: + return "isoWeek"; default: MONGO_UNREACHABLE; } diff --git a/src/mongo/db/exec/sbe/vm/vm.h b/src/mongo/db/exec/sbe/vm/vm.h index 5acf2817702..65f5011fc17 100644 --- a/src/mongo/db/exec/sbe/vm/vm.h +++ b/src/mongo/db/exec/sbe/vm/vm.h @@ -740,6 +740,15 @@ enum class Builtin : uint8_t { internalLeast, // helper functions for computation of sort keys internalGreatest, // helper functions for computation of sort keys year, + month, + hour, + minute, + second, + millisecond, + week, + isoWeekYear, + isoDayOfWeek, + isoWeek, }; std::string builtinToString(Builtin b); @@ -1277,6 +1286,97 @@ private: value::Value dateValue, value::TypeTags timezoneTag, value::Value timezoneValue); + FastTuple<bool, value::TypeTags, value::Value> genericMonth(value::TypeTags timezoneDBTag, + value::Value timezoneDBValue, + value::TypeTags dateTag, + value::Value dateValue, + value::TypeTags timezoneTag, + value::Value timezoneValue); + FastTuple<bool, value::TypeTags, value::Value> genericMonth(value::TypeTags dateTag, + value::Value dateValue, + value::TypeTags timezoneTag, + value::Value timezoneValue); + FastTuple<bool, value::TypeTags, value::Value> genericHour(value::TypeTags timezoneDBTag, + value::Value timezoneDBValue, + value::TypeTags dateTag, + value::Value dateValue, + value::TypeTags timezoneTag, + value::Value timezoneValue); + FastTuple<bool, value::TypeTags, value::Value> genericHour(value::TypeTags dateTag, + value::Value dateValue, + value::TypeTags timezoneTag, + value::Value timezoneValue); + FastTuple<bool, value::TypeTags, value::Value> genericMinute(value::TypeTags timezoneDBTag, + value::Value timezoneDBValue, + value::TypeTags dateTag, + value::Value dateValue, + value::TypeTags timezoneTag, + value::Value timezoneValue); + FastTuple<bool, value::TypeTags, value::Value> genericMinute(value::TypeTags dateTag, + value::Value dateValue, + value::TypeTags timezoneTag, + value::Value timezoneValue); + FastTuple<bool, value::TypeTags, value::Value> genericSecond(value::TypeTags timezoneDBTag, + value::Value timezoneDBValue, + value::TypeTags dateTag, + value::Value dateValue, + value::TypeTags timezoneTag, + value::Value timezoneValue); + FastTuple<bool, value::TypeTags, value::Value> genericSecond(value::TypeTags dateTag, + value::Value dateValue, + value::TypeTags timezoneTag, + value::Value timezoneValue); + FastTuple<bool, value::TypeTags, value::Value> genericMillisecond(value::TypeTags timezoneDBTag, + value::Value timezoneDBValue, + value::TypeTags dateTag, + value::Value dateValue, + value::TypeTags timezoneTag, + value::Value timezoneValue); + FastTuple<bool, value::TypeTags, value::Value> genericMillisecond(value::TypeTags dateTag, + value::Value dateValue, + value::TypeTags timezoneTag, + value::Value timezoneValue); + FastTuple<bool, value::TypeTags, value::Value> genericWeek(value::TypeTags timezoneDBTag, + value::Value timezoneDBValue, + value::TypeTags dateTag, + value::Value dateValue, + value::TypeTags timezoneTag, + value::Value timezoneValue); + FastTuple<bool, value::TypeTags, value::Value> genericWeek(value::TypeTags dateTag, + value::Value dateValue, + value::TypeTags timezoneTag, + value::Value timezoneValue); + FastTuple<bool, value::TypeTags, value::Value> genericISOWeekYear(value::TypeTags timezoneDBTag, + value::Value timezoneDBValue, + value::TypeTags dateTag, + value::Value dateValue, + value::TypeTags timezoneTag, + value::Value timezoneValue); + FastTuple<bool, value::TypeTags, value::Value> genericISOWeekYear(value::TypeTags dateTag, + value::Value dateValue, + value::TypeTags timezoneTag, + value::Value timezoneValue); + FastTuple<bool, value::TypeTags, value::Value> genericISODayOfWeek( + value::TypeTags timezoneDBTag, + value::Value timezoneDBValue, + value::TypeTags dateTag, + value::Value dateValue, + value::TypeTags timezoneTag, + value::Value timezoneValue); + FastTuple<bool, value::TypeTags, value::Value> genericISODayOfWeek(value::TypeTags dateTag, + value::Value dateValue, + value::TypeTags timezoneTag, + value::Value timezoneValue); + FastTuple<bool, value::TypeTags, value::Value> genericISOWeek(value::TypeTags timezoneDBTag, + value::Value timezoneDBValue, + value::TypeTags dateTag, + value::Value dateValue, + value::TypeTags timezoneTag, + value::Value timezoneValue); + FastTuple<bool, value::TypeTags, value::Value> genericISOWeek(value::TypeTags dateTag, + value::Value dateValue, + value::TypeTags timezoneTag, + value::Value timezoneValue); FastTuple<bool, value::TypeTags, value::Value> genericNewKeyString( ArityType arity, CollatorInterface* collator = nullptr); FastTuple<bool, value::TypeTags, value::Value> dateTrunc(value::TypeTags dateTag, @@ -1431,6 +1531,15 @@ private: FastTuple<bool, value::TypeTags, value::Value> builtinMinMaxFromArray(ArityType arity, Builtin f); FastTuple<bool, value::TypeTags, value::Value> builtinYear(ArityType arity); + FastTuple<bool, value::TypeTags, value::Value> builtinMonth(ArityType arity); + FastTuple<bool, value::TypeTags, value::Value> builtinHour(ArityType arity); + FastTuple<bool, value::TypeTags, value::Value> builtinMinute(ArityType arity); + FastTuple<bool, value::TypeTags, value::Value> builtinSecond(ArityType arity); + FastTuple<bool, value::TypeTags, value::Value> builtinMillisecond(ArityType arity); + FastTuple<bool, value::TypeTags, value::Value> builtinWeek(ArityType arity); + FastTuple<bool, value::TypeTags, value::Value> builtinISOWeekYear(ArityType arity); + FastTuple<bool, value::TypeTags, value::Value> builtinISODayOfWeek(ArityType arity); + FastTuple<bool, value::TypeTags, value::Value> builtinISOWeek(ArityType arity); FastTuple<bool, value::TypeTags, value::Value> dispatchBuiltin(Builtin f, ArityType arity); diff --git a/src/mongo/db/pipeline/expression.h b/src/mongo/db/pipeline/expression.h index 682d52b6876..5af5765e8d0 100644 --- a/src/mongo/db/pipeline/expression.h +++ b/src/mongo/db/pipeline/expression.h @@ -2089,7 +2089,8 @@ public: boost::intrusive_ptr<Expression> timeZone = nullptr) : DateExpressionAcceptingTimeZone<ExpressionHour>( expCtx, "$hour", std::move(date), std::move(timeZone)) { - expCtx->sbeCompatibility = SbeCompatibility::notCompatible; + expCtx->sbeCompatibility = + std::min(expCtx->sbeCompatibility, SbeCompatibility::flagGuarded); } Value evaluateDate(Date_t date, const TimeZone& timeZone) const final { @@ -2490,7 +2491,8 @@ public: boost::intrusive_ptr<Expression> timeZone = nullptr) : DateExpressionAcceptingTimeZone<ExpressionMillisecond>( expCtx, "$millisecond", std::move(date), std::move(timeZone)) { - expCtx->sbeCompatibility = SbeCompatibility::notCompatible; + expCtx->sbeCompatibility = + std::min(expCtx->sbeCompatibility, SbeCompatibility::flagGuarded); } Value evaluateDate(Date_t date, const TimeZone& timeZone) const final { @@ -2514,7 +2516,8 @@ public: boost::intrusive_ptr<Expression> timeZone = nullptr) : DateExpressionAcceptingTimeZone<ExpressionMinute>( expCtx, "$minute", std::move(date), std::move(timeZone)) { - expCtx->sbeCompatibility = SbeCompatibility::notCompatible; + expCtx->sbeCompatibility = + std::min(expCtx->sbeCompatibility, SbeCompatibility::flagGuarded); } Value evaluateDate(Date_t date, const TimeZone& timeZone) const final { @@ -2600,7 +2603,8 @@ public: boost::intrusive_ptr<Expression> timeZone = nullptr) : DateExpressionAcceptingTimeZone<ExpressionMonth>( expCtx, "$month", std::move(date), std::move(timeZone)) { - expCtx->sbeCompatibility = SbeCompatibility::notCompatible; + expCtx->sbeCompatibility = + std::min(expCtx->sbeCompatibility, SbeCompatibility::flagGuarded); } Value evaluateDate(Date_t date, const TimeZone& timeZone) const final { @@ -2897,7 +2901,8 @@ public: boost::intrusive_ptr<Expression> timeZone = nullptr) : DateExpressionAcceptingTimeZone<ExpressionSecond>( expCtx, "$second", std::move(date), std::move(timeZone)) { - expCtx->sbeCompatibility = SbeCompatibility::notCompatible; + expCtx->sbeCompatibility = + std::min(expCtx->sbeCompatibility, SbeCompatibility::flagGuarded); } Value evaluateDate(Date_t date, const TimeZone& timeZone) const final { @@ -3683,7 +3688,8 @@ public: boost::intrusive_ptr<Expression> timeZone = nullptr) : DateExpressionAcceptingTimeZone<ExpressionWeek>( expCtx, "$week", std::move(date), std::move(timeZone)) { - expCtx->sbeCompatibility = SbeCompatibility::notCompatible; + expCtx->sbeCompatibility = + std::min(expCtx->sbeCompatibility, SbeCompatibility::flagGuarded); } Value evaluateDate(Date_t date, const TimeZone& timeZone) const final { @@ -3707,7 +3713,8 @@ public: boost::intrusive_ptr<Expression> timeZone = nullptr) : DateExpressionAcceptingTimeZone<ExpressionIsoWeekYear>( expCtx, "$isoWeekYear", std::move(date), std::move(timeZone)) { - expCtx->sbeCompatibility = SbeCompatibility::notCompatible; + expCtx->sbeCompatibility = + std::min(expCtx->sbeCompatibility, SbeCompatibility::flagGuarded); } Value evaluateDate(Date_t date, const TimeZone& timeZone) const final { @@ -3732,7 +3739,8 @@ public: boost::intrusive_ptr<Expression> timeZone = nullptr) : DateExpressionAcceptingTimeZone<ExpressionIsoDayOfWeek>( expCtx, "$isoDayOfWeek", std::move(date), std::move(timeZone)) { - expCtx->sbeCompatibility = SbeCompatibility::notCompatible; + expCtx->sbeCompatibility = + std::min(expCtx->sbeCompatibility, SbeCompatibility::flagGuarded); } Value evaluateDate(Date_t date, const TimeZone& timeZone) const final { @@ -3756,7 +3764,8 @@ public: boost::intrusive_ptr<Expression> timeZone = nullptr) : DateExpressionAcceptingTimeZone<ExpressionIsoWeek>( expCtx, "$isoWeek", std::move(date), std::move(timeZone)) { - expCtx->sbeCompatibility = SbeCompatibility::notCompatible; + expCtx->sbeCompatibility = + std::min(expCtx->sbeCompatibility, SbeCompatibility::flagGuarded); } Value evaluateDate(Date_t date, const TimeZone& timeZone) const final { diff --git a/src/mongo/db/pipeline/expression_bm_fixture.cpp b/src/mongo/db/pipeline/expression_bm_fixture.cpp index a12a56b9aa0..9994020dbce 100644 --- a/src/mongo/db/pipeline/expression_bm_fixture.cpp +++ b/src/mongo/db/pipeline/expression_bm_fixture.cpp @@ -609,11 +609,373 @@ void ExpressionBenchmarkFixture::benchmarkYearUTCMinus0700(benchmark::State& sta } void ExpressionBenchmarkFixture::benchmarkYearNewYork(benchmark::State& state) { + testDateExpressionWithVariableTimezone("$year", + Date_t::fromMillisSinceEpoch(4108446425000LL), + std::string{"America/New_York"}, + state); +} + +void ExpressionBenchmarkFixture::benchmarkMonthNoTZ(benchmark::State& state) { + testDateExpressionWithConstantTimezone( + "$month", Date_t::fromMillisSinceEpoch(1893466800000LL), boost::none, state); +} + +void ExpressionBenchmarkFixture::benchmarkMonthConstTzUTC(benchmark::State& state) { + testDateExpressionWithConstantTimezone( + "$month", Date_t::fromMillisSinceEpoch(1893466800000LL), std::string{"UTC"}, state); +} + +void ExpressionBenchmarkFixture::benchmarkMonthConstTzUTCMinus0700(benchmark::State& state) { + testDateExpressionWithConstantTimezone( + "$month", Date_t::fromMillisSinceEpoch(1583924825000LL), std::string{"-07:00"}, state); +} + +void ExpressionBenchmarkFixture::benchmarkMonthConstTzNewYork(benchmark::State& state) { + testDateExpressionWithConstantTimezone("$month", + Date_t::fromMillisSinceEpoch(4108446425000LL), + std::string{"America/New_York"}, + state); +} + +void ExpressionBenchmarkFixture::benchmarkMonthUTC(benchmark::State& state) { testDateExpressionWithVariableTimezone( - "$year", - Date_t::fromMillisSinceEpoch(4108446425000LL) /* year 2100*/, - std::string{"America/New_York"}, - state); + "$month", Date_t::fromMillisSinceEpoch(1893466800000LL), std::string{"UTC"}, state); +} + +void ExpressionBenchmarkFixture::benchmarkMonthUTCMinus0700(benchmark::State& state) { + testDateExpressionWithVariableTimezone( + "$month", Date_t::fromMillisSinceEpoch(1583924825000LL), std::string{"-07:00"}, state); +} + +void ExpressionBenchmarkFixture::benchmarkMonthNewYork(benchmark::State& state) { + testDateExpressionWithVariableTimezone("$month", + Date_t::fromMillisSinceEpoch(4108446425000LL), + std::string{"America/New_York"}, + state); +} + +void ExpressionBenchmarkFixture::benchmarkHourNoTZ(benchmark::State& state) { + testDateExpressionWithConstantTimezone( + "$hour", Date_t::fromMillisSinceEpoch(1893466800000LL), boost::none, state); +} + +void ExpressionBenchmarkFixture::benchmarkHourConstTzUTC(benchmark::State& state) { + testDateExpressionWithConstantTimezone( + "$hour", Date_t::fromMillisSinceEpoch(1893466800000LL), std::string{"UTC"}, state); +} + +void ExpressionBenchmarkFixture::benchmarkHourConstTzUTCMinus0700(benchmark::State& state) { + testDateExpressionWithConstantTimezone( + "$hour", Date_t::fromMillisSinceEpoch(1583924825000LL), std::string{"-07:00"}, state); +} + +void ExpressionBenchmarkFixture::benchmarkHourConstTzNewYork(benchmark::State& state) { + testDateExpressionWithConstantTimezone("$hour", + Date_t::fromMillisSinceEpoch(4108446425000LL), + std::string{"America/New_York"}, + state); +} + +void ExpressionBenchmarkFixture::benchmarkHourUTC(benchmark::State& state) { + testDateExpressionWithVariableTimezone( + "$hour", Date_t::fromMillisSinceEpoch(1893466800000LL), std::string{"UTC"}, state); +} + +void ExpressionBenchmarkFixture::benchmarkHourUTCMinus0700(benchmark::State& state) { + testDateExpressionWithVariableTimezone( + "$hour", Date_t::fromMillisSinceEpoch(1583924825000LL), std::string{"-07:00"}, state); +} + +void ExpressionBenchmarkFixture::benchmarkHourNewYork(benchmark::State& state) { + testDateExpressionWithVariableTimezone("$hour", + Date_t::fromMillisSinceEpoch(4108446425000LL), + std::string{"America/New_York"}, + state); +} + +void ExpressionBenchmarkFixture::benchmarkMinuteNoTZ(benchmark::State& state) { + testDateExpressionWithConstantTimezone( + "$minute", Date_t::fromMillisSinceEpoch(1893466800000LL), boost::none, state); +} + +void ExpressionBenchmarkFixture::benchmarkMinuteConstTzUTC(benchmark::State& state) { + testDateExpressionWithConstantTimezone( + "$minute", Date_t::fromMillisSinceEpoch(1893466800000LL), std::string{"UTC"}, state); +} + +void ExpressionBenchmarkFixture::benchmarkMinuteConstTzUTCMinus0700(benchmark::State& state) { + testDateExpressionWithConstantTimezone( + "$minute", Date_t::fromMillisSinceEpoch(1583924825000LL), std::string{"-07:00"}, state); +} + +void ExpressionBenchmarkFixture::benchmarkMinuteConstTzNewYork(benchmark::State& state) { + testDateExpressionWithConstantTimezone("$minute", + Date_t::fromMillisSinceEpoch(4108446425000LL), + std::string{"America/New_York"}, + state); +} + +void ExpressionBenchmarkFixture::benchmarkMinuteUTC(benchmark::State& state) { + testDateExpressionWithVariableTimezone( + "$minute", Date_t::fromMillisSinceEpoch(1893466800000LL), std::string{"UTC"}, state); +} + +void ExpressionBenchmarkFixture::benchmarkMinuteUTCMinus0700(benchmark::State& state) { + testDateExpressionWithVariableTimezone( + "$minute", Date_t::fromMillisSinceEpoch(1583924825000LL), std::string{"-07:00"}, state); +} + +void ExpressionBenchmarkFixture::benchmarkMinuteNewYork(benchmark::State& state) { + testDateExpressionWithVariableTimezone("$minute", + Date_t::fromMillisSinceEpoch(4108446425000LL), + std::string{"America/New_York"}, + state); +} + +void ExpressionBenchmarkFixture::benchmarkSecondNoTZ(benchmark::State& state) { + testDateExpressionWithConstantTimezone( + "$second", Date_t::fromMillisSinceEpoch(1893466800000LL), boost::none, state); +} + +void ExpressionBenchmarkFixture::benchmarkSecondConstTzUTC(benchmark::State& state) { + testDateExpressionWithConstantTimezone( + "$second", Date_t::fromMillisSinceEpoch(1893466800000LL), std::string{"UTC"}, state); +} + +void ExpressionBenchmarkFixture::benchmarkSecondConstTzUTCMinus0700(benchmark::State& state) { + testDateExpressionWithConstantTimezone( + "$second", Date_t::fromMillisSinceEpoch(1583924825000LL), std::string{"-07:00"}, state); +} + +void ExpressionBenchmarkFixture::benchmarkSecondConstTzNewYork(benchmark::State& state) { + testDateExpressionWithConstantTimezone("$second", + Date_t::fromMillisSinceEpoch(4108446425000LL), + std::string{"America/New_York"}, + state); +} + +void ExpressionBenchmarkFixture::benchmarkSecondUTC(benchmark::State& state) { + testDateExpressionWithVariableTimezone( + "$second", Date_t::fromMillisSinceEpoch(1893466800000LL), std::string{"UTC"}, state); +} + +void ExpressionBenchmarkFixture::benchmarkSecondUTCMinus0700(benchmark::State& state) { + testDateExpressionWithVariableTimezone( + "$second", Date_t::fromMillisSinceEpoch(1583924825000LL), std::string{"-07:00"}, state); +} + +void ExpressionBenchmarkFixture::benchmarkSecondNewYork(benchmark::State& state) { + testDateExpressionWithVariableTimezone("$second", + Date_t::fromMillisSinceEpoch(4108446425000LL), + std::string{"America/New_York"}, + state); +} + +void ExpressionBenchmarkFixture::benchmarkMillisecondNoTZ(benchmark::State& state) { + testDateExpressionWithConstantTimezone( + "$millisecond", Date_t::fromMillisSinceEpoch(1893466800000LL), boost::none, state); +} + +void ExpressionBenchmarkFixture::benchmarkMillisecondConstTzUTC(benchmark::State& state) { + testDateExpressionWithConstantTimezone( + "$millisecond", Date_t::fromMillisSinceEpoch(1893466800000LL), std::string{"UTC"}, state); +} + +void ExpressionBenchmarkFixture::benchmarkMillisecondConstTzUTCMinus0700(benchmark::State& state) { + testDateExpressionWithConstantTimezone("$millisecond", + Date_t::fromMillisSinceEpoch(1583924825000LL), + std::string{"-07:00"}, + state); +} + +void ExpressionBenchmarkFixture::benchmarkMillisecondConstTzNewYork(benchmark::State& state) { + testDateExpressionWithConstantTimezone("$millisecond", + Date_t::fromMillisSinceEpoch(4108446425000LL), + std::string{"America/New_York"}, + state); +} + +void ExpressionBenchmarkFixture::benchmarkMillisecondUTC(benchmark::State& state) { + testDateExpressionWithVariableTimezone( + "$millisecond", Date_t::fromMillisSinceEpoch(1893466800000LL), std::string{"UTC"}, state); +} + +void ExpressionBenchmarkFixture::benchmarkMillisecondUTCMinus0700(benchmark::State& state) { + testDateExpressionWithVariableTimezone("$millisecond", + Date_t::fromMillisSinceEpoch(1583924825000LL), + std::string{"-07:00"}, + state); +} + +void ExpressionBenchmarkFixture::benchmarkMillisecondNewYork(benchmark::State& state) { + testDateExpressionWithVariableTimezone("$millisecond", + Date_t::fromMillisSinceEpoch(4108446425000LL), + std::string{"America/New_York"}, + state); +} + +void ExpressionBenchmarkFixture::benchmarkWeekNoTZ(benchmark::State& state) { + testDateExpressionWithConstantTimezone( + "$week", Date_t::fromMillisSinceEpoch(1893466800000LL), boost::none, state); +} + +void ExpressionBenchmarkFixture::benchmarkWeekConstTzUTC(benchmark::State& state) { + testDateExpressionWithConstantTimezone( + "$week", Date_t::fromMillisSinceEpoch(1893466800000LL), std::string{"UTC"}, state); +} + +void ExpressionBenchmarkFixture::benchmarkWeekConstTzUTCMinus0700(benchmark::State& state) { + testDateExpressionWithConstantTimezone( + "$week", Date_t::fromMillisSinceEpoch(1583924825000LL), std::string{"-07:00"}, state); +} + +void ExpressionBenchmarkFixture::benchmarkWeekConstTzNewYork(benchmark::State& state) { + testDateExpressionWithConstantTimezone("$week", + Date_t::fromMillisSinceEpoch(4108446425000LL), + std::string{"America/New_York"}, + state); +} + +void ExpressionBenchmarkFixture::benchmarkWeekUTC(benchmark::State& state) { + testDateExpressionWithVariableTimezone( + "$week", Date_t::fromMillisSinceEpoch(1893466800000LL), std::string{"UTC"}, state); +} + +void ExpressionBenchmarkFixture::benchmarkWeekUTCMinus0700(benchmark::State& state) { + testDateExpressionWithVariableTimezone( + "$week", Date_t::fromMillisSinceEpoch(1583924825000LL), std::string{"-07:00"}, state); +} + +void ExpressionBenchmarkFixture::benchmarkWeekNewYork(benchmark::State& state) { + testDateExpressionWithVariableTimezone("$week", + Date_t::fromMillisSinceEpoch(4108446425000LL), + std::string{"America/New_York"}, + state); +} + +void ExpressionBenchmarkFixture::benchmarkISOWeekYearNoTZ(benchmark::State& state) { + testDateExpressionWithConstantTimezone( + "$isoWeekYear", Date_t::fromMillisSinceEpoch(1893466800000LL), boost::none, state); +} + +void ExpressionBenchmarkFixture::benchmarkISOWeekYearConstTzUTC(benchmark::State& state) { + testDateExpressionWithConstantTimezone( + "$isoWeekYear", Date_t::fromMillisSinceEpoch(1893466800000LL), std::string{"UTC"}, state); +} + +void ExpressionBenchmarkFixture::benchmarkISOWeekYearConstTzUTCMinus0700(benchmark::State& state) { + testDateExpressionWithConstantTimezone("$isoWeekYear", + Date_t::fromMillisSinceEpoch(1583924825000LL), + std::string{"-07:00"}, + state); +} + +void ExpressionBenchmarkFixture::benchmarkISOWeekYearConstTzNewYork(benchmark::State& state) { + testDateExpressionWithConstantTimezone("$isoWeekYear", + Date_t::fromMillisSinceEpoch(4108446425000LL), + std::string{"America/New_York"}, + state); +} + +void ExpressionBenchmarkFixture::benchmarkISOWeekYearUTC(benchmark::State& state) { + testDateExpressionWithVariableTimezone( + "$isoWeekYear", Date_t::fromMillisSinceEpoch(1893466800000LL), std::string{"UTC"}, state); +} + +void ExpressionBenchmarkFixture::benchmarkISOWeekYearUTCMinus0700(benchmark::State& state) { + testDateExpressionWithVariableTimezone("$isoWeekYear", + Date_t::fromMillisSinceEpoch(1583924825000LL), + std::string{"-07:00"}, + state); +} + +void ExpressionBenchmarkFixture::benchmarkISOWeekYearNewYork(benchmark::State& state) { + testDateExpressionWithVariableTimezone("$isoWeekYear", + Date_t::fromMillisSinceEpoch(4108446425000LL), + std::string{"America/New_York"}, + state); +} + +void ExpressionBenchmarkFixture::benchmarkISODayOfWeekNoTZ(benchmark::State& state) { + testDateExpressionWithConstantTimezone( + "$isoDayOfWeek", Date_t::fromMillisSinceEpoch(1893466800000LL), boost::none, state); +} + +void ExpressionBenchmarkFixture::benchmarkISODayOfWeekConstTzUTC(benchmark::State& state) { + testDateExpressionWithConstantTimezone( + "$isoDayOfWeek", Date_t::fromMillisSinceEpoch(1893466800000LL), std::string{"UTC"}, state); +} + +void ExpressionBenchmarkFixture::benchmarkISODayOfWeekConstTzUTCMinus0700(benchmark::State& state) { + testDateExpressionWithConstantTimezone("$isoDayOfWeek", + Date_t::fromMillisSinceEpoch(1583924825000LL), + std::string{"-07:00"}, + state); +} + +void ExpressionBenchmarkFixture::benchmarkISODayOfWeekConstTzNewYork(benchmark::State& state) { + testDateExpressionWithConstantTimezone("$isoDayOfWeek", + Date_t::fromMillisSinceEpoch(4108446425000LL), + std::string{"America/New_York"}, + state); +} + +void ExpressionBenchmarkFixture::benchmarkISODayOfWeekUTC(benchmark::State& state) { + testDateExpressionWithVariableTimezone( + "$isoDayOfWeek", Date_t::fromMillisSinceEpoch(1893466800000LL), std::string{"UTC"}, state); +} + +void ExpressionBenchmarkFixture::benchmarkISODayOfWeekUTCMinus0700(benchmark::State& state) { + testDateExpressionWithVariableTimezone("$isoDayOfWeek", + Date_t::fromMillisSinceEpoch(1583924825000LL), + std::string{"-07:00"}, + state); +} + +void ExpressionBenchmarkFixture::benchmarkISODayOfWeekNewYork(benchmark::State& state) { + testDateExpressionWithVariableTimezone("$isoDayOfWeek", + Date_t::fromMillisSinceEpoch(4108446425000LL), + std::string{"America/New_York"}, + state); +} + +void ExpressionBenchmarkFixture::benchmarkISOWeekNoTZ(benchmark::State& state) { + testDateExpressionWithConstantTimezone( + "$isoWeek", Date_t::fromMillisSinceEpoch(1893466800000LL), boost::none, state); +} + +void ExpressionBenchmarkFixture::benchmarkISOWeekConstTzUTC(benchmark::State& state) { + testDateExpressionWithConstantTimezone( + "$isoWeek", Date_t::fromMillisSinceEpoch(1893466800000LL), std::string{"UTC"}, state); +} + +void ExpressionBenchmarkFixture::benchmarkISOWeekConstTzUTCMinus0700(benchmark::State& state) { + testDateExpressionWithConstantTimezone( + "$isoWeek", Date_t::fromMillisSinceEpoch(1583924825000LL), std::string{"-07:00"}, state); +} + +void ExpressionBenchmarkFixture::benchmarkISOWeekConstTzNewYork(benchmark::State& state) { + testDateExpressionWithConstantTimezone("$isoWeek", + Date_t::fromMillisSinceEpoch(4108446425000LL), + std::string{"America/New_York"}, + state); +} + +void ExpressionBenchmarkFixture::benchmarkISOWeekUTC(benchmark::State& state) { + testDateExpressionWithVariableTimezone( + "$isoWeek", Date_t::fromMillisSinceEpoch(1893466800000LL), std::string{"UTC"}, state); +} + +void ExpressionBenchmarkFixture::benchmarkISOWeekUTCMinus0700(benchmark::State& state) { + testDateExpressionWithVariableTimezone( + "$isoWeek", Date_t::fromMillisSinceEpoch(1583924825000LL), std::string{"-07:00"}, state); +} + +void ExpressionBenchmarkFixture::benchmarkISOWeekNewYork(benchmark::State& state) { + testDateExpressionWithVariableTimezone("$isoWeek", + Date_t::fromMillisSinceEpoch(4108446425000LL), + std::string{"America/New_York"}, + state); } /** diff --git a/src/mongo/db/pipeline/expression_bm_fixture.h b/src/mongo/db/pipeline/expression_bm_fixture.h index 675a1c07488..97a8666b772 100644 --- a/src/mongo/db/pipeline/expression_bm_fixture.h +++ b/src/mongo/db/pipeline/expression_bm_fixture.h @@ -115,6 +115,78 @@ public: void benchmarkYearUTCMinus0700(benchmark::State& state); void benchmarkYearNewYork(benchmark::State& state); + void benchmarkMonthNoTZ(benchmark::State& state); + void benchmarkMonthConstTzUTC(benchmark::State& state); + void benchmarkMonthConstTzUTCMinus0700(benchmark::State& state); + void benchmarkMonthConstTzNewYork(benchmark::State& state); + void benchmarkMonthUTC(benchmark::State& state); + void benchmarkMonthUTCMinus0700(benchmark::State& state); + void benchmarkMonthNewYork(benchmark::State& state); + + void benchmarkHourNoTZ(benchmark::State& state); + void benchmarkHourConstTzUTC(benchmark::State& state); + void benchmarkHourConstTzUTCMinus0700(benchmark::State& state); + void benchmarkHourConstTzNewYork(benchmark::State& state); + void benchmarkHourUTC(benchmark::State& state); + void benchmarkHourUTCMinus0700(benchmark::State& state); + void benchmarkHourNewYork(benchmark::State& state); + + void benchmarkMinuteNoTZ(benchmark::State& state); + void benchmarkMinuteConstTzUTC(benchmark::State& state); + void benchmarkMinuteConstTzUTCMinus0700(benchmark::State& state); + void benchmarkMinuteConstTzNewYork(benchmark::State& state); + void benchmarkMinuteUTC(benchmark::State& state); + void benchmarkMinuteUTCMinus0700(benchmark::State& state); + void benchmarkMinuteNewYork(benchmark::State& state); + + void benchmarkSecondNoTZ(benchmark::State& state); + void benchmarkSecondConstTzUTC(benchmark::State& state); + void benchmarkSecondConstTzUTCMinus0700(benchmark::State& state); + void benchmarkSecondConstTzNewYork(benchmark::State& state); + void benchmarkSecondUTC(benchmark::State& state); + void benchmarkSecondUTCMinus0700(benchmark::State& state); + void benchmarkSecondNewYork(benchmark::State& state); + + void benchmarkMillisecondNoTZ(benchmark::State& state); + void benchmarkMillisecondConstTzUTC(benchmark::State& state); + void benchmarkMillisecondConstTzUTCMinus0700(benchmark::State& state); + void benchmarkMillisecondConstTzNewYork(benchmark::State& state); + void benchmarkMillisecondUTC(benchmark::State& state); + void benchmarkMillisecondUTCMinus0700(benchmark::State& state); + void benchmarkMillisecondNewYork(benchmark::State& state); + + void benchmarkWeekNoTZ(benchmark::State& state); + void benchmarkWeekConstTzUTC(benchmark::State& state); + void benchmarkWeekConstTzUTCMinus0700(benchmark::State& state); + void benchmarkWeekConstTzNewYork(benchmark::State& state); + void benchmarkWeekUTC(benchmark::State& state); + void benchmarkWeekUTCMinus0700(benchmark::State& state); + void benchmarkWeekNewYork(benchmark::State& state); + + void benchmarkISOWeekYearNoTZ(benchmark::State& state); + void benchmarkISOWeekYearConstTzUTC(benchmark::State& state); + void benchmarkISOWeekYearConstTzUTCMinus0700(benchmark::State& state); + void benchmarkISOWeekYearConstTzNewYork(benchmark::State& state); + void benchmarkISOWeekYearUTC(benchmark::State& state); + void benchmarkISOWeekYearUTCMinus0700(benchmark::State& state); + void benchmarkISOWeekYearNewYork(benchmark::State& state); + + void benchmarkISODayOfWeekNoTZ(benchmark::State& state); + void benchmarkISODayOfWeekConstTzUTC(benchmark::State& state); + void benchmarkISODayOfWeekConstTzUTCMinus0700(benchmark::State& state); + void benchmarkISODayOfWeekConstTzNewYork(benchmark::State& state); + void benchmarkISODayOfWeekUTC(benchmark::State& state); + void benchmarkISODayOfWeekUTCMinus0700(benchmark::State& state); + void benchmarkISODayOfWeekNewYork(benchmark::State& state); + + void benchmarkISOWeekNoTZ(benchmark::State& state); + void benchmarkISOWeekConstTzUTC(benchmark::State& state); + void benchmarkISOWeekConstTzUTCMinus0700(benchmark::State& state); + void benchmarkISOWeekConstTzNewYork(benchmark::State& state); + void benchmarkISOWeekUTC(benchmark::State& state); + void benchmarkISOWeekUTCMinus0700(benchmark::State& state); + void benchmarkISOWeekNewYork(benchmark::State& state); + void benchmarkGetFieldEvaluateExpression(benchmark::State& state); void benchmarkGetFieldEvaluateShortSyntaxExpression(benchmark::State& state); void benchmarkGetFieldNestedExpression(benchmark::State& state); @@ -361,6 +433,258 @@ private: (benchmark::State & state) { \ benchmarkYearNewYork(state); \ } \ + BENCHMARK_F(Fixture, MonthNoTZ) \ + (benchmark::State & state) { \ + benchmarkMonthNoTZ(state); \ + } \ + BENCHMARK_F(Fixture, MonthConstTzUTC) \ + (benchmark::State & state) { \ + benchmarkMonthConstTzUTC(state); \ + } \ + BENCHMARK_F(Fixture, MonthConstTzUTCMinus0700) \ + (benchmark::State & state) { \ + benchmarkMonthConstTzUTCMinus0700(state); \ + } \ + BENCHMARK_F(Fixture, MonthConstTzNewYork) \ + (benchmark::State & state) { \ + benchmarkMonthConstTzNewYork(state); \ + } \ + BENCHMARK_F(Fixture, MonthUTC) \ + (benchmark::State & state) { \ + benchmarkMonthUTC(state); \ + } \ + BENCHMARK_F(Fixture, MonthUTCMinus0700) \ + (benchmark::State & state) { \ + benchmarkMonthUTCMinus0700(state); \ + } \ + BENCHMARK_F(Fixture, MonthNewYork) \ + (benchmark::State & state) { \ + benchmarkMonthNewYork(state); \ + } \ + BENCHMARK_F(Fixture, HourNoTZ) \ + (benchmark::State & state) { \ + benchmarkHourNoTZ(state); \ + } \ + BENCHMARK_F(Fixture, HourConstTzUTC) \ + (benchmark::State & state) { \ + benchmarkHourConstTzUTC(state); \ + } \ + BENCHMARK_F(Fixture, HourConstTzUTCMinus0700) \ + (benchmark::State & state) { \ + benchmarkHourConstTzUTCMinus0700(state); \ + } \ + BENCHMARK_F(Fixture, HourConstTzNewYork) \ + (benchmark::State & state) { \ + benchmarkHourConstTzNewYork(state); \ + } \ + BENCHMARK_F(Fixture, HourUTC) \ + (benchmark::State & state) { \ + benchmarkHourUTC(state); \ + } \ + BENCHMARK_F(Fixture, HourUTCMinus0700) \ + (benchmark::State & state) { \ + benchmarkHourUTCMinus0700(state); \ + } \ + BENCHMARK_F(Fixture, HourNewYork) \ + (benchmark::State & state) { \ + benchmarkHourNewYork(state); \ + } \ + BENCHMARK_F(Fixture, MinuteNoTZ) \ + (benchmark::State & state) { \ + benchmarkMinuteNoTZ(state); \ + } \ + BENCHMARK_F(Fixture, MinuteConstTzUTC) \ + (benchmark::State & state) { \ + benchmarkMinuteConstTzUTC(state); \ + } \ + BENCHMARK_F(Fixture, MinuteConstTzUTCMinus0700) \ + (benchmark::State & state) { \ + benchmarkMinuteConstTzUTCMinus0700(state); \ + } \ + BENCHMARK_F(Fixture, MinuteConstTzNewYork) \ + (benchmark::State & state) { \ + benchmarkMinuteConstTzNewYork(state); \ + } \ + BENCHMARK_F(Fixture, MinuteUTC) \ + (benchmark::State & state) { \ + benchmarkMinuteUTC(state); \ + } \ + BENCHMARK_F(Fixture, MinuteUTCMinus0700) \ + (benchmark::State & state) { \ + benchmarkMinuteUTCMinus0700(state); \ + } \ + BENCHMARK_F(Fixture, MinuteNewYork) \ + (benchmark::State & state) { \ + benchmarkMinuteNewYork(state); \ + } \ + BENCHMARK_F(Fixture, SecondNoTZ) \ + (benchmark::State & state) { \ + benchmarkSecondNoTZ(state); \ + } \ + BENCHMARK_F(Fixture, SecondConstTzUTC) \ + (benchmark::State & state) { \ + benchmarkSecondConstTzUTC(state); \ + } \ + BENCHMARK_F(Fixture, SecondConstTzUTCMinus0700) \ + (benchmark::State & state) { \ + benchmarkSecondConstTzUTCMinus0700(state); \ + } \ + BENCHMARK_F(Fixture, SecondConstTzNewYork) \ + (benchmark::State & state) { \ + benchmarkSecondConstTzNewYork(state); \ + } \ + BENCHMARK_F(Fixture, SecondUTC) \ + (benchmark::State & state) { \ + benchmarkSecondUTC(state); \ + } \ + BENCHMARK_F(Fixture, SecondUTCMinus0700) \ + (benchmark::State & state) { \ + benchmarkSecondUTCMinus0700(state); \ + } \ + BENCHMARK_F(Fixture, SecondNewYork) \ + (benchmark::State & state) { \ + benchmarkSecondNewYork(state); \ + } \ + BENCHMARK_F(Fixture, MillisecondNoTZ) \ + (benchmark::State & state) { \ + benchmarkMillisecondNoTZ(state); \ + } \ + BENCHMARK_F(Fixture, MillisecondConstTzUTC) \ + (benchmark::State & state) { \ + benchmarkMillisecondConstTzUTC(state); \ + } \ + BENCHMARK_F(Fixture, MillisecondConstTzUTCMinus0700) \ + (benchmark::State & state) { \ + benchmarkMillisecondConstTzUTCMinus0700(state); \ + } \ + BENCHMARK_F(Fixture, MillisecondConstTzNewYork) \ + (benchmark::State & state) { \ + benchmarkMillisecondConstTzNewYork(state); \ + } \ + BENCHMARK_F(Fixture, MillisecondUTC) \ + (benchmark::State & state) { \ + benchmarkMillisecondUTC(state); \ + } \ + BENCHMARK_F(Fixture, MillisecondUTCMinus0700) \ + (benchmark::State & state) { \ + benchmarkMillisecondUTCMinus0700(state); \ + } \ + BENCHMARK_F(Fixture, MillisecondNewYork) \ + (benchmark::State & state) { \ + benchmarkMillisecondNewYork(state); \ + } \ + BENCHMARK_F(Fixture, WeekNoTZ) \ + (benchmark::State & state) { \ + benchmarkWeekNoTZ(state); \ + } \ + BENCHMARK_F(Fixture, WeekConstTzUTC) \ + (benchmark::State & state) { \ + benchmarkWeekConstTzUTC(state); \ + } \ + BENCHMARK_F(Fixture, WeekConstTzUTCMinus0700) \ + (benchmark::State & state) { \ + benchmarkWeekConstTzUTCMinus0700(state); \ + } \ + BENCHMARK_F(Fixture, WeekConstTzNewYork) \ + (benchmark::State & state) { \ + benchmarkWeekConstTzNewYork(state); \ + } \ + BENCHMARK_F(Fixture, WeekUTC) \ + (benchmark::State & state) { \ + benchmarkWeekUTC(state); \ + } \ + BENCHMARK_F(Fixture, WeekUTCMinus0700) \ + (benchmark::State & state) { \ + benchmarkWeekUTCMinus0700(state); \ + } \ + BENCHMARK_F(Fixture, WeekNewYork) \ + (benchmark::State & state) { \ + benchmarkWeekNewYork(state); \ + } \ + BENCHMARK_F(Fixture, ISOWeekYearNoTZ) \ + (benchmark::State & state) { \ + benchmarkISOWeekYearNoTZ(state); \ + } \ + BENCHMARK_F(Fixture, ISOWeekYearConstTzUTC) \ + (benchmark::State & state) { \ + benchmarkISOWeekYearConstTzUTC(state); \ + } \ + BENCHMARK_F(Fixture, ISOWeekYearConstTzUTCMinus0700) \ + (benchmark::State & state) { \ + benchmarkISOWeekYearConstTzUTCMinus0700(state); \ + } \ + BENCHMARK_F(Fixture, ISOWeekYearConstTzNewYork) \ + (benchmark::State & state) { \ + benchmarkISOWeekYearConstTzNewYork(state); \ + } \ + BENCHMARK_F(Fixture, ISOWeekYearUTC) \ + (benchmark::State & state) { \ + benchmarkISOWeekYearUTC(state); \ + } \ + BENCHMARK_F(Fixture, ISOWeekYearUTCMinus0700) \ + (benchmark::State & state) { \ + benchmarkISOWeekYearUTCMinus0700(state); \ + } \ + BENCHMARK_F(Fixture, ISOWeekYearNewYork) \ + (benchmark::State & state) { \ + benchmarkISOWeekYearNewYork(state); \ + } \ + BENCHMARK_F(Fixture, ISODayOfWeekNoTZ) \ + (benchmark::State & state) { \ + benchmarkISODayOfWeekNoTZ(state); \ + } \ + BENCHMARK_F(Fixture, ISODayOfWeekConstTzUTC) \ + (benchmark::State & state) { \ + benchmarkISODayOfWeekConstTzUTC(state); \ + } \ + BENCHMARK_F(Fixture, ISODayOfWeekConstTzUTCMinus0700) \ + (benchmark::State & state) { \ + benchmarkISODayOfWeekConstTzUTCMinus0700(state); \ + } \ + BENCHMARK_F(Fixture, ISODayOfWeekConstTzNewYork) \ + (benchmark::State & state) { \ + benchmarkISODayOfWeekConstTzNewYork(state); \ + } \ + BENCHMARK_F(Fixture, ISODayOfWeekUTC) \ + (benchmark::State & state) { \ + benchmarkISODayOfWeekUTC(state); \ + } \ + BENCHMARK_F(Fixture, ISODayOfWeekUTCMinus0700) \ + (benchmark::State & state) { \ + benchmarkISODayOfWeekUTCMinus0700(state); \ + } \ + BENCHMARK_F(Fixture, ISODayOfWeekNewYork) \ + (benchmark::State & state) { \ + benchmarkISODayOfWeekNewYork(state); \ + } \ + BENCHMARK_F(Fixture, ISOWeekNoTZ) \ + (benchmark::State & state) { \ + benchmarkISOWeekNoTZ(state); \ + } \ + BENCHMARK_F(Fixture, ISOWeekConstTzUTC) \ + (benchmark::State & state) { \ + benchmarkISOWeekConstTzUTC(state); \ + } \ + BENCHMARK_F(Fixture, ISOWeekConstTzUTCMinus0700) \ + (benchmark::State & state) { \ + benchmarkISOWeekConstTzUTCMinus0700(state); \ + } \ + BENCHMARK_F(Fixture, ISOWeekConstTzNewYork) \ + (benchmark::State & state) { \ + benchmarkISOWeekConstTzNewYork(state); \ + } \ + BENCHMARK_F(Fixture, ISOWeekUTC) \ + (benchmark::State & state) { \ + benchmarkISOWeekUTC(state); \ + } \ + BENCHMARK_F(Fixture, ISOWeekUTCMinus0700) \ + (benchmark::State & state) { \ + benchmarkISOWeekUTCMinus0700(state); \ + } \ + BENCHMARK_F(Fixture, ISOWeekNewYork) \ + (benchmark::State & state) { \ + benchmarkISOWeekNewYork(state); \ + } \ BENCHMARK_F(Fixture, GetFieldEvaluateExpression) \ (benchmark::State & state) { \ benchmarkGetFieldEvaluateExpression(state); \ diff --git a/src/mongo/db/query/sbe_stage_builder_expression.cpp b/src/mongo/db/query/sbe_stage_builder_expression.cpp index 7af0638bebe..47d96dec7c0 100644 --- a/src/mongo/db/query/sbe_stage_builder_expression.cpp +++ b/src/mongo/db/query/sbe_stage_builder_expression.cpp @@ -3066,31 +3066,31 @@ public: generateDateExpressionAcceptingTimeZone("dayOfYear", expr); } void visit(const ExpressionHour* expr) final { - unsupportedExpression("$hour"); + generateDateExpressionAcceptingTimeZone("hour", expr); } void visit(const ExpressionMillisecond* expr) final { - unsupportedExpression("$millisecond"); + generateDateExpressionAcceptingTimeZone("millisecond", expr); } void visit(const ExpressionMinute* expr) final { - unsupportedExpression("$minute"); + generateDateExpressionAcceptingTimeZone("minute", expr); } void visit(const ExpressionMonth* expr) final { - unsupportedExpression("$month"); + generateDateExpressionAcceptingTimeZone("month", expr); } void visit(const ExpressionSecond* expr) final { - unsupportedExpression("$second"); + generateDateExpressionAcceptingTimeZone("second", expr); } void visit(const ExpressionWeek* expr) final { - unsupportedExpression("$week"); + generateDateExpressionAcceptingTimeZone("week", expr); } void visit(const ExpressionIsoWeekYear* expr) final { - unsupportedExpression("$isoWeekYear"); + generateDateExpressionAcceptingTimeZone("isoWeekYear", expr); } void visit(const ExpressionIsoDayOfWeek* expr) final { - unsupportedExpression("$isoDayOfWeek"); + generateDateExpressionAcceptingTimeZone("isoDayOfWeek", expr); } void visit(const ExpressionIsoWeek* expr) final { - unsupportedExpression("$isoWeek"); + generateDateExpressionAcceptingTimeZone("isoWeek", expr); } void visit(const ExpressionYear* expr) final { generateDateExpressionAcceptingTimeZone("year", expr); |