diff options
author | Projjal Chanda <projjal.chanda@mongodb.com> | 2023-03-29 21:14:44 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2023-03-29 23:13:03 +0000 |
commit | 2d234e665d21d700cadc2d550b764c64ba180779 (patch) | |
tree | c572ca0eaae52df793f23848457003a052138e84 /src/mongo/db/exec | |
parent | 81241aab38636cad5ae569e16e5b429f0ac155bf (diff) | |
download | mongo-2d234e665d21d700cadc2d550b764c64ba180779.tar.gz |
SERVER-51570: Added date time expressions to sbe
Diffstat (limited to 'src/mongo/db/exec')
-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 |
5 files changed, 1058 insertions, 0 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); |