summaryrefslogtreecommitdiff
path: root/src/mongo/db/exec
diff options
context:
space:
mode:
authorProjjal Chanda <projjal.chanda@mongodb.com>2023-03-29 21:14:44 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2023-03-29 23:13:03 +0000
commit2d234e665d21d700cadc2d550b764c64ba180779 (patch)
treec572ca0eaae52df793f23848457003a052138e84 /src/mongo/db/exec
parent81241aab38636cad5ae569e16e5b429f0ac155bf (diff)
downloadmongo-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.cpp12
-rw-r--r--src/mongo/db/exec/sbe/expressions/sbe_date_expression_accepting_timezone_test.cpp512
-rw-r--r--src/mongo/db/exec/sbe/vm/datetime.cpp252
-rw-r--r--src/mongo/db/exec/sbe/vm/vm.cpp173
-rw-r--r--src/mongo/db/exec/sbe/vm/vm.h109
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);