public Term GenerateTerm(IDatumConverterFactory datumConverterFactory) { var retval = new Term() { type = Term.TermType.GROUPED_MAP_REDUCE, }; retval.args.Add(sequenceQuery.GenerateTerm(datumConverterFactory)); retval.args.Add(ExpressionUtils.CreateFunctionTerm(datumConverterFactory, grouping)); retval.args.Add(ExpressionUtils.CreateFunctionTerm(datumConverterFactory, mapping)); retval.args.Add(ExpressionUtils.CreateFunctionTerm(datumConverterFactory, reduction)); if (this.baseProvided) { retval.optargs.Add(new Term.AssocPair() { key = "base", val = new Term() { type = Term.TermType.DATUM, datum = datumConverterFactory.Get <TMap>().ConvertObject(@base) } }); } return(retval); }
public static Tuple <bool, IDatumConverter> TryGet(IDatumConverterFactory target, IDatumConverterFactory rootDatumConverterFactory) { IDatumConverter <T> datumConverter; bool success = target.TryGet <T>(rootDatumConverterFactory, out datumConverter); return(new Tuple <bool, IDatumConverter>(success, datumConverter)); }
public void TestFixtureSetUp() { datumConverterFactory = new AggregateDatumConverterFactory( PrimitiveDatumConverterFactory.Instance, DataContractDatumConverterFactory.Instance ); }
public override bool TryGet <T>(IDatumConverterFactory rootDatumConverterFactory, out IDatumConverter <T> datumConverter) { if (typeof(T).IsGenericType && typeof(T).GetGenericTypeDefinition().Equals(typeof(List <>))) { Type listDatumConverterType = typeof(ListDatumConverter <>).MakeGenericType( typeof(T).GetGenericArguments()[0] ); datumConverter = (IDatumConverter <T>)Activator.CreateInstance(listDatumConverterType, rootDatumConverterFactory); return(true); } if (typeof(T).IsGenericType && typeof(T).GetGenericTypeDefinition().Equals(typeof(IList <>))) { Type listDatumConverterType = typeof(IListDatumConverter <>).MakeGenericType( typeof(T).GetGenericArguments()[0] ); datumConverter = (IDatumConverter <T>)Activator.CreateInstance(listDatumConverterType, rootDatumConverterFactory); return(true); } datumConverter = null; return(false); }
public Term GenerateTerm(IDatumConverterFactory datumConverterFactory) { var getAllTerm = new Term() { type = Term.TermType.GET_ALL, }; getAllTerm.args.Add(tableTerm.GenerateTerm(datumConverterFactory)); getAllTerm.args.Add(new Term() { type = Term.TermType.DATUM, datum = datumConverterFactory.Get <TKey>().ConvertObject(key) }); if (!String.IsNullOrEmpty(indexName)) { getAllTerm.optargs.Add(new Term.AssocPair() { key = "index", val = new Term() { type = Term.TermType.DATUM, datum = new Datum() { type = Datum.DatumType.R_STR, r_str = indexName }, } }); } return(getAllTerm); }
public void TestFixtureSetUp() { datumConverterFactory = Substitute.For<IDatumConverterFactory>(); queryConverter = new QueryConverter(datumConverterFactory, expressionConverterFactory); var stringDatum = new Datum() { type = Datum.DatumType.R_STR, r_str = "Jackpot!", }; var stringDatumConverter = Substitute.For<IDatumConverter<string>>(); stringDatumConverter .ConvertObject("Jackpot!") .Returns(stringDatum); stringDatumConverter .ConvertDatum(Arg.Is<Datum>(d => d.type == stringDatum.type && d.r_str == stringDatum.r_str)) .Returns("Jackpot!"); IDatumConverter<string> value; datumConverterFactory .TryGet<string>(queryConverter, out value) .Returns(args => { args[1] = stringDatumConverter; return true; }); IDatumConverter value2; datumConverterFactory .TryGet(typeof(string), queryConverter, out value2) .Returns(args => { args[2] = stringDatumConverter; return true; }); }
public override bool TryGet <T>(IDatumConverterFactory rootDatumConverterFactory, out IDatumConverter <T> datumConverter) { if (rootDatumConverterFactory == null) { throw new ArgumentNullException("rootDatumConverterFactory"); } datumConverter = null; var dataContractAttribute = typeof(T).GetCustomAttribute <DataContractAttribute>(); if (dataContractAttribute == null) { return(false); } if (typeof(T).IsEnum) { // [DataContract] on an enum type isn't supported by this datum converter. It possibly should be, // as using the [EnumValue] attribute allows users to assign arbitrary text values to enums. (#146) return(false); } Type datumConverterType = TypeCache <T> .Instance.Value; datumConverter = (IDatumConverter <T>)Activator.CreateInstance(datumConverterType, rootDatumConverterFactory); return(true); }
public void TestFixtureSetUp() { datumConverterFactory = Substitute.For<IDatumConverterFactory>(); string[] strs = { "one", "two", "three" }; var stringDatumConverter = Substitute.For<IDatumConverter>(); foreach (var i in strs) { var dtm = i.ToDatum(); stringDatumConverter .ConvertObject(i) .Returns(dtm); stringDatumConverter .ConvertDatum(Arg.Is<Datum>(d => d.type == dtm.type && d.r_str == dtm.r_str)) .Returns(i); } IDatumConverter value; datumConverterFactory .TryGet(typeof(string), datumConverterFactory, out value) .Returns(args => { args[2] = stringDatumConverter; return true; }); }
public void TestFixtureSetUp() { datumConverterFactory = Substitute.For <IDatumConverterFactory>(); var intDatumConverter = Substitute.For <IDatumConverter>(); intDatumConverter.ConvertDatum(Arg.Any <Datum>()).Returns(args => (int)((Datum)args[0]).r_num); intDatumConverter.ConvertObject(Arg.Any <object>()).Returns(args => new Datum() { type = Datum.DatumType.R_NUM, r_num = (int)args [0] }); IDatumConverter value; datumConverterFactory .TryGet(typeof(int), datumConverterFactory, out value) .Returns(args => { args[2] = intDatumConverter; return(true); }); datumConverterFactory.GetBestNativeTypeForDatum(Arg.Any <Datum>()).Returns(typeof(int)); }
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 Term GenerateTerm(IDatumConverterFactory datumConverterFactory) { var term = new Term() { type = Term.TermType.SLICE, }; term.args.Add(sequenceQuery.GenerateTerm(datumConverterFactory)); term.args.Add(new Term() { type = Term.TermType.DATUM, datum = new Datum() { type = Datum.DatumType.R_NUM, r_num = startIndex, } }); term.args.Add(new Term() { type = Term.TermType.DATUM, datum = new Datum() { type = Datum.DatumType.R_NUM, r_num = endIndex.GetValueOrDefault(int.MaxValue), } }); return(term); }
public Term GenerateTerm(IDatumConverterFactory datumConverterFactory) { var reduceTerm = new Term() { type = Term.TermType.REDUCE, }; reduceTerm.args.Add(sequenceQuery.GenerateTerm(datumConverterFactory)); reduceTerm.args.Add(ExpressionUtils.CreateFunctionTerm <T, T, T>(datumConverterFactory, reduceFunction)); if (this.baseProvided) { reduceTerm.optargs.Add(new Term.AssocPair() { key = "base", val = new Term() { type = Term.TermType.DATUM, datum = datumConverterFactory.Get <T>().ConvertObject(@base) } }); } return(reduceTerm); }
public Term GenerateTerm(IDatumConverterFactory datumConverterFactory) { var replaceTerm = new Term() { type = Term.TermType.REPLACE, }; replaceTerm.args.Add(getTerm.GenerateTerm(datumConverterFactory)); replaceTerm.args.Add(new Term() { type = Term.TermType.DATUM, datum = datumConverterFactory.Get <T>().ConvertObject(newObject) }); AddOptionalArguments(replaceTerm); if (nonAtomic) { replaceTerm.optargs.Add(new Term.AssocPair() { key = "non_atomic", val = new Term() { type = Term.TermType.DATUM, datum = new Datum() { type = Datum.DatumType.R_BOOL, r_bool = nonAtomic } } }); } return(replaceTerm); }
public Term GenerateTerm(IDatumConverterFactory datumConverterFactory) { var term = new Term() { type = Term.TermType.EQ_JOIN, }; term.args.Add(leftQuery.GenerateTerm(datumConverterFactory)); term.args.Add(GetMemberName(datumConverterFactory)); term.args.Add(rightQuery.GenerateTerm(datumConverterFactory)); if (!String.IsNullOrEmpty(indexName)) { term.optargs.Add(new Term.AssocPair() { key = "index", val = new Term() { type = Term.TermType.DATUM, datum = new Datum() { type = Datum.DatumType.R_STR, r_str = indexName }, } }); } return(term); }
private Datum GetMemberName(Expression memberReference, IDatumConverterFactory datumConverterFactory) { var datumConverter = datumConverterFactory.Get <TObject>(); var fieldConverter = datumConverter as IObjectDatumConverter; if (fieldConverter == null) { throw new NotSupportedException("Cannot map member access into ReQL without implementing IObjectDatumConverter"); } MemberExpression memberExpr; if (memberReference.NodeType == ExpressionType.MemberAccess) { memberExpr = (MemberExpression)memberReference; } else { throw new NotSupportedException("Unsupported expression type " + memberReference.NodeType + "; expected MemberAccess"); } if (memberExpr.Expression.NodeType != ExpressionType.Parameter) { throw new NotSupportedException("Unrecognized member access pattern"); } return(new Datum() { type = Datum.DatumType.R_STR, r_str = fieldConverter.GetDatumFieldName(memberExpr.Member) }); }
public void TestFixtureSetUp() { datumConverterFactory = Substitute.For <IDatumConverterFactory>(); string[] strs = { "one", "two", "three", "left", "right" }; var stringDatumConverter = Substitute.For <IDatumConverter>(); foreach (var i in strs) { var dtm = i.ToDatum(); stringDatumConverter .ConvertObject(i) .Returns(dtm); stringDatumConverter .ConvertDatum(Arg.Is <Datum>(d => d.type == dtm.type && d.r_str == dtm.r_str)) .Returns(i); } IDatumConverter value; datumConverterFactory .TryGet(typeof(string), datumConverterFactory, out value) .Returns(args => { args[2] = stringDatumConverter; return(true); }); }
public async Task <T> RunAsync <T>(IDatumConverterFactory datumConverterFactory, IScalarQuery <T> queryObject, CancellationToken cancellationToken) { var query = new Spec.Query(); query.token = GetNextToken(); query.type = Spec.Query.QueryType.START; query.query = queryObject.GenerateTerm(datumConverterFactory); var response = await InternalRunQuery(query, cancellationToken); switch (response.type) { case Response.ResponseType.SUCCESS_SEQUENCE: case Response.ResponseType.SUCCESS_ATOM: if (response.response.Count != 1) { throw new RethinkDbRuntimeException(String.Format("Expected 1 object, received {0}", response.response.Count)); } return(datumConverterFactory.Get <T>().ConvertDatum(response.response[0])); case Response.ResponseType.CLIENT_ERROR: case Response.ResponseType.COMPILE_ERROR: throw new RethinkDbInternalErrorException("Client error: " + response.response[0].r_str); case Response.ResponseType.RUNTIME_ERROR: throw new RethinkDbRuntimeException("Runtime error: " + response.response[0].r_str); default: throw new RethinkDbInternalErrorException("Unhandled response type: " + response.type); } }
public void TestFixtureSetUp() { datumConverterFactory = Substitute.For <IDatumConverterFactory>(); queryConverter = new QueryConverter(datumConverterFactory, expressionConverterFactory); var stringDatum = new Datum() { type = Datum.DatumType.R_STR, r_str = "Jackpot!", }; var stringDatumConverter = Substitute.For <IDatumConverter <string> >(); stringDatumConverter .ConvertObject("Jackpot!") .Returns(stringDatum); stringDatumConverter .ConvertDatum(Arg.Is <Datum>(d => d.type == stringDatum.type && d.r_str == stringDatum.r_str)) .Returns("Jackpot!"); IDatumConverter <string> value; datumConverterFactory .TryGet <string>(queryConverter, out value) .Returns(args => { args[1] = stringDatumConverter; return(true); }); }
private string GetMemberName(IDatumConverterFactory datumConverterFactory) { var datumConverter = datumConverterFactory.Get <TObject>(); var fieldConverter = datumConverter as IObjectDatumConverter; if (fieldConverter == null) { throw new NotSupportedException("Cannot map member access into ReQL without implementing IObjectDatumConverter"); } if (numericMemberReference.NodeType != ExpressionType.Lambda) { throw new NotSupportedException("Unsupported expression type " + numericMemberReference.Type + "; expected Lambda"); } var body = ((LambdaExpression)numericMemberReference).Body; MemberExpression memberExpr; if (body.NodeType == ExpressionType.MemberAccess) { memberExpr = (MemberExpression)body; } else { throw new NotSupportedException("Unsupported expression type " + body.NodeType + "; expected MemberAccess"); } if (memberExpr.Expression.NodeType != ExpressionType.Parameter) { throw new NotSupportedException("Unrecognized member access pattern"); } return(fieldConverter.GetDatumFieldName(memberExpr.Member)); }
public Term GenerateReductionObject(IDatumConverterFactory datumConverterFactory) { if (retval == null) { var newValue = new Term() { type = Term.TermType.MAKE_OBJ }; newValue.optargs.Add(new Term.AssocPair() { key = "COUNT", val = new Term() { type = Term.TermType.DATUM, datum = new Datum() { type = Datum.DatumType.R_BOOL, r_bool = true } } }); retval = newValue; } return(retval); }
private bool ServerSideMemberAccess(IDatumConverterFactory datumConverterFactory, MemberExpression memberExpression, out Term term) { term = null; if (memberExpression.Expression == null) { // static member access; can't do that server-side, wouldn't want to either. return(false); } if (memberExpression.Expression.NodeType == ExpressionType.Constant) { // Accessing a constant; client-side conversion will be more efficient since we won't be round-tripping the object return(false); } IDatumConverter datumConverter; if (!datumConverterFactory.TryGet(memberExpression.Expression.Type, out datumConverter)) { // No datum converter for this type. return(false); } var fieldConverter = datumConverter as IObjectDatumConverter; if (fieldConverter == null) { // doesn't implement IObjectDatumConverter, so we don't know how to map the MemberInfo to the field name return(false); } var datumFieldName = fieldConverter.GetDatumFieldName(memberExpression.Member); if (string.IsNullOrEmpty(datumFieldName)) { // At this point we're not returning false because we're expecting this should work; throwing an error instead. throw new NotSupportedException(String.Format("Member {0} on type {1} could not be mapped to a datum field", memberExpression.Member.Name, memberExpression.Type)); } var getAttrTerm = new Term() { type = Term.TermType.GET_FIELD }; getAttrTerm.args.Add(RecursiveMap(memberExpression.Expression)); getAttrTerm.args.Add(new Term() { type = Term.TermType.DATUM, datum = new Datum() { type = Datum.DatumType.R_STR, r_str = datumFieldName } }); term = getAttrTerm; return(true); }
public static IDatumConverter Get(this IDatumConverterFactory datumConverterFactory, Type datumType) { if (datumConverterFactory == null) { throw new ArgumentNullException("datumConverterFactory"); } return(datumConverterFactory.Get(datumType, datumConverterFactory)); }
public QueryEnumerator(Connection connection, IDatumConverterFactory datumConverterFactory, ISequenceQuery <T> queryObject) { this.connection = connection; this.datumConverterFactory = datumConverterFactory; this.datumConverter = datumConverterFactory.Get <T>(); this.queryObject = queryObject; this.stackTrace = new StackTrace(true); }
public IAsyncEnumerator <T> RunAsync <T>(IDatumConverterFactory datumConverterFactory, ISequenceQuery <T> queryObject) { if (this.disposed) { throw new ObjectDisposedException("ReliableConnectionWrapper"); } return(new RetryAsyncEnumeratorWrapper <T>(this, () => this.innerConnection.RunAsync(datumConverterFactory, queryObject))); }
public Task <T> RunAsync <T>(IDatumConverterFactory datumConverterFactory, IScalarQuery <T> queryObject, CancellationToken cancellationToken) { if (this.disposed) { throw new ObjectDisposedException("PooledConnectionWrapper"); } return(this.innerConnection.RunAsync <T>(datumConverterFactory, queryObject, cancellationToken)); }
public void TestFixtureSetUp() { datumConverterFactory = new AggregateDatumConverterFactory( PrimitiveDatumConverterFactory.Instance, TimeSpanDatumConverterFactory.Instance, DateTimeDatumConverterFactory.Instance ); }
public IAsyncEnumerator <T> RunAsync <T>(IDatumConverterFactory datumConverterFactory, ISequenceQuery <T> queryObject) { if (this.disposed) { throw new ObjectDisposedException("PooledConnectionWrapper"); } return(this.innerConnection.RunAsync <T>(datumConverterFactory, queryObject)); }
public static IDatumConverter <T> Get <T>(this IDatumConverterFactory datumConverterFactory) { if (datumConverterFactory == null) { throw new ArgumentNullException("datumConverterFactory"); } return(datumConverterFactory.Get <T>(datumConverterFactory)); }
public Term GenerateTerm(IDatumConverterFactory datumConverterFactory) { var term = new Term() { type = Term.TermType.NOW, }; return(term); }
public override bool TryGet <T>(IDatumConverterFactory rootDatumConverterFactory, out IDatumConverter <T> datumConverter) { datumConverter = null; if (typeof(T) == typeof(Bound)) { datumConverter = (IDatumConverter <T>)BoundEnumDatumConverter.Instance; } return(datumConverter != null); }
public Term GenerateTerm(IDatumConverterFactory datumConverterFactory) { var dbTerm = new Term() { type = Term.TermType.DB_LIST, }; return(dbTerm); }
public override bool TryGet <T>(IDatumConverterFactory rootDatumConverterFactory, out IDatumConverter <T> datumConverter) { datumConverter = null; if (typeof(T).IsEnum) { datumConverter = EnumDatumConverter <T> .Instance.Value; } return(datumConverter != null); }
// This is really ugly, using a helper class and reflection to call the generic TryGet<T> method. But, // I can't see any alternative due to the generic out parameter, and I'm making the assumptions that // (a) non-generic version of TryGet will be less frequently used than the generic version, and (b) the // generic version is easier to write, so the non-generic version should be the uglier one. public bool TryGet(Type datumType, IDatumConverterFactory rootDatumConverterFactory, out IDatumConverter datumConverter) { var helperType = typeof(GenericHelper <>).MakeGenericType(datumType); var helperMethod = helperType.GetMethod("TryGet", BindingFlags.Public | BindingFlags.Static); var retval = (Tuple <bool, IDatumConverter>)helperMethod.Invoke(null, new object[] { this, rootDatumConverterFactory }); datumConverter = retval.Item2; return(retval.Item1); }
public void TestFixtureSetUp() { datumConverterFactory = new AggregateDatumConverterFactory( PrimitiveDatumConverterFactory.Instance, DataContractDatumConverterFactory.Instance ); expressionConverterFactory = new RethinkDb.Expressions.DefaultExpressionConverterFactory(); queryConverter = new QueryConverter(datumConverterFactory, expressionConverterFactory); }
public void TestFixtureSetUp() { datumConverterFactory = new AggregateDatumConverterFactory( PrimitiveDatumConverterFactory.Instance, TimeSpanDatumConverterFactory.Instance, DateTimeDatumConverterFactory.Instance ); expressionConverterFactory = new RethinkDb.Expressions.DefaultExpressionConverterFactory(); queryConverter = new QueryConverter(datumConverterFactory, expressionConverterFactory); }
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 Term GenerateTerm(IDatumConverterFactory datumConverterFactory) { var dbTerm = new Term() { type = Term.TermType.DB_DROP, }; dbTerm.args.Add( new Term() { type = Term.TermType.DATUM, datum = new Datum() { type = Datum.DatumType.R_STR, r_str = db, } } ); return dbTerm; }
public Term GenerateTerm(IDatumConverterFactory datumConverterFactory) { var tableTerm = new Term() { type = Term.TermType.TABLE_DROP, }; tableTerm.args.Add(dbTerm.GenerateTerm(datumConverterFactory)); tableTerm.args.Add( new Term() { type = Term.TermType.DATUM, datum = new Datum() { type = Datum.DatumType.R_STR, r_str = table, } } ); return tableTerm; }
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 void TestFixtureSetUp() { var stringDatum = new Datum() { type = Datum.DatumType.R_STR, r_str = "Jackpot!", }; var stringDatumConverter = Substitute.For<IDatumConverter<string>>(); stringDatumConverter .ConvertObject("Jackpot!") .Returns(stringDatum); stringDatumConverter .ConvertDatum(Arg.Is<Datum>(d => d.type == stringDatum.type && d.r_str == stringDatum.r_str)) .Returns("Jackpot!"); ((IDatumConverter)stringDatumConverter) .ConvertObject("Jackpot!") .Returns(stringDatum); ((IDatumConverter)stringDatumConverter) .ConvertDatum(Arg.Is<Datum>(d => d.type == stringDatum.type && d.r_str == stringDatum.r_str)) .Returns("Jackpot!"); rootDatumConverterFactory = Substitute.For<IDatumConverterFactory>(); IDatumConverter<string> _dcs; rootDatumConverterFactory .TryGet<string>(rootDatumConverterFactory, out _dcs) .Returns(args => { Console.WriteLine("TryGet<string>"); args[1] = stringDatumConverter; return true; }); IDatumConverter _dc; rootDatumConverterFactory .TryGet(typeof(String), rootDatumConverterFactory, out _dc) .Returns(args => { args[2] = stringDatumConverter; return true; }); }
private bool ServerSideMemberAccess(IDatumConverterFactory datumConverterFactory, MemberExpression memberExpression, out Term term) { term = null; if (memberExpression.Expression == null) // static member access; can't do that server-side, wouldn't want to either. return false; if (memberExpression.Expression.NodeType == ExpressionType.Constant) // Accessing a constant; client-side conversion will be more efficient since we won't be round-tripping the object return false; IDatumConverter datumConverter; if (!datumConverterFactory.TryGet(memberExpression.Expression.Type, out datumConverter)) // No datum converter for this type. return false; var fieldConverter = datumConverter as IObjectDatumConverter; if (fieldConverter == null) // doesn't implement IObjectDatumConverter, so we don't know how to map the MemberInfo to the field name return false; var datumFieldName = fieldConverter.GetDatumFieldName(memberExpression.Member); if (string.IsNullOrEmpty(datumFieldName)) { // At this point we're not returning false because we're expecting this should work; throwing an error instead. // We're expecting this to work, but, returning false will give us a chance to try client-side evaluation instead and // maintain compatibility with the pre-PR #209 behaviour. (issue #220). return false; } var getAttrTerm = new Term() { type = Term.TermType.GET_FIELD }; getAttrTerm.args.Add(RecursiveMap(memberExpression.Expression)); getAttrTerm.args.Add(new Term() { type = Term.TermType.DATUM, datum = new Datum() { type = Datum.DatumType.R_STR, r_str = datumFieldName } }); term = getAttrTerm; return true; }
protected Term SimpleMap(IDatumConverterFactory datumConverterFactory, Expression expr) { switch (expr.NodeType) { case ExpressionType.Constant: { var constantExpression = (ConstantExpression)expr; var datumConverter = datumConverterFactory.Get(constantExpression.Type); var datum = datumConverter.ConvertObject(constantExpression.Value); return new Term() { type = Term.TermType.DATUM, datum = datum }; } case ExpressionType.Add: case ExpressionType.Modulo: case ExpressionType.Divide: case ExpressionType.Multiply: case ExpressionType.Subtract: case ExpressionType.Equal: case ExpressionType.LessThan: case ExpressionType.LessThanOrEqual: case ExpressionType.GreaterThan: case ExpressionType.GreaterThanOrEqual: case ExpressionType.AndAlso: case ExpressionType.OrElse: case ExpressionType.NotEqual: case ExpressionType.ArrayIndex: return ConvertBinaryExpressionToTerm((BinaryExpression)expr, datumConverterFactory); case ExpressionType.Not: case ExpressionType.ArrayLength: return ConvertUnaryExpressionToTerm((UnaryExpression)expr, datumConverterFactory); case ExpressionType.New: { var newExpression = (NewExpression)expr; if (AnonymousTypeDatumConverterFactory.Instance.IsTypeSupported(newExpression.Type)) { var retval = new Term() { type = Term.TermType.MAKE_OBJ, }; foreach (var property in newExpression.Type.GetProperties().Select((p, i) => new { Property = p, Index = i })) { var key = property.Property.Name; var value = RecursiveMap(newExpression.Arguments[property.Index]); retval.optargs.Add(new Term.AssocPair() { key = key, val = value }); } return retval; } DefaultExpressionConverterFactory.ExpressionMappingDelegate<NewExpression> newExpressionMapping; if (expressionConverterFactory.TryGetNewExpressionMapping(newExpression.Constructor, out newExpressionMapping)) return newExpressionMapping(newExpression, RecursiveMap, datumConverterFactory, expressionConverterFactory); return AttemptClientSideConversion(datumConverterFactory, expr); } case ExpressionType.NewArrayInit: var arrayExpression = (NewArrayExpression)expr; var array = new Term {type = Term.TermType.MAKE_ARRAY}; foreach (var expression in arrayExpression.Expressions) { array.args.Add(RecursiveMap(expression)); } return array; case ExpressionType.Call: { var callExpression = (MethodCallExpression)expr; var method = callExpression.Method; DefaultExpressionConverterFactory.ExpressionMappingDelegate<MethodCallExpression> methodCallMapping; if (expressionConverterFactory.TryGetMethodCallMapping(method, out methodCallMapping)) return methodCallMapping(callExpression, RecursiveMap, datumConverterFactory, expressionConverterFactory); else return AttemptClientSideConversion(datumConverterFactory, expr); } case ExpressionType.MemberAccess: { var memberExpression = (MemberExpression)expr; var member = memberExpression.Member; DefaultExpressionConverterFactory.ExpressionMappingDelegate<MemberExpression> memberAccessMapping; if (expressionConverterFactory.TryGetMemberAccessMapping(member, out memberAccessMapping)) return memberAccessMapping(memberExpression, RecursiveMap, datumConverterFactory, expressionConverterFactory); Term serverSideTerm; if (ServerSideMemberAccess(datumConverterFactory, memberExpression, out serverSideTerm)) return serverSideTerm; return AttemptClientSideConversion(datumConverterFactory, expr); } case ExpressionType.Conditional: { var conditionalExpression = (ConditionalExpression)expr; return new Term() { type = Term.TermType.BRANCH, args = { RecursiveMap(conditionalExpression.Test), RecursiveMap(conditionalExpression.IfTrue), RecursiveMap(conditionalExpression.IfFalse) } }; } case ExpressionType.Convert: { // The use-case for this right now is automatic boxing that occurs when setting a Dictionary<string,object>'s value // to a primitive. In that particular case, we don't actually need to generate any ReQL for the conversion, so we're // just ignoring the Convert and mapping the expression inside. Might need other behavior here in the future... return RecursiveMap(((UnaryExpression)expr).Operand); } case ExpressionType.MemberInit: { var memberInit = (MemberInitExpression)expr; var memberType = memberInit.Type; IDatumConverter datumConverter; if (!datumConverterFactory.TryGet(memberType, out datumConverter)) return AttemptClientSideConversion(datumConverterFactory, expr); var fieldConverter = datumConverter as IObjectDatumConverter; if (fieldConverter == null) return AttemptClientSideConversion(datumConverterFactory, expr); var makeObjTerm = new Term() { type = Term.TermType.MAKE_OBJ, }; foreach (var binding in memberInit.Bindings) { switch (binding.BindingType) { case MemberBindingType.Assignment: { var memberAssignment = (MemberAssignment)binding; var pair = new Term.AssocPair(); pair.key = fieldConverter.GetDatumFieldName(memberAssignment.Member); pair.val = RecursiveMap(memberAssignment.Expression); if (pair.key == null) throw new NotSupportedException("Cannot map member assignments into ReQL without implementing IObjectDatumConverter"); makeObjTerm.optargs.Add(pair); break; } case MemberBindingType.ListBinding: case MemberBindingType.MemberBinding: throw new NotSupportedException("Binding type not currently supported"); } } return makeObjTerm; } default: { return AttemptClientSideConversion(datumConverterFactory, expr); } } }
protected Term SimpleMap(IDatumConverterFactory datumConverterFactory, Expression expr) { switch (expr.NodeType) { case ExpressionType.Constant: { var constantExpression = (ConstantExpression)expr; var datumConverter = datumConverterFactory.Get(constantExpression.Type); var datum = datumConverter.ConvertObject(constantExpression.Value); return new Term() { type = Term.TermType.DATUM, datum = datum }; } case ExpressionType.Add: case ExpressionType.Modulo: case ExpressionType.Divide: case ExpressionType.Multiply: case ExpressionType.Subtract: case ExpressionType.Equal: case ExpressionType.LessThan: case ExpressionType.LessThanOrEqual: case ExpressionType.GreaterThan: case ExpressionType.GreaterThanOrEqual: case ExpressionType.AndAlso: case ExpressionType.OrElse: case ExpressionType.NotEqual: case ExpressionType.ArrayIndex: return ConvertBinaryExpressionToTerm((BinaryExpression)expr, datumConverterFactory); case ExpressionType.Not: case ExpressionType.ArrayLength: return ConvertUnaryExpressionToTerm((UnaryExpression)expr, datumConverterFactory); case ExpressionType.New: { var newExpression = (NewExpression)expr; if (AnonymousTypeDatumConverterFactory.Instance.IsTypeSupported(newExpression.Type)) { var retval = new Term() { type = Term.TermType.MAKE_OBJ, }; foreach (var property in newExpression.Type.GetProperties().Select((p, i) => new { Property = p, Index = i })) { var key = property.Property.Name; var value = RecursiveMap(newExpression.Arguments[property.Index]); retval.optargs.Add(new Term.AssocPair() { key = key, val = value }); } return retval; } DefaultExpressionConverterFactory.ExpressionMappingDelegate<NewExpression> newExpressionMapping; if (expressionConverterFactory.TryGetNewExpressionMapping(newExpression.Constructor, out newExpressionMapping)) return newExpressionMapping(newExpression, RecursiveMap, datumConverterFactory, expressionConverterFactory); return AttemptClientSideConversion(datumConverterFactory, expr); } case ExpressionType.Call: { var callExpression = (MethodCallExpression)expr; var method = callExpression.Method; DefaultExpressionConverterFactory.ExpressionMappingDelegate<MethodCallExpression> methodCallMapping; if (expressionConverterFactory.TryGetMethodCallMapping(method, out methodCallMapping)) return methodCallMapping(callExpression, RecursiveMap, datumConverterFactory, expressionConverterFactory); else return AttemptClientSideConversion(datumConverterFactory, expr); } case ExpressionType.MemberAccess: { var memberExpression = (MemberExpression)expr; var member = memberExpression.Member; DefaultExpressionConverterFactory.ExpressionMappingDelegate<MemberExpression> memberAccessMapping; if (expressionConverterFactory.TryGetMemberAccessMapping(member, out memberAccessMapping)) return memberAccessMapping(memberExpression, RecursiveMap, datumConverterFactory, expressionConverterFactory); Term serverSideTerm; if (ServerSideMemberAccess(datumConverterFactory, memberExpression, out serverSideTerm)) return serverSideTerm; return AttemptClientSideConversion(datumConverterFactory, expr); } case ExpressionType.Conditional: { var conditionalExpression = (ConditionalExpression)expr; return new Term() { type = Term.TermType.BRANCH, args = { RecursiveMap(conditionalExpression.Test), RecursiveMap(conditionalExpression.IfTrue), RecursiveMap(conditionalExpression.IfFalse) } }; } case ExpressionType.Convert: { // The use-case for this right now is automatic boxing that occurs when setting a Dictionary<string,object>'s value // to a primitive. In that particular case, we don't actually need to generate any ReQL for the conversion, so we're // just ignoring the Convert and mapping the expression inside. Might need other behavior here in the future... return RecursiveMap(((UnaryExpression)expr).Operand); } default: { return AttemptClientSideConversion(datumConverterFactory, expr); } } }
private bool ServerSideMemberAccess(IDatumConverterFactory datumConverterFactory, MemberExpression memberExpression, out Term term) { term = null; if (memberExpression.Expression == null) // static member access; can't do that server-side, wouldn't want to either. return false; if (memberExpression.Expression.NodeType == ExpressionType.Constant) // Accessing a constant; client-side conversion will be more efficient since we won't be round-tripping the object return false; IDatumConverter datumConverter; if (!datumConverterFactory.TryGet(memberExpression.Expression.Type, out datumConverter)) // No datum converter for this type. return false; var fieldConverter = datumConverter as IObjectDatumConverter; if (fieldConverter == null) // doesn't implement IObjectDatumConverter, so we don't know how to map the MemberInfo to the field name return false; var datumFieldName = fieldConverter.GetDatumFieldName(memberExpression.Member); if (string.IsNullOrEmpty(datumFieldName)) // At this point we're not returning false because we're expecting this should work; throwing an error instead. throw new NotSupportedException(String.Format("Member {0} on type {1} could not be mapped to a datum field", memberExpression.Member.Name, memberExpression.Type)); var getAttrTerm = new Term() { type = Term.TermType.GET_FIELD }; getAttrTerm.args.Add(RecursiveMap(memberExpression.Expression)); getAttrTerm.args.Add(new Term() { type = Term.TermType.DATUM, datum = new Datum() { type = Datum.DatumType.R_STR, r_str = datumFieldName } }); term = getAttrTerm; return true; }
private Term ConvertUnaryExpressionToTerm(UnaryExpression expr, IDatumConverterFactory datumConverterFactory) { DefaultExpressionConverterFactory.ExpressionMappingDelegate<UnaryExpression> unaryExpressionMapping; Term.TermType defaultTermType; if (expressionConverterFactory.TryGetUnaryExpressionMapping(expr.Operand.Type, expr.NodeType, out unaryExpressionMapping)) { return unaryExpressionMapping(expr, RecursiveMap, datumConverterFactory, expressionConverterFactory); } else if (DefaultTermTypes.TryGetValue(expr.NodeType, out defaultTermType)) { var term = new Term() { type = defaultTermType }; term.args.Add(RecursiveMap(expr.Operand)); return term; } else return AttemptClientSideConversion(datumConverterFactory, expr); }
private Term AttemptClientSideConversion(IDatumConverterFactory datumConverterFactory, Expression expr) { try { var converter = datumConverterFactory.Get(expr.Type); var clientSideFunc = Expression.Lambda(expr).Compile(); return new Term() { type = Term.TermType.DATUM, datum = converter.ConvertObject(clientSideFunc.DynamicInvoke()) }; } catch (InvalidOperationException ex) { throw new InvalidOperationException( String.Format( "Failed to perform client-side evaluation of expression tree node '{0}'; this is caused by refering to a server-side variable in an expression tree that isn't convertible to ReQL logic", expr), ex); } }
public void TestFixtureSetUp() { datumConverterFactory = Substitute.For<IDatumConverterFactory>(); var intDatumConverter = Substitute.For<IDatumConverter>(); intDatumConverter.ConvertDatum(Arg.Any<Datum>()).Returns(args => (int)((Datum)args[0]).r_num); intDatumConverter.ConvertObject(Arg.Any<object>()).Returns(args => new Datum() { type = Datum.DatumType.R_NUM, r_num = (int)args [0] }); IDatumConverter value; datumConverterFactory .TryGet(typeof(int), datumConverterFactory, out value) .Returns(args => { args[2] = intDatumConverter; return true; }); datumConverterFactory.GetBestNativeTypeForDatum(Arg.Any<Datum>()).Returns(typeof(int)); }
public Term GenerateTerm(IDatumConverterFactory datumConverterFactory) { var tableTerm = new Term() { type = Term.TermType.TABLE_CREATE, }; tableTerm.args.Add(dbTerm.GenerateTerm(datumConverterFactory)); tableTerm.args.Add( new Term() { type = Term.TermType.DATUM, datum = new Datum() { type = Datum.DatumType.R_STR, r_str = table, } } ); if (datacenter != null) { tableTerm.optargs.Add(new Term.AssocPair() { key = "datacenter", val = new Term() { type = Term.TermType.DATUM, datum = new Datum() { type = Datum.DatumType.R_STR, r_str = datacenter, } } }); } if (primaryKey != null) { tableTerm.optargs.Add(new Term.AssocPair() { key = "primary_key", val = new Term() { type = Term.TermType.DATUM, datum = new Datum() { type = Datum.DatumType.R_STR, r_str = primaryKey, } } }); } if (cacheSize.HasValue) { tableTerm.optargs.Add(new Term.AssocPair() { key = "cache_size", val = new Term() { type = Term.TermType.DATUM, datum = new Datum() { type = Datum.DatumType.R_NUM, r_num = cacheSize.Value, } } }); } return tableTerm; }
protected Term SimpleMap(IDatumConverterFactory datumConverterFactory, Expression expr) { switch (expr.NodeType) { case ExpressionType.Constant: { var constantExpression = (ConstantExpression)expr; var datumConverter = datumConverterFactory.Get(constantExpression.Type); var datum = datumConverter.ConvertObject(constantExpression.Value); return new Term() { type = Term.TermType.DATUM, datum = datum }; } case ExpressionType.Add: case ExpressionType.Modulo: case ExpressionType.Divide: case ExpressionType.Multiply: case ExpressionType.Subtract: case ExpressionType.Equal: case ExpressionType.LessThan: case ExpressionType.LessThanOrEqual: case ExpressionType.GreaterThan: case ExpressionType.GreaterThanOrEqual: case ExpressionType.AndAlso: case ExpressionType.OrElse: case ExpressionType.NotEqual: case ExpressionType.ArrayIndex: return ConvertBinaryExpressionToTerm((BinaryExpression)expr, datumConverterFactory); case ExpressionType.Not: case ExpressionType.ArrayLength: return ConvertUnaryExpressionToTerm((UnaryExpression)expr, datumConverterFactory); case ExpressionType.New: { var newExpression = (NewExpression)expr; if (AnonymousTypeDatumConverterFactory.Instance.IsTypeSupported(newExpression.Type)) { var retval = new Term() { type = Term.TermType.MAKE_OBJ, }; foreach (var property in newExpression.Type.GetProperties().Select((p, i) => new { Property = p, Index = i })) { var key = property.Property.Name; var value = RecursiveMap(newExpression.Arguments[property.Index]); retval.optargs.Add(new Term.AssocPair() { key = key, val = value }); } return retval; } DefaultExpressionConverterFactory.ExpressionMappingDelegate<NewExpression> newExpressionMapping; if (expressionConverterFactory.TryGetNewExpressionMapping(newExpression.Constructor, out newExpressionMapping)) return newExpressionMapping(newExpression, RecursiveMap, datumConverterFactory, expressionConverterFactory); return AttemptClientSideConversion(datumConverterFactory, expr); } case ExpressionType.Call: { var callExpression = (MethodCallExpression)expr; var method = callExpression.Method; DefaultExpressionConverterFactory.ExpressionMappingDelegate<MethodCallExpression> methodCallMapping; if (expressionConverterFactory.TryGetMethodCallMapping(method, out methodCallMapping)) return methodCallMapping(callExpression, RecursiveMap, datumConverterFactory, expressionConverterFactory); else return AttemptClientSideConversion(datumConverterFactory, expr); } case ExpressionType.MemberAccess: { var memberExpression = (MemberExpression)expr; var member = memberExpression.Member; DefaultExpressionConverterFactory.ExpressionMappingDelegate<MemberExpression> memberAccessMapping; if (expressionConverterFactory.TryGetMemberAccessMapping(member, out memberAccessMapping)) return memberAccessMapping(memberExpression, RecursiveMap, datumConverterFactory, expressionConverterFactory); else return AttemptClientSideConversion(datumConverterFactory, expr); } case ExpressionType.Conditional: { var conditionalExpression = (ConditionalExpression)expr; return new Term() { type = Term.TermType.BRANCH, args = { RecursiveMap(conditionalExpression.Test), RecursiveMap(conditionalExpression.IfTrue), RecursiveMap(conditionalExpression.IfFalse) } }; } default: { return AttemptClientSideConversion(datumConverterFactory, expr); } } }