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;
        }
 private void AssertAddFunctionWithConversion(Term expr, double value, double conversion)
 {
     var funcTerm = 
         new Term() {
             type = Term.TermType.FUNC,
             args = {
                 new Term() {
                     type = Term.TermType.MAKE_ARRAY,
                     args = {
                         new Term() {
                             type = Term.TermType.DATUM,
                             datum = new Datum() {
                                 type = Datum.DatumType.R_NUM,
                                 r_num = 2,
                             }
                         }
                     }
                 },
                 new Term() {
                     type = Term.TermType.ADD,
                     args = {
                         new Term() {
                             type = Term.TermType.VAR,
                             args = {
                                 new Term() {
                                     type = Term.TermType.DATUM,
                                     datum = new Datum() {
                                         type = Datum.DatumType.R_NUM,
                                         r_num = 2,
                                     }
                                 }
                             }
                         },
                         new Term() {
                             type = Term.TermType.MUL,
                             args = {
                                 new Term() {
                                     type = Term.TermType.DATUM,
                                     datum = new Datum() {
                                         type = Datum.DatumType.R_NUM,
                                         r_num = value,
                                     }
                                 },
                                 new Term() {
                                     type = Term.TermType.DATUM,
                                     datum = new Datum() {
                                         type = Datum.DatumType.R_NUM,
                                         r_num = conversion,
                                     }
                                 },
                             }
                         }
                     }
                 },
             }
         };
     expr.ShouldBeEquivalentTo(funcTerm);
 }
 private void AssertAddFunction(Term expr, TimeSpan ts)
 {
     var funcTerm = 
         new Term() {
             type = Term.TermType.FUNC,
             args = {
                 new Term() {
                     type = Term.TermType.MAKE_ARRAY,
                     args = {
                         new Term() {
                             type = Term.TermType.DATUM,
                             datum = new Datum() {
                                 type = Datum.DatumType.R_NUM,
                                 r_num = 2,
                             }
                         }
                     }
                 },
                 new Term() {
                     type = Term.TermType.ADD,
                     args = {
                         new Term() {
                             type = Term.TermType.VAR,
                             args = {
                                 new Term() {
                                     type = Term.TermType.DATUM,
                                     datum = new Datum() {
                                         type = Datum.DatumType.R_NUM,
                                         r_num = 2,
                                     }
                                 }
                             }
                         },
                         new Term() {
                             type = Term.TermType.DATUM,
                             datum = new Datum() {
                                 type = Datum.DatumType.R_NUM,
                                 r_num = ts.TotalSeconds,
                             }
                         },
                     }
                 },
             }
         };
     expr.ShouldBeEquivalentTo(funcTerm);
 }
Example #4
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;
 }
Example #5
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;
        }
 private static Term Count(Term term)
 {
     return new Term() { type = Term.TermType.COUNT, args = { term } };
 }
Example #8
0
        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 void AssertDateTimeAccessor(Term expr, Term.TermType termType)
 {
     expr.ShouldBeEquivalentTo(
         new Term() {
             type = Term.TermType.FUNC,
             args = {
                 new Term() {
                     type = Term.TermType.MAKE_ARRAY,
                     args = {
                         new Term() {
                             type = Term.TermType.DATUM,
                             datum = new Datum() {
                                 type = Datum.DatumType.R_NUM,
                                 r_num = 2,
                             }
                         }
                     }
                 },
                 new Term() {
                     type = termType,
                     args = {
                         new Term() {
                             type = Term.TermType.VAR,
                             args = {
                                 new Term() {
                                     type = Term.TermType.DATUM,
                                     datum = new Datum() {
                                         type = Datum.DatumType.R_NUM,
                                         r_num = 2,
                                     }
                                 }
                             }
                         }
                     }
                 }
             }
         }
     );
 }
 private static Term TimeSpanToPlusMinus(Term offset)
 {
     return new Term()
     {
         type = Term.TermType.BRANCH,
         args = {
             Binary(offset, Term.TermType.LT, 0),
             String("-"),
             String("+")
         }
     };
 }
 private static Term TimeSpanToOffsetHouts(Term offset)
 {
     // (offset - (offset % 3600)) / 3600
     var hours = Binary(
         Binary(offset, Term.TermType.SUB, Binary(offset, Term.TermType.MOD, 3600)),
         Term.TermType.DIV,
         3600);
     // then ensure hours is positive; TimeSpanToPlusMinus takes care of the minus sign if needed
     // to make the padding simpler here
     hours = Branch(
         Binary(hours, Term.TermType.LT, 0),
         Binary(hours, Term.TermType.MUL, -1),
         hours);
     return
         Branch(
             Binary(hours, Term.TermType.LT, 10),
             Add(String("0"), CoerceTo(hours, "string")),
             CoerceTo(hours, "string")
         );
 }
 private static Term MinutesToSeconds(Term term)
 {
     return Binary(term, Term.TermType.MUL, 60);
 }
 private static void WriteDatum(JsonWriter writer, Spec.Datum datum)
 {
     switch (datum.type)
     {
         case Spec.Datum.DatumType.R_BOOL:
             writer.WriteBoolean(datum.r_bool);
             break;
         case Spec.Datum.DatumType.R_JSON:
             throw new NotSupportedException();
         case Spec.Datum.DatumType.R_NULL:
             writer.WriteNull();
             break;
         case Spec.Datum.DatumType.R_NUM:
             writer.WriteNumber(datum.r_num);
             break;
         case Spec.Datum.DatumType.R_STR:
             writer.WriteString(datum.r_str);
             break;
         case Spec.Datum.DatumType.R_ARRAY:
             {
                 var newterm = new Term() { type = Term.TermType.MAKE_ARRAY };
                 newterm.args.AddRange(datum.r_array.Select(ap => new Term()
                 {
                     type = Term.TermType.DATUM,
                     datum = ap,
                 }));
                 WriteTerm(writer, newterm);
             }
             break;
         case Spec.Datum.DatumType.R_OBJECT:
             {
                 var newterm = new Term() { type = Term.TermType.MAKE_OBJ };
                 newterm.optargs.AddRange(datum.r_object.Select(ap => new Term.AssocPair()
                 {
                     key = ap.key,
                     val = new Term()
                     {
                         type = Term.TermType.DATUM,
                         datum = ap.val
                     }
                 }));
                 WriteTerm(writer, newterm);
             }
             break;
     }
 }
Example #14
0
        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);
                }
            }
        }
Example #15
0
        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;
        }
 private static Term HoursToSeconds(Term term)
 {
     // seconds per hour
     return Binary(term, Term.TermType.MUL, 3600);
 }
 private static Term MillisecondsToSeconds(Term term)
 {
     return Binary(term, Term.TermType.DIV, 1000);
 }
 public static Term TimeSpanToOffset(Term offset)
 {
     // offset will be a number of seconds on the server-side since that's how we've mapped
     // TimeSpans to ReQL.  This is basically:  str(floor(offset / 60)) + ":" + (offset % 60),
     // but, ReQL doesn't support floor, and requires the timezone to be in the exact format
     // [+-][0-9]{2}:[0-9]{2}.
     return Add(
         TimeSpanToPlusMinus(offset),
         TimeSpanToOffsetHouts(offset),
         String(":"),
         TimeSpanToOffsetMinutes(offset)
     );
 }
 private static Term TicksToSeconds(Term term)
 {
     return Binary(term, Term.TermType.DIV, TimeSpan.TicksPerSecond);
 }
 private static Term Binary(Term leftTerm, Term.TermType type, Term rightTerm)
 {
     return new Term()
     {
         type = type,
         args = {
             leftTerm,
             rightTerm
         }
     };
 }
 private static Term TimeSpanToOffsetMinutes(Term offset)
 {
     // minutes is now the total number of minutes, any second precision has been removed
     var minutes = Binary(
         Binary(offset, Term.TermType.SUB, Binary(offset, Term.TermType.MOD, 60)),
         Term.TermType.DIV,
         60);
     // then take out the hours accounted for in TimeSpanToOffsetHours
     minutes = Binary(minutes, Term.TermType.MOD, 60);
     // then ensure minutes is positive; ReSQL -30 % 60 -> -30
     minutes = Branch(
         Binary(minutes, Term.TermType.LT, 0),
         Binary(minutes, Term.TermType.MUL, -1),
         minutes);
     return
         Branch(
             Binary(minutes, Term.TermType.LE, 10),
             Add(String("0"), CoerceTo(minutes, "string")), // leading zero
             CoerceTo(minutes, "string")
         );
 }
 private static Term Binary(Term leftTerm, Term.TermType type, double rightTerm)
 {
     return Binary(leftTerm, type, new Term()
     {
         type = Term.TermType.DATUM,
         datum = new Datum() {
             type = Datum.DatumType.R_NUM,
             r_num = rightTerm
         }
     });
 }
Example #23
0
        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;
        }
 private static Term Branch(Term test, Term ifTrue, Term ifFalse)
 {
     return new Term()
     {
         type = Term.TermType.BRANCH,
         args = {
             test,
             ifTrue,
             ifFalse
         }
     };
 }
        public void DateTimeYearMonthDayConstructor()
        {
            var expr = ExpressionUtils.CreateFunctionTerm<int, DateTime>(queryConverter, (i) => new DateTime(i, i, i));
            var variableRefenceTerm = new Term() {
                type = Term.TermType.VAR,
                args = {
                    new Term() {
                        type = Term.TermType.DATUM,
                        datum = new Datum() {
                            type = Datum.DatumType.R_NUM,
                            r_num = 2,
                        }
                    }
                }
            };

            expr.ShouldBeEquivalentTo(
                new Term()
                {
                    type = Term.TermType.FUNC,
                    args = {
                        new Term() {
                            type = Term.TermType.MAKE_ARRAY,
                            args = {
                                new Term() {
                                    type = Term.TermType.DATUM,
                                    datum = new Datum() {
                                        type = Datum.DatumType.R_NUM,
                                        r_num = 2,
                                    }
                                }
                            }
                        },
                        new Term() {
                            type = Term.TermType.TIME,
                            args = {
                                variableRefenceTerm,
                                variableRefenceTerm,
                                variableRefenceTerm,
                                new Term() {
                                    type = Term.TermType.DATUM,
                                    datum = new Datum() {
                                        type = Datum.DatumType.R_STR,
                                        r_str = "Z",
                                    }
                                }
                            }
                        }
                    }
                }
            );
        }
 private static Term CoerceTo(Term term, string type)
 {
     return new Term()
     {
         type = Term.TermType.COERCE_TO,
         args = {
             term,
             String(type)
         }
     };
 }
Example #27
0
        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 static Term DaysToSeconds(Term term)
 {
     // seconds per day... doesn't account for days with leap seconds, but, close enough
     return Binary(term, Term.TermType.MUL, 86400);
 }
Example #29
0
        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);
                }
            }
        }
Example #30
0
        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);
                }
            }
        }