public static Term ConvertAppendToTerm(MethodCallExpression methodCall, DefaultExpressionConverterFactory.RecursiveMapDelegate recursiveMap, IDatumConverterFactory datumConverterFactory, IExpressionConverterFactory expressionConverterFactory) { var target = methodCall.Arguments[0]; var appendArray = methodCall.Arguments[1]; if (appendArray.NodeType != ExpressionType.NewArrayInit) throw new NotSupportedException(String.Format("Expected second arg to ReQLExpression.Append to be NewArrayInit, but was: {0}", appendArray.NodeType)); var newArrayExpression = (NewArrayExpression)appendArray; var term = recursiveMap(target); foreach (var datumExpression in newArrayExpression.Expressions) { var newTerm = new Term() { type = Term.TermType.APPEND }; newTerm.args.Add(term); if (datumExpression.NodeType == ExpressionType.MemberInit) { var memberInit = (MemberInitExpression)datumExpression; newTerm.args.Add(recursiveMap(memberInit)); } else throw new NotSupportedException(String.Format("Expected ReQLExpression.Append to contain MemberInit additions, but was: {0}", datumExpression.NodeType)); term = newTerm; } return term; }
public void CustomBinaryExpressionConverterTest() { var datumConverterFactory = Substitute.For<IDatumConverterFactory>(); var expresionConverterFactory = new DefaultExpressionConverterFactory(); expresionConverterFactory.RegisterBinaryExpressionMapping<DateTime, DateTime>(ExpressionType.Subtract, CustomBinaryExpressionConverter); var expressionConverter = expresionConverterFactory.CreateExpressionConverter<TimeSpan>(datumConverterFactory); var term = expressionConverter.CreateFunctionTerm(() => DateTime.Now - DateTime.Now); Assert.That(term, Is.Not.Null); Assert.That(term.type, Is.EqualTo(Term.TermType.DATUM)); // not SUB; our custom converter was involved }
public void CustomUnaryExpressionConverterTest() { var datumConverterFactory = Substitute.For<IDatumConverterFactory>(); var expresionConverterFactory = new DefaultExpressionConverterFactory(); expresionConverterFactory.RegisterUnaryExpressionMapping<bool>(ExpressionType.Not, CustomUnaryExpressionConverter); bool value = new Random().NextDouble() > 0.5; var expressionConverter = expresionConverterFactory.CreateExpressionConverter<bool>(datumConverterFactory); var term = expressionConverter.CreateFunctionTerm(() => !value); Assert.That(term, Is.Not.Null); Assert.That(term.type, Is.EqualTo(Term.TermType.DATUM)); // not NOT; our custom converter was involved }
public void CustomBinaryExpressionConverterTest() { var datumConverterFactory = Substitute.For <IDatumConverterFactory>(); var expresionConverterFactory = new DefaultExpressionConverterFactory(); expresionConverterFactory.RegisterBinaryExpressionMapping <DateTime, DateTime>(ExpressionType.Subtract, CustomBinaryExpressionConverter); var expressionConverter = expresionConverterFactory.CreateExpressionConverter <TimeSpan>(datumConverterFactory); var term = expressionConverter.CreateFunctionTerm(() => DateTime.Now - DateTime.Now); Assert.That(term, Is.Not.Null); Assert.That(term.type, Is.EqualTo(Term.TermType.DATUM)); // not SUB; our custom converter was involved }
public static void RegisterOnConverterFactory(DefaultExpressionConverterFactory expressionConverterFactory) { expressionConverterFactory.RegisterTemplateMapping<int?, bool>( v => v.HasValue, v => new Term() { type = Term.TermType.NE, args = { v, new Term() { type = Term.TermType.DATUM, datum = new Datum() { type = Datum.DatumType.R_NULL } } } } ); }
private Term CustomUnaryExpressionConverter( UnaryExpression expr, DefaultExpressionConverterFactory.RecursiveMapDelegate recursiveMap, IDatumConverterFactory datumConverterFactory, IExpressionConverterFactory expressionConverterFactory) { return new Term() { type = Term.TermType.DATUM, datum = new Datum() { type = Datum.DatumType.R_STR, r_str = "Woot woot!", } }; }
public static void RegisterOnConverterFactory(DefaultExpressionConverterFactory expressionConverterFactory) { expressionConverterFactory.RegisterTemplateMapping<string, string>( s => s.ToLowerInvariant(), s => new Term() { type = Term.TermType.DOWNCASE, args = { s } }); expressionConverterFactory.RegisterTemplateMapping<string, string>( s => s.ToUpperInvariant(), s => new Term() { type = Term.TermType.UPCASE, args = { s } }); expressionConverterFactory.RegisterTemplateMapping<string, string, MatchResponse>( (@string, regexp) => ReQLExpression.Match(@string, regexp), (@string, regexp) => new Term() { type = Term.TermType.MATCH, args = { @string, regexp } }); }
public void CustomUnaryExpressionConverterTest() { var datumConverterFactory = Substitute.For <IDatumConverterFactory>(); var expresionConverterFactory = new DefaultExpressionConverterFactory(); expresionConverterFactory.RegisterUnaryExpressionMapping <bool>(ExpressionType.Not, CustomUnaryExpressionConverter); bool value = new Random().NextDouble() > 0.5; var expressionConverter = expresionConverterFactory.CreateExpressionConverter <bool>(datumConverterFactory); var term = expressionConverter.CreateFunctionTerm(() => !value); Assert.That(term, Is.Not.Null); Assert.That(term.type, Is.EqualTo(Term.TermType.DATUM)); // not NOT; our custom converter was involved }
public static Term ConvertEnumerableAnyToTerm(MethodCallExpression methodCall, DefaultExpressionConverterFactory.RecursiveMapDelegate recursiveMap, IDatumConverterFactory datumConverterFactory, IExpressionConverterFactory expressionConverterFactory) { var target = methodCall.Arguments[0]; var predicate = methodCall.Arguments[1]; var filterTerm = new Term() { type = Term.TermType.CONTAINS }; filterTerm.args.Add(recursiveMap(target)); var enumerableElementType = methodCall.Method.GetGenericArguments()[0]; var createFunctionTermMethod = typeof(ExpressionUtils) .GetMethods(BindingFlags.Public | BindingFlags.Static) .Single(m => m.Name == "CreateFunctionTerm" && m.GetGenericArguments().Length == 2); createFunctionTermMethod = createFunctionTermMethod.MakeGenericMethod(enumerableElementType, typeof(bool)); var functionTerm = (Term)createFunctionTermMethod.Invoke(null, new object[] { new QueryConverter(datumConverterFactory, expressionConverterFactory), predicate }); filterTerm.args.Add(functionTerm); return filterTerm; }
public static void RegisterOnConverterFactory(DefaultExpressionConverterFactory expressionConverterFactory) { expressionConverterFactory.RegisterTemplateMapping<Dictionary<string, object>, string, bool>( (d, k) => d.ContainsKey(k), (d, k) => new Term() { type = Term.TermType.HAS_FIELDS, args = { d, k } }); expressionConverterFactory.RegisterTemplateMapping<Dictionary<string, object>, string, object>( (d, k) => d[k], (d, k) => new Term() { type = Term.TermType.GET_FIELD, args = { d, k } }); expressionConverterFactory.RegisterTemplateMapping<Dictionary<string, object>, string, object, Dictionary<string, object>>( (d, k, v) => d.SetValue(k, v), (d, k, v) => new Term() { type = Term.TermType.MERGE, args = { d, new Term() { type = Term.TermType.OBJECT, args = { k, v } } } }); expressionConverterFactory.RegisterTemplateMapping<Dictionary<string, object>, Dictionary<string, object>.KeyCollection>( (d) => d.Keys, (d) => new Term() { type = Term.TermType.KEYS, args = { d } }); // There's no RethinkDB command to get the "values" of an object; so, return the actual dictionary when // accessing .Values and assume the datum converter will do the right thing for this type. expressionConverterFactory.RegisterTemplateMapping<Dictionary<string, object>, Dictionary<string, object>.ValueCollection>( (d) => d.Values, (d) => d); expressionConverterFactory.RegisterTemplateMapping<Dictionary<string, object>, string, Dictionary<string, object>>( (d, k) => d.Without(k), (d, k) => new Term() { type = Term.TermType.WITHOUT, args = { d, k } }); }
public static void RegisterDateTimeAddMethods(DefaultExpressionConverterFactory expressionConverterFactory) { expressionConverterFactory.RegisterTemplateMapping<DateTime, TimeSpan, DateTime>( (dt, timespan) => dt.Add(timespan), (dt, timespan) => Add(dt, timespan)); expressionConverterFactory.RegisterTemplateMapping<DateTimeOffset, TimeSpan, DateTimeOffset>( (dt, timespan) => dt.Add(timespan), (dt, timespan) => Add(dt, timespan)); expressionConverterFactory.RegisterTemplateMapping<DateTime, double, DateTime>( (dt, minutes) => dt.AddMinutes(minutes), (dt, minutes) => Add(dt, MinutesToSeconds(minutes))); expressionConverterFactory.RegisterTemplateMapping<DateTimeOffset, double, DateTimeOffset>( (dt, minutes) => dt.AddMinutes(minutes), (dt, minutes) => Add(dt, MinutesToSeconds(minutes))); expressionConverterFactory.RegisterTemplateMapping<DateTime, double, DateTime>( (dt, seconds) => dt.AddSeconds(seconds), (dt, seconds) => Add(dt, seconds)); expressionConverterFactory.RegisterTemplateMapping<DateTimeOffset, double, DateTimeOffset>( (dt, seconds) => dt.AddSeconds(seconds), (dt, seconds) => Add(dt, seconds)); expressionConverterFactory.RegisterTemplateMapping<DateTime, double, DateTime>( (dt, hours) => dt.AddHours(hours), (dt, hours) => Add(dt, HoursToSeconds(hours))); expressionConverterFactory.RegisterTemplateMapping<DateTimeOffset, double, DateTimeOffset>( (dt, hours) => dt.AddHours(hours), (dt, hours) => Add(dt, HoursToSeconds(hours))); expressionConverterFactory.RegisterTemplateMapping<DateTime, double, DateTime>( (dt, ms) => dt.AddMilliseconds(ms), (dt, ms) => Add(dt, MillisecondsToSeconds(ms))); expressionConverterFactory.RegisterTemplateMapping<DateTimeOffset, double, DateTimeOffset>( (dt, ms) => dt.AddMilliseconds(ms), (dt, ms) => Add(dt, MillisecondsToSeconds(ms))); expressionConverterFactory.RegisterTemplateMapping<DateTime, long, DateTime>( (dt, ticks) => dt.AddTicks(ticks), (dt, ticks) => Add(dt, TicksToSeconds(ticks))); expressionConverterFactory.RegisterTemplateMapping<DateTimeOffset, long, DateTimeOffset>( (dt, ticks) => dt.AddTicks(ticks), (dt, ticks) => Add(dt, TicksToSeconds(ticks))); expressionConverterFactory.RegisterTemplateMapping<DateTime, double, DateTime>( (dt, days) => dt.AddDays(days), (dt, days) => Add(dt, DaysToSeconds(days))); expressionConverterFactory.RegisterTemplateMapping<DateTimeOffset, double, DateTimeOffset>( (dt, days) => dt.AddDays(days), (dt, days) => Add(dt, DaysToSeconds(days))); }
public static void RegisterTimeSpanConstructors(DefaultExpressionConverterFactory expressionConverterFactory) { expressionConverterFactory.RegisterTemplateMapping<long, TimeSpan>( (ticks) => new TimeSpan(ticks), (ticks) => TicksToSeconds(ticks) ); expressionConverterFactory.RegisterTemplateMapping<int, int, int, TimeSpan>( (hours, minutes, seconds) => new TimeSpan(hours, minutes, seconds), (hours, minutes, seconds) => Add( HoursToSeconds(hours), MinutesToSeconds(minutes), seconds ) ); expressionConverterFactory.RegisterTemplateMapping<int, int, int, int, TimeSpan>( (days, hours, minutes, seconds) => new TimeSpan(days, hours, minutes, seconds), (days, hours, minutes, seconds) => Add( DaysToSeconds(days), HoursToSeconds(hours), MinutesToSeconds(minutes), seconds ) ); expressionConverterFactory.RegisterTemplateMapping<int, int, int, int, int, TimeSpan>( (days, hours, minutes, seconds, milliseconds) => new TimeSpan(days, hours, minutes, seconds, milliseconds), (days, hours, minutes, seconds, milliseconds) => Add( DaysToSeconds(days), HoursToSeconds(hours), MinutesToSeconds(minutes), seconds, MillisecondsToSeconds(milliseconds) ) ); expressionConverterFactory.RegisterTemplateMapping<double, TimeSpan>( (days) => TimeSpan.FromDays(days), DaysToSeconds ); expressionConverterFactory.RegisterTemplateMapping<double, TimeSpan>( (hours) => TimeSpan.FromHours(hours), HoursToSeconds ); expressionConverterFactory.RegisterTemplateMapping<double, TimeSpan>( (milliseconds) => TimeSpan.FromMilliseconds(milliseconds), MillisecondsToSeconds ); expressionConverterFactory.RegisterTemplateMapping<double, TimeSpan>( (minutes) => TimeSpan.FromMinutes(minutes), MinutesToSeconds ); expressionConverterFactory.RegisterTemplateMapping<double, TimeSpan>( (seconds) => TimeSpan.FromSeconds(seconds), term => term ); expressionConverterFactory.RegisterTemplateMapping<long, TimeSpan>( (ticks) => TimeSpan.FromTicks(ticks), TicksToSeconds ); }
public static void RegisterOnConverterFactory(DefaultExpressionConverterFactory expressionConverterFactory) { RegisterDateTimeConstructors(expressionConverterFactory); RegisterDateTimeAddMethods(expressionConverterFactory); RegisterDateTimeAccessors(expressionConverterFactory); RegisterTimeSpanConstructors(expressionConverterFactory); }
public static void RegisterDateTimeConstructors(DefaultExpressionConverterFactory expressionConverterFactory) { expressionConverterFactory.RegisterTemplateMapping<DateTime>( () => DateTime.UtcNow, () => new Term() { type = Term.TermType.NOW }); expressionConverterFactory.RegisterTemplateMapping<DateTimeOffset>( () => DateTimeOffset.UtcNow, () => new Term() { type = Term.TermType.NOW }); expressionConverterFactory.RegisterTemplateMapping<int, int, int, DateTime>( (year, month, day) => new DateTime(year, month, day), (year, month, day) => new Term() { type = Term.TermType.TIME, args = { year, month, day, String("Z") } }); expressionConverterFactory.RegisterTemplateMapping<int, int, int, int, int, int, DateTime>( (year, month, day, hour, minute, second) => new DateTime(year, month, day, hour, minute, second), (year, month, day, hour, minute, second) => new Term() { type = Term.TermType.TIME, args = { year, month, day, hour, minute, second, String("Z") } }); expressionConverterFactory.RegisterTemplateMapping<int, int, int, int, int, int, int, DateTime>( (year, month, day, hour, minute, second, millisecond) => new DateTime(year, month, day, hour, minute, second, millisecond), (year, month, day, hour, minute, second, millisecond) => new Term() { type = Term.TermType.TIME, args = { year, month, day, hour, minute, Add(second, Binary(millisecond, Term.TermType.DIV, 1000)), String("Z") } }); // new DateTimeOffset in .NET creates a DateTimeOffset with either local time offset, or UTC offset, // depending upon the DateTime's Kind property. We can't really support that because we're not actually // working with DateTime objects on the RethinkDB side; we're working with ReQL times that already have // offsets associated with them. So... this is basically a NOOP. expressionConverterFactory.RegisterTemplateMapping<DateTime, DateTimeOffset>( (dt) => new DateTimeOffset(dt), (dt) => dt); // But creating a DateTimeOffset with a specific timezone isn't a NOOP. This is re-interpreting the given // time at the given timezone (not converting it). expressionConverterFactory.RegisterTemplateMapping<DateTime, TimeSpan, DateTimeOffset>( (dt, offset) => new DateTimeOffset(dt, offset), (dt, offset) => new Term() { type = Term.TermType.TIME, // Well, this is awkward, but... break the time up and construct it again with the specified // TZ offset. args = { new Term() { type = Term.TermType.YEAR, args = { dt } }, new Term() { type = Term.TermType.MONTH, args = { dt } }, new Term() { type = Term.TermType.DAY, args = { dt } }, new Term() { type = Term.TermType.HOURS, args = { dt } }, new Term() { type = Term.TermType.MINUTES, args = { dt } }, new Term() { type = Term.TermType.SECONDS, args = { dt } }, TimeSpanToOffset(offset), } }); // epoch = (UtcTicks - 621355968000000000) / 10000000.0 expressionConverterFactory.RegisterTemplateMapping<long, TimeSpan, DateTimeOffset>( (ticks, offset) => new DateTimeOffset(ticks, offset), (ticks, offset) => new Term() { type = Term.TermType.IN_TIMEZONE, args = { new Term() { type = Term.TermType.EPOCH_TIME, args = { Binary( Binary( Binary(ticks, Term.TermType.SUB, 621355968000000000), Term.TermType.DIV, 10000000 ), Term.TermType.SUB, offset ) } }, TimeSpanToOffset(offset) } }); expressionConverterFactory.RegisterTemplateMapping<int, int, int, int, int, int, TimeSpan, DateTimeOffset>( (year, month, day, hour, minute, second, offset) => new DateTimeOffset(year, month, day, hour, minute, second, offset), (year, month, day, hour, minute, second, offset) => new Term() { type = Term.TermType.TIME, args = { year, month, day, hour, minute, second, TimeSpanToOffset(offset) } }); expressionConverterFactory.RegisterTemplateMapping<int, int, int, int, int, int, int, TimeSpan, DateTimeOffset>( (year, month, day, hour, minute, second, millisecond, offset) => new DateTimeOffset(year, month, day, hour, minute, second, millisecond, offset), (year, month, day, hour, minute, second, millisecond, offset) => new Term() { type = Term.TermType.TIME, args = { year, month, day, hour, minute, Add(second, Binary(millisecond, Term.TermType.DIV, 1000)), TimeSpanToOffset(offset) } }); }
public static void RegisterOnConverterFactory(DefaultExpressionConverterFactory expressionConverterFactory) { var appendDelegate = (AppendDelegate<int>)ReQLExpression.Append; expressionConverterFactory.RegisterMethodCallMapping(appendDelegate.Method, ConvertAppendToTerm); var whereDelegate = (WhereDelegate<int>)Enumerable.Where; expressionConverterFactory.RegisterMethodCallMapping(whereDelegate.Method, ConvertEnumerableWhereToTerm); var anyDelegate = (AnyDelegate<int>)Enumerable.Any; expressionConverterFactory.RegisterMethodCallMapping(anyDelegate.Method, ConvertEnumerableAnyToTerm); expressionConverterFactory.RegisterTemplateMapping<IEnumerable<int>, int, bool>( (list, arg) => list.Contains(arg), (list, arg) => new Term() { type = Term.TermType.CONTAINS, args = { list, arg } }); expressionConverterFactory.RegisterTemplateMapping<IList<int>, int, bool>( (list, arg) => list.Contains(arg), (list, arg) => new Term() { type = Term.TermType.CONTAINS, args = { list, arg } }); expressionConverterFactory.RegisterTemplateMapping<List<int>, int, bool>( (list, arg) => list.Contains(arg), (list, arg) => new Term() { type = Term.TermType.CONTAINS, args = { list, arg } }); expressionConverterFactory.RegisterTemplateMapping<IEnumerable<int>, int>( list => list.Count(), list => Count(list) ); expressionConverterFactory.RegisterTemplateMapping<List<int>, int>( list => list.Count, list => Count(list) ); expressionConverterFactory.RegisterTemplateMapping<ICollection<int>, int>( list => list.Count, list => Count(list) ); expressionConverterFactory.RegisterTemplateMapping<int[], int, int[]>( (list, startIndex) => ReQLExpression.Slice(list, startIndex), (list, startIndex) => new Term() { type = Term.TermType.SLICE, args = { list, startIndex } }); expressionConverterFactory.RegisterTemplateMapping<int[], int, int, int[]>( (list, startIndex, endIndex) => ReQLExpression.Slice(list, startIndex, endIndex), (list, startIndex, endIndex) => new Term() { type = Term.TermType.SLICE, args = { list, startIndex, endIndex } }); expressionConverterFactory.RegisterTemplateMapping<int[], int, int, Bound, Bound, int[]>( (list, startIndex, endIndex, leftBound, rightBound) => ReQLExpression.Slice(list, startIndex, endIndex, leftBound, rightBound), (list, startIndex, endIndex, leftBound, rightBound) => new Term() { type = Term.TermType.SLICE, args = { list, startIndex, endIndex }, optargs = { new Term.AssocPair() { key = "left_bound", val = leftBound, }, new Term.AssocPair() { key = "right_bound", val = rightBound, } } }); expressionConverterFactory.RegisterTemplateMapping<string, int>( (errorMessage) => ReQLExpression.Error<int>(errorMessage), (errorMessage) => new Term() { type = Term.TermType.ERROR, args = { errorMessage } }); }
public static void RegisterDateTimeAccessors(DefaultExpressionConverterFactory expressionConverterFactory) { expressionConverterFactory.RegisterTemplateMapping<DateTime, int>( dt => dt.Year, dt => new Term() { type = Term.TermType.YEAR, args = { dt } } ); expressionConverterFactory.RegisterTemplateMapping<DateTimeOffset, int>( dt => dt.Year, dt => new Term() { type = Term.TermType.YEAR, args = { dt } } ); expressionConverterFactory.RegisterTemplateMapping<DateTime, int>( dt => dt.Month, dt => new Term() { type = Term.TermType.MONTH, args = { dt } } ); expressionConverterFactory.RegisterTemplateMapping<DateTimeOffset, int>( dt => dt.Month, dt => new Term() { type = Term.TermType.MONTH, args = { dt } } ); expressionConverterFactory.RegisterTemplateMapping<DateTime, int>( dt => dt.Day, dt => new Term() { type = Term.TermType.DAY, args = { dt } } ); expressionConverterFactory.RegisterTemplateMapping<DateTimeOffset, int>( dt => dt.Day, dt => new Term() { type = Term.TermType.DAY, args = { dt } } ); expressionConverterFactory.RegisterTemplateMapping<DateTime, int>( dt => dt.Hour, dt => new Term() { type = Term.TermType.HOURS, args = { dt } } ); expressionConverterFactory.RegisterTemplateMapping<DateTimeOffset, int>( dt => dt.Hour, dt => new Term() { type = Term.TermType.HOURS, args = { dt } } ); expressionConverterFactory.RegisterTemplateMapping<DateTime, int>( dt => dt.Minute, dt => new Term() { type = Term.TermType.MINUTES, args = { dt } } ); expressionConverterFactory.RegisterTemplateMapping<DateTimeOffset, int>( dt => dt.Minute, dt => new Term() { type = Term.TermType.MINUTES, args = { dt } } ); expressionConverterFactory.RegisterTemplateMapping<DateTime, int>( dt => dt.Second, dt => new Term() { type = Term.TermType.SECONDS, args = { dt } } ); expressionConverterFactory.RegisterTemplateMapping<DateTimeOffset, int>( dt => dt.Second, dt => new Term() { type = Term.TermType.SECONDS, args = { dt } } ); expressionConverterFactory.RegisterTemplateMapping<DateTime, DayOfWeek>( dt => dt.DayOfWeek, dt => new Term() { type = Term.TermType.DAY_OF_WEEK, args = { dt } } ); expressionConverterFactory.RegisterTemplateMapping<DateTimeOffset, DayOfWeek>( dt => dt.DayOfWeek, dt => new Term() { type = Term.TermType.DAY_OF_WEEK, args = { dt } } ); expressionConverterFactory.RegisterTemplateMapping<DateTime, int>( dt => dt.DayOfYear, dt => new Term() { type = Term.TermType.DAY_OF_YEAR, args = { dt } } ); expressionConverterFactory.RegisterTemplateMapping<DateTimeOffset, int>( dt => dt.DayOfYear, dt => new Term() { type = Term.TermType.DAY_OF_YEAR, args = { dt } } ); }
protected BaseExpression(DefaultExpressionConverterFactory expressionConverterFactory) { this.expressionConverterFactory = expressionConverterFactory; }
public static void RegisterOnConverterFactory(DefaultExpressionConverterFactory expressionConverterFactory) { expressionConverterFactory.RegisterTemplateMapping<Guid>( () => Guid.NewGuid(), () => new Term() { type = Term.TermType.UUID }); }