Skip to content

Commit ffcf4a0

Browse files
committed
CSHARP-4540: Add full support for $dateFromString.
1 parent fc04833 commit ffcf4a0

File tree

6 files changed

+427
-0
lines changed

6 files changed

+427
-0
lines changed

src/MongoDB.Driver.Core/Core/Misc/Feature.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ public class Feature
6666
private static readonly Feature __csfle2 = new Feature("Csfle2", WireVersion.Server60);
6767
private static readonly Feature __csfle2Qev2 = new Feature("Csfle2Qev2", WireVersion.Server70, notSupportedMessage: "Driver support of Queryable Encryption is incompatible with server. Upgrade server to use Queryable Encryption.");
6868
private static readonly Feature __currentOpCommand = new Feature("CurrentOpCommand", WireVersion.Server32);
69+
private static readonly Feature __dateFromStringFormatArgument = new Feature("DateFromStringFormatArgument", WireVersion.Server40);
6970
private static readonly Feature __dateOperatorsNewIn50 = new Feature("DateOperatorsNewIn50", WireVersion.Server50);
7071
private static readonly Feature __densifyStage = new Feature("DensifyStage", WireVersion.Server51);
7172
private static readonly Feature __documentsStage = new Feature("DocumentsStage", WireVersion.Server51);
@@ -375,6 +376,11 @@ public class Feature
375376
[Obsolete("This property will be removed in a later release.")]
376377
public static Feature CurrentOpCommand => __currentOpCommand;
377378

379+
/// <summary>
380+
/// Gets the $dateFromString format argument feature.
381+
/// </summary>
382+
public static Feature DateFromStringFormatArgument => __dateFromStringFormatArgument;
383+
378384
/// <summary>
379385
/// Gets the date operators added in 5.0 feature.
380386
/// </summary>

src/MongoDB.Driver/Linq/Linq3Implementation/Reflection/MqlMethod.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,39 @@
1313
* limitations under the License.
1414
*/
1515

16+
using System;
1617
using System.Reflection;
1718

1819
namespace MongoDB.Driver.Linq.Linq3Implementation.Reflection
1920
{
2021
internal static class MqlMethod
2122
{
2223
// private static fields
24+
private static readonly MethodInfo __dateFromString;
25+
private static readonly MethodInfo __dateFromStringWithFormat;
26+
private static readonly MethodInfo __dateFromStringWithFormatAndTimezone;
27+
private static readonly MethodInfo __dateFromStringWithFormatAndTimezoneAndOnErrorAndOnNull;
2328
private static readonly MethodInfo __exists;
2429
private static readonly MethodInfo __isMissing;
2530
private static readonly MethodInfo __isNullOrMissing;
2631

2732
// static constructor
2833
static MqlMethod()
2934
{
35+
__dateFromString = ReflectionInfo.Method((string dateStringl) => Mql.DateFromString(dateStringl));
36+
__dateFromStringWithFormat = ReflectionInfo.Method((string dateString, string format) => Mql.DateFromString(dateString, format));
37+
__dateFromStringWithFormatAndTimezone = ReflectionInfo.Method((string dateString, string format, string timezone) => Mql.DateFromString(dateString, format, timezone));
38+
__dateFromStringWithFormatAndTimezoneAndOnErrorAndOnNull = ReflectionInfo.Method((string dateString, string format, string timezone, DateTime? onError, DateTime? onNull) => Mql.DateFromString(dateString, format, timezone, onError, onNull));
3039
__exists = ReflectionInfo.Method((object field) => Mql.Exists(field));
3140
__isMissing = ReflectionInfo.Method((object field) => Mql.IsMissing(field));
3241
__isNullOrMissing = ReflectionInfo.Method((object field) => Mql.IsNullOrMissing(field));
3342
}
3443

3544
// public properties
45+
public static MethodInfo DateFromString => __dateFromString;
46+
public static MethodInfo DateFromStringWithFormat => __dateFromStringWithFormat;
47+
public static MethodInfo DateFromStringWithFormatAndTimezone => __dateFromStringWithFormatAndTimezone;
48+
public static MethodInfo DateFromStringWithFormatAndTimezoneAndOnErrorAndOnNull => __dateFromStringWithFormatAndTimezoneAndOnErrorAndOnNull;
3649
public static MethodInfo Exists => __exists;
3750
public static MethodInfo IsMissing => __isMissing;
3851
public static MethodInfo IsNullOrMissing => __isNullOrMissing;

src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/MethodCallExpressionToAggregationExpressionTranslator.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ public static AggregationExpression Translate(TranslationContext context, Method
4040
case "CovariancePopulation": return CovariancePopulationMethodToAggregationExpressionTranslator.Translate(context, expression);
4141
case "CovarianceSample": return CovarianceSampleMethodToAggregationExpressionTranslator.Translate(context, expression);
4242
case "Create": return CreateMethodToAggregationExpressionTranslator.Translate(context, expression);
43+
case "DateFromString": return DateFromStringMethodToAggregationExpressionTranslator.Translate(context, expression);
4344
case "DefaultIfEmpty": return DefaultIfEmptyMethodToAggregationExpressionTranslator.Translate(context, expression);
4445
case "DenseRank": return DenseRankMethodToAggregationExpressionTranslator.Translate(context, expression);
4546
case "Derivative": return DerivativeMethodToAggregationExpressionTranslator.Translate(context, expression);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/* Copyright 2010-present MongoDB Inc.
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
using System.Linq.Expressions;
17+
using System.Reflection;
18+
using MongoDB.Bson.Serialization;
19+
using MongoDB.Bson.Serialization.Serializers;
20+
using MongoDB.Driver.Linq.Linq3Implementation.Ast.Expressions;
21+
using MongoDB.Driver.Linq.Linq3Implementation.Misc;
22+
using MongoDB.Driver.Linq.Linq3Implementation.Reflection;
23+
24+
namespace MongoDB.Driver.Linq.Linq3Implementation.Translators.ExpressionToAggregationExpressionTranslators.MethodTranslators
25+
{
26+
internal static class DateFromStringMethodToAggregationExpressionTranslator
27+
{
28+
private static readonly MethodInfo[] __dateFromStringMethods =
29+
{
30+
MqlMethod.DateFromString,
31+
MqlMethod.DateFromStringWithFormat,
32+
MqlMethod.DateFromStringWithFormatAndTimezone,
33+
MqlMethod.DateFromStringWithFormatAndTimezoneAndOnErrorAndOnNull
34+
};
35+
36+
private static readonly MethodInfo[] __withFormatMethods =
37+
{
38+
MqlMethod.DateFromStringWithFormat,
39+
MqlMethod.DateFromStringWithFormatAndTimezone,
40+
MqlMethod.DateFromStringWithFormatAndTimezoneAndOnErrorAndOnNull
41+
};
42+
43+
private static readonly MethodInfo[] __withTimezoneMethods =
44+
{
45+
MqlMethod.DateFromStringWithFormatAndTimezone,
46+
MqlMethod.DateFromStringWithFormatAndTimezoneAndOnErrorAndOnNull
47+
};
48+
49+
public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression)
50+
{
51+
var method = expression.Method;
52+
var arguments = expression.Arguments;
53+
54+
if (method.IsOneOf(__dateFromStringMethods))
55+
{
56+
var dateStringExpression = arguments[0];
57+
var dateStringTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, dateStringExpression);
58+
var dateStringAst = dateStringTranslation.Ast;
59+
IBsonSerializer resultSerializer = DateTimeSerializer.Instance;
60+
61+
AstExpression format = null;
62+
if (method.IsOneOf(__withFormatMethods))
63+
{
64+
var formatExpression = arguments[1];
65+
var formatTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, formatExpression);
66+
format = formatTranslation.Ast;
67+
}
68+
69+
AstExpression timezoneAst = null;
70+
if (method.IsOneOf(__withTimezoneMethods))
71+
{
72+
var timezoneExpression = arguments[2];
73+
var timezoneTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, timezoneExpression);
74+
timezoneAst = timezoneTranslation.Ast;
75+
}
76+
77+
AstExpression onErrorAst = null;
78+
AstExpression onNullAst = null;
79+
if (method.Is(MqlMethod.DateFromStringWithFormatAndTimezoneAndOnErrorAndOnNull))
80+
{
81+
var onErrorExpression = arguments[3];
82+
var onErrorTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, onErrorExpression);
83+
onErrorAst = onErrorTranslation.Ast;
84+
85+
var onNullExpression = arguments[4];
86+
var onNullTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, onNullExpression);
87+
onNullAst = onNullTranslation.Ast;
88+
89+
resultSerializer = NullableSerializer.Create(resultSerializer);
90+
}
91+
92+
var ast = AstExpression.DateFromString(dateStringAst, format, timezoneAst, onErrorAst, onNullAst);
93+
return new AggregationExpression(expression, ast, resultSerializer);
94+
}
95+
96+
throw new ExpressionNotSupportedException(expression);
97+
}
98+
}
99+
}

src/MongoDB.Driver/Mql.cs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,63 @@ namespace MongoDB.Driver
2222
/// </summary>
2323
public static class Mql
2424
{
25+
/// <summary>
26+
/// Converts a string to a DateTime using the $dateFromString aggregation operator.
27+
/// </summary>
28+
/// <param name="dateString">The string.</param>
29+
/// <returns>A DateTime.</returns>
30+
public static DateTime DateFromString(string dateString)
31+
{
32+
throw new NotSupportedException("This method is not functional. It is only usable in MongoDB LINQ queries.");
33+
}
34+
35+
/// <summary>
36+
/// Converts a string to a DateTime using the $dateFromString aggregation operator.
37+
/// </summary>
38+
/// <param name="dateString">The string.</param>
39+
/// <param name="format">The format string.</param>
40+
/// <returns>A DateTime.</returns>
41+
public static DateTime DateFromString(
42+
string dateString,
43+
string format)
44+
{
45+
throw new NotSupportedException("This method is not functional. It is only usable in MongoDB LINQ queries.");
46+
}
47+
48+
/// <summary>
49+
/// Converts a string to a DateTime using the $dateFromString aggregation operator.
50+
/// </summary>
51+
/// <param name="dateString">The string.</param>
52+
/// <param name="format">The format string.</param>
53+
/// <param name="timezone">The time zone.</param>
54+
/// <returns>A DateTime.</returns>
55+
public static DateTime DateFromString(
56+
string dateString,
57+
string format,
58+
string timezone)
59+
{
60+
throw new NotSupportedException("This method is not functional. It is only usable in MongoDB LINQ queries.");
61+
}
62+
63+
/// <summary>
64+
/// Converts a string to a DateTime using the $dateFromString aggregation operator.
65+
/// </summary>
66+
/// <param name="dateString">The string.</param>
67+
/// <param name="format">The format string.</param>
68+
/// <param name="timezone">The time zone.</param>
69+
/// <param name="onError">The onError value.</param>
70+
/// <param name="onNull">The onNull value.</param>
71+
/// <returns>A DateTime.</returns>
72+
public static DateTime? DateFromString(
73+
string dateString,
74+
string format,
75+
string timezone,
76+
DateTime? onError,
77+
DateTime? onNull)
78+
{
79+
throw new NotSupportedException("This method is not functional. It is only usable in MongoDB LINQ queries.");
80+
}
81+
2582
/// <summary>
2683
/// Tests whether a field exists.
2784
/// </summary>

0 commit comments

Comments
 (0)