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));
            }
Exemple #3
0
 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);
        }
Exemple #5
0
        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;
                    });
        }
Exemple #7
0
        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;
        }
Exemple #11
0
        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);
        }
Exemple #12
0
        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);
        }
Exemple #14
0
        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);
        }
Exemple #15
0
        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)
            });
        }
Exemple #16
0
        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);
            });
        }
Exemple #17
0
        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);
            }
        }
Exemple #18
0
        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);
            });
        }
Exemple #19
0
        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));
        }
Exemple #20
0
        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);
        }
Exemple #22
0
 public static IDatumConverter Get(this IDatumConverterFactory datumConverterFactory, Type datumType)
 {
     if (datumConverterFactory == null)
     {
         throw new ArgumentNullException("datumConverterFactory");
     }
     return(datumConverterFactory.Get(datumType, datumConverterFactory));
 }
Exemple #23
0
 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));
 }
Exemple #28
0
 public static IDatumConverter <T> Get <T>(this IDatumConverterFactory datumConverterFactory)
 {
     if (datumConverterFactory == null)
     {
         throw new ArgumentNullException("datumConverterFactory");
     }
     return(datumConverterFactory.Get <T>(datumConverterFactory));
 }
Exemple #29
0
        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);
 }
Exemple #31
0
        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);
        }
Exemple #34
0
 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!",
         }
     };
 }
Exemple #37
0
 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;
 }
Exemple #38
0
 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);
                }
            }
        }