예제 #1
0
        protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
        {
            QueryJoinClause o = other as QueryJoinClause;

            return(o != null && this.IsGroupJoin == o.IsGroupJoin &&
                   this.Type.DoMatch(o.Type, match) && MatchString(this.JoinIdentifier, o.JoinIdentifier) &&
                   this.InExpression.DoMatch(o.InExpression, match) && this.OnExpression.DoMatch(o.OnExpression, match) &&
                   this.EqualsExpression.DoMatch(o.EqualsExpression, match) &&
                   MatchString(this.IntoIdentifier, o.IntoIdentifier));
        }
예제 #2
0
        S IAstVisitor <T, S> .VisitQueryJoinClause(QueryJoinClause queryJoinClause, T data)
        {
            var handler = QueryJoinClauseVisited;

            if (handler != null)
            {
                handler(queryJoinClause, data);
            }
            return(VisitChildren(queryJoinClause, data));
        }
예제 #3
0
            public override AstNode VisitQueryJoinClause(QueryJoinClause queryJoinClause)
            {
                Expression resultSelectorBody = null;
                var        inExpression       = VisitNested(queryJoinClause.InExpression, null);

                if (!queryJoinClause.Type.IsNull)
                {
                    inExpression = inExpression.Invoke("Cast", new[] { queryJoinClause.Type.Clone() }, EmptyList <Expression> .Instance);
                }
                var key1SelectorFirstParam = CreateParameterForCurrentRangeVariable();
                var key1Selector           = CreateLambda(new[] { key1SelectorFirstParam }, VisitNested(queryJoinClause.OnExpression, key1SelectorFirstParam));
                var key2Param    = CreateParameter(Identifier.Create(queryJoinClause.JoinIdentifier));
                var key2Selector = CreateLambda(new[] { key2Param }, VisitNested(queryJoinClause.EqualsExpression, null));

                var resultSelectorFirstParam = CreateParameterForCurrentRangeVariable();

                var select = GetNextQueryClause(queryJoinClause) as QuerySelectClause;

                if (select != null)
                {
                    resultSelectorBody = VisitNested(select.Expression, resultSelectorFirstParam);
                    eatSelect          = true;
                }

                if (queryJoinClause.IntoKeyword.IsNull)
                {
                    // Normal join
                    if (resultSelectorBody == null)
                    {
                        resultSelectorBody = AddMemberToCurrentTransparentType(resultSelectorFirstParam, queryJoinClause.JoinIdentifierToken, new IdentifierExpression(queryJoinClause.JoinIdentifier), false);
                    }

                    var resultSelector = CreateLambda(new[] { resultSelectorFirstParam, CreateParameter(Identifier.Create(queryJoinClause.JoinIdentifier)) }, resultSelectorBody);
                    rangeVariables[queryJoinClause.JoinIdentifierToken] = key2Param;
                    return(currentResult.Invoke("Join", inExpression, key1Selector, key2Selector, resultSelector));
                }
                else
                {
                    // Group join
                    if (resultSelectorBody == null)
                    {
                        resultSelectorBody = AddMemberToCurrentTransparentType(resultSelectorFirstParam, queryJoinClause.IntoIdentifierToken, new IdentifierExpression(queryJoinClause.IntoIdentifier), false);
                    }

                    var intoParam      = CreateParameter(Identifier.Create(queryJoinClause.IntoIdentifier));
                    var resultSelector = CreateLambda(new[] { resultSelectorFirstParam, intoParam }, resultSelectorBody);
                    rangeVariables[queryJoinClause.IntoIdentifierToken] = intoParam;

                    return(currentResult.Invoke("GroupJoin", inExpression, key1Selector, key2Selector, resultSelector));
                }
            }
예제 #4
0
        QueryExpression DecompileQuery(InvocationExpression invocation)
        {
            if (invocation == null)
            {
                return(null);
            }
            MemberReferenceExpression mre = invocation.Target as MemberReferenceExpression;

            if (mre == null)
            {
                return(null);
            }

            switch (mre.MemberName)
            {
            case "Select":
            {
                if (invocation.Arguments.Count != 1)
                {
                    return(null);
                }
                string     parameterName;
                Expression body;
                if (MatchSimpleLambda(invocation.Arguments.Single(), out parameterName, out body))
                {
                    QueryExpression query = new QueryExpression();
                    query.Clauses.Add(new QueryFromClause {
                            Identifier = parameterName, Expression = ExtractQuery(mre)
                        });
                    query.Clauses.Add(new QuerySelectClause {
                            Expression = body.Detach()
                        });
                    return(query);
                }
                return(null);
            }

            case "Cast":
            {
                if (invocation.Arguments.Count == 0 && mre.TypeArguments.Count == 1)
                {
                    var typeArgument = mre.TypeArguments.First();

                    QueryExpression query   = new QueryExpression();
                    string          varName = GenerateVariableName();
                    query.Clauses.Add(new QueryFromClause {
                            Identifier = varName,
                            Expression = ExtractQuery(mre),
                            Type       = typeArgument.Detach()
                        });
                    return(query);
                }
                return(null);
            }

            case "GroupBy":
            {
                if (invocation.Arguments.Count == 2)
                {
                    string     parameterName1, parameterName2;
                    Expression keySelector, elementSelector;
                    if (MatchSimpleLambda(invocation.Arguments.ElementAt(0), out parameterName1, out keySelector) &&
                        MatchSimpleLambda(invocation.Arguments.ElementAt(1), out parameterName2, out elementSelector) &&
                        parameterName1 == parameterName2)
                    {
                        QueryExpression query = new QueryExpression();
                        query.Clauses.Add(new QueryFromClause {
                                Identifier = parameterName1, Expression = ExtractQuery(mre)
                            });
                        query.Clauses.Add(new QueryGroupClause {
                                Projection = elementSelector.Detach(), Key = keySelector.Detach()
                            });
                        return(query);
                    }
                }
                else if (invocation.Arguments.Count == 1)
                {
                    string     parameterName;
                    Expression keySelector;
                    if (MatchSimpleLambda(invocation.Arguments.Single(), out parameterName, out keySelector))
                    {
                        QueryExpression query = new QueryExpression();
                        query.Clauses.Add(new QueryFromClause {
                                Identifier = parameterName, Expression = ExtractQuery(mre)
                            });
                        query.Clauses.Add(new QueryGroupClause {
                                Projection = new IdentifierExpression(parameterName),
                                Key        = keySelector.Detach()
                            });
                        return(query);
                    }
                }
                return(null);
            }

            case "SelectMany":
            {
                if (invocation.Arguments.Count != 2)
                {
                    return(null);
                }
                string     parameterName;
                Expression collectionSelector;
                if (!MatchSimpleLambda(invocation.Arguments.ElementAt(0), out parameterName, out collectionSelector))
                {
                    return(null);
                }
                LambdaExpression lambda = invocation.Arguments.ElementAt(1) as LambdaExpression;
                if (lambda != null && lambda.Parameters.Count == 2 && lambda.Body is Expression)
                {
                    ParameterDeclaration p1    = lambda.Parameters.ElementAt(0);
                    ParameterDeclaration p2    = lambda.Parameters.ElementAt(1);
                    QueryExpression      query = new QueryExpression();
                    query.Clauses.Add(new QueryFromClause {
                            Identifier = p1.Name, Expression = ExtractQuery(mre)
                        });
                    query.Clauses.Add(new QueryFromClause {
                            Identifier = p2.Name, Expression = collectionSelector.Detach()
                        });
                    query.Clauses.Add(new QuerySelectClause {
                            Expression = ((Expression)lambda.Body).Detach()
                        });
                    return(query);
                }
                return(null);
            }

            case "Where":
            {
                if (invocation.Arguments.Count != 1)
                {
                    return(null);
                }
                string     parameterName;
                Expression body;
                if (MatchSimpleLambda(invocation.Arguments.Single(), out parameterName, out body))
                {
                    QueryExpression query = new QueryExpression();
                    query.Clauses.Add(new QueryFromClause {
                            Identifier = parameterName, Expression = ExtractQuery(mre)
                        });
                    query.Clauses.Add(new QueryWhereClause {
                            Condition = body.Detach()
                        });
                    return(query);
                }
                return(null);
            }

            case "OrderBy":
            case "OrderByDescending":
            case "ThenBy":
            case "ThenByDescending":
            {
                if (invocation.Arguments.Count != 1)
                {
                    return(null);
                }
                string     parameterName;
                Expression orderExpression;
                if (MatchSimpleLambda(invocation.Arguments.Single(), out parameterName, out orderExpression))
                {
                    if (ValidateThenByChain(invocation, parameterName))
                    {
                        QueryOrderClause     orderClause = new QueryOrderClause();
                        InvocationExpression tmp         = invocation;
                        while (mre.MemberName == "ThenBy" || mre.MemberName == "ThenByDescending")
                        {
                            // insert new ordering at beginning
                            orderClause.Orderings.InsertAfter(
                                null, new QueryOrdering {
                                    Expression = orderExpression.Detach(),
                                    Direction  = (mre.MemberName == "ThenBy" ? QueryOrderingDirection.None : QueryOrderingDirection.Descending)
                                });

                            tmp = (InvocationExpression)mre.Target;
                            mre = (MemberReferenceExpression)tmp.Target;
                            MatchSimpleLambda(tmp.Arguments.Single(), out parameterName, out orderExpression);
                        }
                        // insert new ordering at beginning
                        orderClause.Orderings.InsertAfter(
                            null, new QueryOrdering {
                                Expression = orderExpression.Detach(),
                                Direction  = (mre.MemberName == "OrderBy" ? QueryOrderingDirection.None : QueryOrderingDirection.Descending)
                            });

                        QueryExpression query = new QueryExpression();
                        query.Clauses.Add(new QueryFromClause {
                                Identifier = parameterName, Expression = ExtractQuery(mre)
                            });
                        query.Clauses.Add(orderClause);
                        return(query);
                    }
                }
                return(null);
            }

            case "Join":
            case "GroupJoin":
            {
                if (invocation.Arguments.Count != 4)
                {
                    return(null);
                }
                Expression source1 = mre.Target;
                Expression source2 = invocation.Arguments.ElementAt(0);
                string     elementName1, elementName2;
                Expression key1, key2;
                if (!MatchSimpleLambda(invocation.Arguments.ElementAt(1), out elementName1, out key1))
                {
                    return(null);
                }
                if (!MatchSimpleLambda(invocation.Arguments.ElementAt(2), out elementName2, out key2))
                {
                    return(null);
                }
                LambdaExpression lambda = invocation.Arguments.ElementAt(3) as LambdaExpression;
                if (lambda != null && lambda.Parameters.Count == 2 && lambda.Body is Expression)
                {
                    ParameterDeclaration p1    = lambda.Parameters.ElementAt(0);
                    ParameterDeclaration p2    = lambda.Parameters.ElementAt(1);
                    QueryExpression      query = new QueryExpression();
                    query.Clauses.Add(new QueryFromClause {
                            Identifier = elementName1, Expression = source1.Detach()
                        });
                    QueryJoinClause joinClause = new QueryJoinClause();

                    joinClause.JoinIdentifier = elementName2;                                        // join elementName2
                    joinClause.InExpression   = source2.Detach();                                    // in source2

                    Match castMatch = castPattern.Match(source2);
                    if (castMatch.Success)
                    {
                        Expression target = castMatch.Get <Expression>("inExpr").Single().Detach();
                        joinClause.Type         = castMatch.Get <AstType>("targetType").Single().Detach();
                        joinClause.InExpression = target;
                    }

                    joinClause.OnExpression     = key1.Detach();                                     // on key1
                    joinClause.EqualsExpression = key2.Detach();                                     // equals key2
                    if (mre.MemberName == "GroupJoin")
                    {
                        joinClause.IntoIdentifier = p2.Name;                                         // into p2.Name
                    }
                    query.Clauses.Add(joinClause);
                    Expression resultExpr = ((Expression)lambda.Body).Detach();
                    if (p1.Name != elementName1)
                    {
                        foreach (var identifier in resultExpr.Descendants.OfType <Identifier>().Where(id => id.Name == p1.Name))
                        {
                            identifier.Name = elementName1;
                        }
                    }
                    if (p2.Name != elementName2 && mre.MemberName != "GroupJoin")
                    {
                        foreach (var identifier in resultExpr.Descendants.OfType <Identifier>().Where(id => id.Name == p2.Name))
                        {
                            identifier.Name = elementName2;
                        }
                    }
                    query.Clauses.Add(new QuerySelectClause {
                            Expression = resultExpr
                        });
                    return(query);
                }
                return(null);
            }

            default:
                return(null);
            }
        }
예제 #5
0
 void IAstVisitor.VisitQueryJoinClause(QueryJoinClause queryJoinClause)
 {
     Visit(EnterQueryJoinClause, LeaveQueryJoinClause, queryJoinClause);
 }
예제 #6
0
 public virtual S VisitQueryJoinClause(QueryJoinClause queryJoinClause, T data)
 {
     return(VisitChildren(queryJoinClause, data));
 }
예제 #7
0
 public override void VisitQueryJoinClause(QueryJoinClause queryJoinClause)
 {
     FixClauseIndentation(queryJoinClause, queryJoinClause.JoinKeyword);
 }
 public virtual S VisitQueryJoinClause(QueryJoinClause queryJoinClause, T data)
 {
     throw new NotImplementedException();
 }