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

            return(o != null && this.Type.DoMatch(o.Type, match) && MatchString(this.Identifier, o.Identifier) &&
                   this.Expression.DoMatch(o.Expression, match));
        }
        public Expression ConvertFluentToQuery(Expression node)
        {
            node = node.Clone();

            var artificialParent = new ExpressionStatement();

            artificialParent.Expression = node;

            DecompileQueries(node);
            // After all queries were decompiled, detect degenerate queries (queries not property terminated with 'select' or 'group')
            // and fix them, either by adding a degenerate select, or by combining them with another query.
            foreach (QueryExpression query in artificialParent.Descendants.OfType <QueryExpression>())
            {
                QueryFromClause fromClause = (QueryFromClause)query.Clauses.First();
                if (IsDegenerateQuery(query))
                {
                    string identifierName = fromClause.Identifier;

                    // introduce select for degenerate query
                    query.Clauses.Add(new QuerySelectClause {
                        Expression = new IdentifierExpression(identifierName)
                    });
                }

                if (fromClause.Type.IsNull)
                {
                    // See if the data source of this query is a degenerate query,
                    // and combine the queries if possible.
                    QueryExpression innerQuery = fromClause.Expression as QueryExpression;
                    while (IsDegenerateQuery(innerQuery))
                    {
                        QueryFromClause innerFromClause = (QueryFromClause)innerQuery.Clauses.First();
                        if (fromClause.Identifier != innerFromClause.Identifier && !innerFromClause.Identifier.StartsWith("<>"))
                        {
                            break;
                        }
                        // Replace the fromClause with all clauses from the inner query
                        fromClause.Remove();
                        foreach (var identifierChild in innerQuery.Descendants.OfType <Identifier>().Where(identifier => identifier.Name == innerFromClause.Identifier))
                        {
                            //When the identifier is "<>X", then replace it with the outer one
                            identifierChild.ReplaceWith(fromClause.IdentifierToken.Clone());
                        }
                        QueryClause insertionPos = null;
                        foreach (var clause in innerQuery.Clauses)
                        {
                            query.Clauses.InsertAfter(insertionPos, insertionPos = clause.Detach());
                        }
                        fromClause = innerFromClause;
                        innerQuery = fromClause.Expression as QueryExpression;
                    }
                }
            }

            return(artificialParent.Expression.Clone());
        }
        public string CombineQuery(AstNode node, AstNode rootQuery = null)
        {
            if (rootQuery == null)
            {
                rootQuery = node;
            }

            QueryExpression query = node as QueryExpression;

            if (query != null)
            {
                string continuationIdentifier = null;

                foreach (var clause in query.Clauses)
                {
                    var continuation = clause as QueryContinuationClause;
                    if (continuation != null)
                    {
                        CombineQuery(continuation.PrecedingQuery);
                    }

                    var from = clause as QueryFromClause;
                    if (from != null)
                    {
                        continuationIdentifier = CombineQuery(from.Expression, rootQuery);
                    }
                }

                QueryFromClause fromClause = (QueryFromClause)query.Clauses.First();
                QueryExpression innerQuery = fromClause.Expression as QueryExpression;
                if (innerQuery != null)
                {
                    continuationIdentifier = continuationIdentifier ?? ((QueryFromClause)innerQuery.Clauses.First()).Identifier;

                    string transparentIdentifier;
                    if (TryRemoveTransparentIdentifier(query, fromClause, innerQuery, continuationIdentifier, out transparentIdentifier))
                    {
                        RemoveTransparentIdentifierReferences(rootQuery, transparentIdentifier);
                    }
                    else if (fromClause.Type.IsNull)
                    {
                        QueryContinuationClause continuation = new QueryContinuationClause();
                        continuation.PrecedingQuery = innerQuery.Detach();
                        continuation.Identifier     = fromClause.Identifier;
                        fromClause.ReplaceWith(continuation);
                    }

                    return(transparentIdentifier);
                }
                else
                {
                    Match m = castPattern.Match(fromClause.Expression);
                    if (m.Success)
                    {
                        fromClause.Type       = m.Get <AstType>("targetType").Single().Detach();
                        fromClause.Expression = m.Get <Expression>("inExpr").Single().Detach();
                    }
                }
            }

            return(null);
        }
        bool TryRemoveTransparentIdentifier(QueryExpression query, QueryFromClause fromClause, QueryExpression innerQuery, string continuationIdentifier, out string transparentIdentifier)
        {
            transparentIdentifier = fromClause.Identifier;

            Match match = selectTransparentIdentifierPattern.Match(innerQuery.Clauses.Last());

            if (!match.Success)
            {
                return(false);
            }
            QuerySelectClause selectClause = (QuerySelectClause)innerQuery.Clauses.Last();
            Expression        nae1         = match.Get <Expression>("nae1").SingleOrDefault();
            string            nae1Name     = ExtractExpressionName(ref nae1);

            if (nae1Name == null)
            {
                return(false);
            }

            Expression nae2     = match.Get <Expression>("nae2").SingleOrDefault();
            string     nae2Name = ExtractExpressionName(ref nae2);

            if (nae1Name == null)
            {
                return(false);
            }

            bool introduceLetClause = true;
            var  nae1Identifier     = nae1 as IdentifierExpression;
            var  nae2Identifier     = nae2 as IdentifierExpression;

            if (nae1Identifier != null && nae2Identifier != null && nae1Identifier.Identifier == nae1Name && nae2Identifier.Identifier == nae2Name)
            {
                introduceLetClause = false;
            }

            if (nae1Name != continuationIdentifier)
            {
                if (nae2Name == continuationIdentifier)
                {
                    //Members are in reversed order
                    string     tempName = nae1Name;
                    Expression tempNae  = nae1;

                    nae1Name = nae2Name;
                    nae1     = nae2;
                    nae2Name = tempName;
                    nae2     = tempNae;
                }
                else
                {
                    return(false);
                }
            }

            if (introduceLetClause && innerQuery.Clauses.OfType <QueryFromClause>().Any(from => from.Identifier == nae2Name))
            {
                return(false);
            }
            if (introduceLetClause && innerQuery.Clauses.OfType <QueryJoinClause>().Any(join => join.JoinIdentifier == nae2Name))
            {
                return(false);
            }

            // from * in (from x in ... select new { x = x, y = expr }) ...
            // =>
            // from x in ... let y = expr ...
            fromClause.Remove();
            selectClause.Remove();
            // Move clauses from innerQuery to query
            QueryClause insertionPos = null;

            foreach (var clause in innerQuery.Clauses)
            {
                query.Clauses.InsertAfter(insertionPos, insertionPos = clause.Detach());
            }
            if (introduceLetClause)
            {
                query.Clauses.InsertAfter(insertionPos, new QueryLetClause {
                    Identifier = nae2Name, Expression = nae2.Detach()
                });
            }
            return(true);
        }
예제 #5
0
 void IAstVisitor.VisitQueryFromClause(QueryFromClause queryFromClause)
 {
     Visit(EnterQueryFromClause, LeaveQueryFromClause, queryFromClause);
 }
 public override void VisitQueryFromClause(QueryFromClause queryFromClause)
 {
     FixClauseIndentation(queryFromClause, queryFromClause.FromKeyword);
 }