/// <summary>
        /// Resolves types for the specified expression.
        /// </summary>
        /// <param name="expression">The expression to resolve types for.</param>
        /// <returns>Expression with resolved types.</returns>
        public QueryExpression Visit(QueryConstantExpression expression)
        {
            if (expression.ExpressionType.IsUnresolved)
            {
                var value = expression.ScalarValue.Value;
                ExceptionUtilities.Assert(value != null, "Constant expression with unresolved type cannot have null value.");
                var queryType = this.GetQueryScalarTypeFromObjectValue(value);
                return(CommonQueryBuilder.Constant(queryType.CreateValue(value)));
            }

            return(expression);
        }
Esempio n. 2
0
        /// <summary>
        /// Evaluates the specified expression.
        /// </summary>
        /// <param name="expression">The expression to evaluate.</param>
        /// <returns>Value of the expression.</returns>
        public virtual QueryValue Visit(QueryCustomFunctionCallExpression expression)
        {
            QueryValue result;

            var argumentValues = this.EvaluateArguments(expression.Arguments);

            var customEvaluator = expression.Function.Annotations.OfType <FunctionEvaluatorAnnotation>().Select(a => a.FunctionEvaluator).SingleOrDefault();

            if (customEvaluator != null)
            {
                result = customEvaluator(expression.ExpressionType, argumentValues);
            }
            else if (expression.FunctionBody != null)
            {
                QueryExpression functionBody = expression.FunctionBody;

                // replace parameter refs with arguments
                if (expression.Function.Parameters.Any())
                {
                    // Consider query:
                    //      "select value DefaultNamespace.GetCustomer(c.CustomerId) from [DefaultContainer].[Customer] as c" where GetCustomer is a function.
                    //    After we replace parameter references in the function's body with "c.CustomerId" expression evaluation
                    //    of the body expression fails becuase variable "c" is not in the scope for the function's body.
                    //    Note also that function body itself can have a variable reference with the same name "c".
                    // So the right thing is to evaluate each argument and then replace parameter references with constant expressions.
                    // However QueryConstantExpression currently only supports QueryScalarType/QueryScalarValue.
                    // So for now we only evaluating scalar arguments.
                    // TODO: add supoort for non-scalar constants and change the following code to evaluate each argument
                    //      NOTE: we have similar limitation in LinqToEntitiesEvaluator
                    List <QueryExpression> evaluatedArguments = new List <QueryExpression>();
                    foreach (var argument in expression.Arguments)
                    {
                        QueryScalarType scalarArgumentType = argument.ExpressionType as QueryScalarType;
                        if (scalarArgumentType != null)
                        {
                            QueryScalarValue scalarValue = (QueryScalarValue)this.Evaluate(argument);
                            var constant = CommonQueryBuilder.Constant(scalarValue);
                            evaluatedArguments.Add(constant);
                        }
                        else
                        {
                            evaluatedArguments.Add(argument);
                        }
                    }

                    var visitor = this.CreateFunctionParameterReferenceReplacingVisitor(expression.Function, evaluatedArguments);
                    functionBody = visitor.ReplaceExpression(expression.FunctionBody);
                }

                result = this.Evaluate(functionBody);
            }
            else
            {
                result = expression.ExpressionType.EvaluationStrategy.EvaluateFunction(
                    expression.ExpressionType,
                    expression.Function,
                    argumentValues);
            }

            return(result);
        }