public IJoinInfo VisitUnresolvedCollectionJoinInfo(UnresolvedCollectionJoinInfo joinInfo)
        {
            ArgumentUtility.CheckNotNull("joinInfo", joinInfo);

            var resolvedExpression = _stage.ResolveCollectionSourceExpression(joinInfo.SourceExpression, _context);

            while (resolvedExpression is UnaryExpression)
            {
                resolvedExpression = _stage.ResolveCollectionSourceExpression(((UnaryExpression)resolvedExpression).Operand, _context);
            }

            var resolvedExpressionAsEntity = resolvedExpression as SqlEntityExpression;

            if (resolvedExpressionAsEntity != null)
            {
                var unresolvedJoinInfo = new UnresolvedJoinInfo(resolvedExpressionAsEntity, joinInfo.MemberInfo, JoinCardinality.Many);
                return(unresolvedJoinInfo.Accept(this));
            }

            var message = string.Format(
                "Only entities can be used as the collection source in from expressions, '{0}' cannot. Member: '{1}'",
                FormattingExpressionTreeVisitor.Format(resolvedExpression),
                joinInfo.MemberInfo);

            throw new NotSupportedException(message);
        }
Esempio n. 2
0
        private SqlCommandData GenerateSqlCommand(QueryModel queryModel)
        {
            ISqlPreparationContext    preparationContext       = new SqlPreparationContext(new SqlStatementBuilder());
            IMappingResolutionContext mappingResolutionContext = new MappingResolutionContext();

            var generator         = new UniqueIdentifierGenerator();
            var preparationStage  = new DefaultSqlPreparationStage(_methodCallTransformerProvider, _resultOperatorHandlerRegistry, generator);
            var preparedStatement = preparationStage.PrepareSqlStatement(queryModel, preparationContext);

            var resolutionStage   = new DefaultMappingResolutionStage(_mappingResolver, generator);
            var resolvedStatement = resolutionStage.ResolveSqlStatement(preparedStatement, mappingResolutionContext);

            var builder         = new SqlCommandBuilder();
            var generationStage = new DefaultSqlGenerationStage();

            generationStage.GenerateTextForOuterSqlStatement(builder, resolvedStatement);

            var command = builder.GetCommand();

            if (_showQuery)
            {
                Console.WriteLine(command.CommandText);
                Console.WriteLine(string.Join(", ", command.Parameters.Select(p => p.Name + "=" + p.Value)));
                Console.WriteLine(FormattingExpressionTreeVisitor.Format(command.GetInMemoryProjection <object>()));
            }
            return(command);
        }
Esempio n. 3
0
        protected override Expression VisitNewExpression(NewExpression expression)
        {
            ArgumentUtility.CheckNotNull("expression", expression);

            if (_currentContext == SqlExpressionContext.SingleValueRequired)
            {
                string message = string.Format(
                    "Cannot use a complex expression ('{0}') in a place where SQL requires a single value.",
                    FormattingExpressionTreeVisitor.Format(expression));
                throw new NotSupportedException(message);
            }

            var newArguments = expression.Arguments.Select(ApplyValueContext).ToArray();

            if (!newArguments.SequenceEqual(expression.Arguments))
            {
                // ReSharper disable ConditionIsAlwaysTrueOrFalse
                if (expression.Members != null && expression.Members.Count > 0)
                {
                    return(Expression.New(expression.Constructor, newArguments, expression.Members));
                }
                else
                {
                    return(Expression.New(expression.Constructor, newArguments));
                }
                // ReSharper restore ConditionIsAlwaysTrueOrFalse
            }

            return(expression);
        }
        /// <summary>
        /// Gets the constant value of the given expression, assuming it is a <see cref="ConstantExpression"/>. If it is
        /// not, an <see cref="InvalidOperationException"/> is thrown.
        /// </summary>
        /// <typeparam name="T">The expected value type. If the value is not of this type, an <see cref="InvalidOperationException"/> is thrown.</typeparam>
        /// <param name="expressionName">A string describing the value; this will be included in the exception message if an exception is thrown.</param>
        /// <param name="expression">The expression whose value to get.</param>
        /// <returns>
        /// The constant value of the given <paramref name="expression"/>.
        /// </returns>
        protected T GetConstantValueFromExpression <T> (string expressionName, Expression expression)
        {
            ArgumentUtility.CheckNotNull("expression", expression);
            if (!typeof(T).GetTypeInfo().IsAssignableFrom(expression.Type.GetTypeInfo()))
            {
                var message = string.Format(
                    "The value stored by the {0} expression ('{1}') is not of type '{2}', it is of type '{3}'.",
                    expressionName,
                    FormattingExpressionTreeVisitor.Format(expression),
                    typeof(T),
                    expression.Type);
                throw new ArgumentException(message, "expression");
            }

            var itemAsConstantExpression = expression as ConstantExpression;

            if (itemAsConstantExpression != null)
            {
                return((T)itemAsConstantExpression.Value);
            }
            else
            {
                var message = string.Format(
                    "The {0} expression ('{1}') is no ConstantExpression, it is a {2}.",
                    expressionName,
                    FormattingExpressionTreeVisitor.Format(expression),
                    expression.GetType().Name);
                throw new ArgumentException(message, "expression");
            }
        }
Esempio n. 5
0
        public Expression Transform(MethodCallExpression methodCallExpression)
        {
            ArgumentUtility.CheckNotNull("methodCallExpression", methodCallExpression);

            if (methodCallExpression.Arguments.Count == 2)
            {
                return(new SqlFunctionExpression(typeof(bool), "FREETEXT", methodCallExpression.Arguments[0], methodCallExpression.Arguments[1]));
            }
            else if (methodCallExpression.Arguments.Count == 3)
            {
                MethodCallTransformerUtility.CheckConstantExpression(
                    methodCallExpression.Method.Name, methodCallExpression.Arguments[2], "language parameter");

                var compositeExpression = new SqlCompositeCustomTextGeneratorExpression(
                    typeof(string), new SqlCustomTextExpression("LANGUAGE ", typeof(string)), methodCallExpression.Arguments[2]);

                return(new SqlFunctionExpression(
                           typeof(bool), "FREETEXT", methodCallExpression.Arguments[0], methodCallExpression.Arguments[1], compositeExpression));
            }
            else
            {
                var message = string.Format(
                    "IndexOf function with {0} arguments is not supported. Expression: '{1}'",
                    methodCallExpression.Arguments.Count,
                    FormattingExpressionTreeVisitor.Format(methodCallExpression));
                throw new NotSupportedException(message);
            }
        }
Esempio n. 6
0
 public override string ToString()
 => "Include("
 + FormattingExpressionTreeVisitor.Format(NavigationPropertyPath)
 + (_chainedNavigationProperties.Count > 0
            ? _chainedNavigationProperties.Select(p => p.Name).Join(".")
            : string.Empty)
 + ")";
        public void VisitUnknownNonExtensionExpression()
        {
            var expression = new UnknownExpression(typeof(object));
            var result     = FormattingExpressionTreeVisitor.Format(expression);

            Assert.That(result, Is.EqualTo("[-1]"));
        }
Esempio n. 8
0
 public override string ToString()
 {
     return(string.Format(
                "{0} ON {1}",
                ForeignTableInfo,
                FormattingExpressionTreeVisitor.Format(JoinCondition)));
 }
        public static FromExpressionInfo AnalyzeFromExpression(
            Expression fromExpression,
            ISqlPreparationStage stage,
            UniqueIdentifierGenerator generator,
            IMethodCallTransformerProvider provider,
            ISqlPreparationContext context,
            Func <ITableInfo, SqlTable> tableGenerator)
        {
            ArgumentUtility.CheckNotNull("fromExpression", fromExpression);
            ArgumentUtility.CheckNotNull("stage", stage);
            ArgumentUtility.CheckNotNull("generator", generator);
            ArgumentUtility.CheckNotNull("provider", provider);
            ArgumentUtility.CheckNotNull("context", context);

            var visitor = new SqlPreparationFromExpressionVisitor(generator, stage, provider, context, tableGenerator);

            visitor.VisitExpression(fromExpression);
            if (visitor.FromExpressionInfo != null)
            {
                return(visitor.FromExpressionInfo.Value);
            }

            var message = string.Format(
                "Error parsing expression '{0}'. Expressions of type '{1}' cannot be used as the SqlTables of a from clause.",
                FormattingExpressionTreeVisitor.Format(fromExpression),
                fromExpression.Type.Name);

            throw new NotSupportedException(message);
        }
        public void VisitExtensionExpression()
        {
            var expression = new TestExtensionExpression(Expression.Constant(0));
            var result     = FormattingExpressionTreeVisitor.Format(expression);

            Assert.That(result, Is.EqualTo("Test(0)"));
        }
Esempio n. 11
0
        private Expression CombineComparisons(
            Expression previousParts,
            Expression currentPart,
            ExpressionType comparisonExpressionType,
            Expression leftCompoundExpression,
            Expression rightCompoundExpression)
        {
            if (previousParts == null)
            {
                previousParts = currentPart;
            }
            else
            {
                switch (comparisonExpressionType)
                {
                case ExpressionType.Equal:
                    previousParts = Expression.AndAlso(previousParts, currentPart);
                    break;

                case ExpressionType.NotEqual:
                    previousParts = Expression.OrElse(previousParts, currentPart);
                    break;

                default:
                    var message = string.Format(
                        "Compound values can only be compared using 'Equal' and 'NotEqual', not '{0}'. Expressions: {1}, {2}",
                        comparisonExpressionType,
                        FormattingExpressionTreeVisitor.Format(leftCompoundExpression),
                        FormattingExpressionTreeVisitor.Format(rightCompoundExpression));
                    throw new NotSupportedException(message);
                }
            }
            return(previousParts);
        }
Esempio n. 12
0
 public override string ToString()
 {
     return(string.Format(
                "{0} IN {1}",
                FormattingExpressionTreeVisitor.Format(_leftExpression),
                FormattingExpressionTreeVisitor.Format(_rightExpression)));
 }
Esempio n. 13
0
        private IEnumerable <Expression> GetConcatenatedItems(MethodCallExpression methodCallExpression)
        {
            if (methodCallExpression.Arguments.Count == 1 &&
                (typeof(IEnumerable).IsAssignableFrom(methodCallExpression.Arguments[0].Type) &&
                 methodCallExpression.Arguments[0].Type != typeof(string)))
            {
                ConstantExpression argumentAsConstantExpression;
                NewArrayExpression argumentAsNewArrayExpression;

                if ((argumentAsNewArrayExpression = methodCallExpression.Arguments[0] as NewArrayExpression) != null)
                {
                    return(argumentAsNewArrayExpression.Expressions);
                }
                else if ((argumentAsConstantExpression = methodCallExpression.Arguments[0] as ConstantExpression) != null)
                {
                    return(((object[])argumentAsConstantExpression.Value).Select(element => (Expression)Expression.Constant(element)));
                }
                else
                {
                    var message = string.Format(
                        "The method call '{0}' is not supported. When the array overloads of String.Concat are used, only constant or new array expressions can "
                        + "be translated to SQL; in this usage, the expression has type '{1}'.",
                        FormattingExpressionTreeVisitor.Format(methodCallExpression),
                        methodCallExpression.Arguments[0].GetType());
                    throw new NotSupportedException(message);
                }
            }
            else
            {
                return(methodCallExpression.Arguments);
            }
        }
        protected override Expression VisitMethodCallExpression(MethodCallExpression expression)
        {
            //unsupported method can be run in memory
            if (Query.CanQueryInMemory)
            {
                Query.ShouldQueryInMemory = true;

                VisitExpression(expression.Object);

                foreach (var arg in expression.Arguments)
                {
                    VisitExpression(arg);
                }

                return(expression);
            }

            var sb = new StringBuilder();

            foreach (var candidate in Query.ExpressionMatchers)
            {
                if (candidate.TryMatch(expression, sb, exp => VisitExpression(exp), Query.Context, Query.ConverterFactory))
                {
                    return(expression);
                }
            }

            throw new FrameworkException("Unsupported method call: " + expression.Method.Name
                                         + " in query " + FormattingExpressionTreeVisitor.Format(expression) + ".");
        }
Esempio n. 15
0
        protected override Expression VisitNewExpression(NewExpression expression)
        {
            ArgumentUtility.CheckNotNull("expression", expression);

            // This ReSharper warning is wrong, expression.Members can be null.
            // ReSharper disable ConditionIsAlwaysTrueOrFalse
            if (expression.Members != null && expression.Members.Count > 0)
            // ReSharper restore ConditionIsAlwaysTrueOrFalse
            {
                // Scenario: (new X (A = arg1, B = arg2, ...)).Member - we can resolve this if one of (A, B, ...) matches Member.
                // Use the MemberBinding classes to determine this. (This takes care of A, B, ... and Member being  of different member types,
                // e.g., accessor MethodInfo and PropertyInfo.)
                var membersAndAssignedExpressions = expression.Members.Select((m, i) => MemberBinding.Bind(m, expression.Arguments[i]));
                var result = membersAndAssignedExpressions.SingleOrDefault(c => c.MatchesReadAccess(_memberInfo));

                if (result != null)
                {
                    // remove name if any - the name is only required at the definition, not at the reference
                    return(_context.RemoveNamesAndUpdateMapping(result.AssociatedExpression));
                }
            }

            // Scenario: (new X (A = arg1, B = arg2, ...)).Member - with a non-matching Member; or
            // Scenario: (new X (arg1, arg2, ...)).Member - we can't resolve this ATM


            throw new NotSupportedException(
                      string.Format(
                          "The member '{0}.{1}' cannot be translated to SQL. Expression: '{2}'",
                          expression.Type.Name,
                          _memberInfo.Name,
                          FormattingExpressionTreeVisitor.Format(expression)));
        }
        public void OrdinaryExpression()
        {
            var expression          = Expression.MakeBinary(ExpressionType.GreaterThan, Expression.Constant(1), Expression.Constant(2));
            var formattedExpression = FormattingExpressionTreeVisitor.Format(expression);

            Assert.That(formattedExpression, Is.EqualTo("(1 > 2)"));
        }
Esempio n. 17
0
 public override string ToString()
 {
     return(string.Format(
                "GroupBy({0}, {1})",
                FormattingExpressionTreeVisitor.Format(KeySelector),
                FormattingExpressionTreeVisitor.Format(ElementSelector)));
 }
Esempio n. 18
0
 public override string ToString()
 {
     return(String.Format(
                "GROUPING (KEY: {0}, ELEMENT: {1}, AGGREGATIONS: ({2}))",
                FormattingExpressionTreeVisitor.Format(KeyExpression),
                FormattingExpressionTreeVisitor.Format(ElementExpression),
                string.Join(", ", AggregationExpressions.Select(FormattingExpressionTreeVisitor.Format))));
 }
 public override string ToString()
 {
     return(string.Format(
                @"PartialEvalException ({0} (""{1}""), {2})",
                _exception.GetType().Name,
                _exception.Message,
                FormattingExpressionTreeVisitor.Format(_evaluatedExpression)));
 }
 public override string ToString()
 {
     return(string.Format(
                "{0} LIKE {1} ESCAPE {2}",
                FormattingExpressionTreeVisitor.Format(_left),
                FormattingExpressionTreeVisitor.Format(_right),
                FormattingExpressionTreeVisitor.Format(_escapeExpression)));
 }
Esempio n. 21
0
 public override string ToString()
 {
     return("Include("
            + FormattingExpressionTreeVisitor.Format(NavigationPropertyPath)
            + (_chainedNavigationProperties != null
                ? "." + _chainedNavigationProperties.Select(p => p.Name).Join(".")
                : null)
            + ")");
 }
Esempio n. 22
0
        public Expression Transform(MethodCallExpression methodCallExpression)
        {
            ArgumentUtility.CheckNotNull("methodCallExpression", methodCallExpression);

            MethodCallTransformerUtility.CheckArgumentCount(methodCallExpression, 1);
            MethodCallTransformerUtility.CheckInstanceMethod(methodCallExpression);

            switch (methodCallExpression.Method.Name)
            {
            case "Add":
                Trace.Assert(methodCallExpression.Method.Name == "Add");
                var constantTimeSpanExpression = methodCallExpression.Arguments[0] as ConstantExpression;
                if (constantTimeSpanExpression == null)
                {
                    var message =
                        string.Format(
                            "The method 'System.DateTime.Add' can only be transformed to SQL when its argument is a constant value. Expression: '{0}'.",
                            FormattingExpressionTreeVisitor.Format(methodCallExpression));
                    throw new NotSupportedException(message);
                }

                return(AddTimeSpan((TimeSpan)constantTimeSpanExpression.Value, methodCallExpression.Object));

            case "AddDays":
                return(AddWithConversion(
                           methodCallExpression.Arguments[0], TimeSpan.TicksPerDay / TimeSpan.TicksPerMillisecond, methodCallExpression.Object));

            case "AddHours":
                return(AddWithConversion(
                           methodCallExpression.Arguments[0], TimeSpan.TicksPerHour / TimeSpan.TicksPerMillisecond, methodCallExpression.Object));

            case "AddMilliseconds":
                return(AddMilliseconds(methodCallExpression.Arguments[0], methodCallExpression.Object));

            case "AddMinutes":
                return(AddWithConversion(
                           methodCallExpression.Arguments[0], TimeSpan.TicksPerMinute / TimeSpan.TicksPerMillisecond, methodCallExpression.Object));

            case "AddMonths":
                return(AddUnits(methodCallExpression.Arguments[0], "month", methodCallExpression.Object));

            case "AddSeconds":
                return(AddWithConversion(
                           methodCallExpression.Arguments[0], TimeSpan.TicksPerSecond / TimeSpan.TicksPerMillisecond, methodCallExpression.Object));

            case "AddTicks":
                return(AddTicks(methodCallExpression.Arguments[0], methodCallExpression.Object));

            case "AddYears":
                return(AddUnits(methodCallExpression.Arguments[0], "year", methodCallExpression.Object));

            default:
                var argumentExceptionMessage = string.Format(
                    "The method '{0}.{1}' is not a supported method.", methodCallExpression.Method.DeclaringType, methodCallExpression.Method.Name);
                throw new ArgumentException(argumentExceptionMessage, "methodCallExpression");
            }
        }
Esempio n. 23
0
        protected override Exception CreateUnhandledItemException <T> (T unhandledItem, string visitMethod)
        {
            var message = string.Format(
                "The expression '{0}' cannot be translated to SQL text by this SQL generator. Expression type '{1}' is not supported.",
                FormattingExpressionTreeVisitor.Format((Expression)(object)unhandledItem),
                unhandledItem.GetType().Name);

            throw new NotSupportedException(message);
        }
        public void QuerySourceReferenceExpression()
        {
            var referencedClause = ExpressionHelper.CreateMainFromClause_Int("i", typeof(int), ExpressionHelper.CreateQueryable <Cook>());

            var expression          = Expression.MakeBinary(ExpressionType.GreaterThan, new QuerySourceReferenceExpression(referencedClause), Expression.Constant(2));
            var formattedExpression = FormattingExpressionTreeVisitor.Format(expression);

            Assert.That(formattedExpression, Is.EqualTo("([i] > 2)"));
        }
Esempio n. 25
0
 public override string ToString()
 {
     return(string.Format(
                "join {0} {1} in {2} on {3} equals {4}",
                ItemType.Name,
                ItemName,
                FormattingExpressionTreeVisitor.Format(InnerSequence),
                FormattingExpressionTreeVisitor.Format(OuterKeySelector),
                FormattingExpressionTreeVisitor.Format(InnerKeySelector)));
 }
        public void SubQueryExpression()
        {
            var queryExpression = ExpressionHelper.MakeExpression(() => (from s in ExpressionHelper.CreateQueryable <Cook> () select s).Count());
            var subQueryModel   = ExpressionHelper.ParseQuery(queryExpression);

            var expression          = Expression.MakeBinary(ExpressionType.GreaterThan, new SubQueryExpression(subQueryModel), Expression.Constant(2));
            var formattedExpression = FormattingExpressionTreeVisitor.Format(expression);

            Assert.That(formattedExpression, Is.EqualTo("({TestQueryable<Cook>() => Count()} > 2)"));
        }
Esempio n. 27
0
        protected override Expression VisitMethodCallExpression(MethodCallExpression expression)
        {
            string message = string.Format(
                "The method '{0}.{1}' is not supported by this code generator, and no custom transformer has been registered. Expression: '{2}'",
                expression.Method.DeclaringType,
                expression.Method.Name,
                FormattingExpressionTreeVisitor.Format(expression));

            throw new NotSupportedException(message);
        }
        /// <summary>
        /// Formats an unhandled item for representing the expression as a string.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="unhandledItem">The unhandled item.</param>
        /// <returns></returns>
        /// <remarks></remarks>
        public static string FormatUnhandledItem <T>(T unhandledItem) where T : class
        {
            Mandate.ParameterNotNull(unhandledItem, "unhandledItem");

            var itemAsExpression = unhandledItem as Expression;

            return(itemAsExpression != null
                       ? FormattingExpressionTreeVisitor.Format(itemAsExpression)
                       : unhandledItem.ToString());
        }
Esempio n. 29
0
        public static void CheckAreEqualTrees(Expression expectedTree, Expression actualTree)
        {
            ArgumentUtility.CheckNotNull("expectedTree", expectedTree);
            ArgumentUtility.CheckNotNull("actualTree", actualTree);

            var comparer = new SqlExpressionTreeComparer(
                FormattingExpressionTreeVisitor.Format(expectedTree),
                FormattingExpressionTreeVisitor.Format(actualTree));

            comparer.CheckAreEqualNodes(expectedTree, actualTree);
        }
Esempio n. 30
0
 public override string ToString()
 {
     if (OptionalDefaultValue == null)
     {
         return("DefaultIfEmpty()");
     }
     else
     {
         return("DefaultIfEmpty(" + FormattingExpressionTreeVisitor.Format(OptionalDefaultValue) + ")");
     }
 }