internal override SqlExpression VisitGrouping(SqlGrouping g)
        {
            SqlGrouping n = new SqlGrouping(g.ClrType, g.SqlType,
                                            this.VisitExpression(g.Key), this.VisitExpression(g.Group), g.SourceExpression
                                            );

            return(n);
        }
 internal override SqlExpression VisitGrouping(SqlGrouping g) {
     if (!isDebugMode) {
         throw Error.InvalidFormatNode("Grouping");
     }
     sb.Append("Group(");
     this.Visit(g.Key);
     sb.Append(", ");
     this.Visit(g.Group);
     sb.Append(")");
     return g;
 }
Esempio n. 3
0
 internal virtual SqlExpression VisitGrouping(SqlGrouping g) {
     g.Key = this.VisitExpression(g.Key);
     g.Group = this.VisitExpression(g.Group);
     return g;
 }
 internal override SqlExpression VisitGrouping(SqlGrouping g) {
     SqlGrouping n = new SqlGrouping(g.ClrType, g.SqlType,
         this.VisitExpression(g.Key), this.VisitExpression(g.Group), g.SourceExpression
         );
     return n;
 }
Esempio n. 5
0
        private SqlNode VisitGroupBy(Expression sequence, LambdaExpression keyLambda, LambdaExpression elemLambda, LambdaExpression resultSelector) {
            // Convert seq.Group(elem, key) into
            //
            // SELECT s.key, MULTISET(select s2.elem from seq AS s2 where s.key == s2.key)
            // FROM seq AS s
            //
            // where key and elem can be either simple scalars or object constructions
            //
            SqlSelect seq = this.VisitSequence(sequence);
            seq = this.LockSelect(seq);
            SqlAlias seqAlias = new SqlAlias(seq);
            SqlAliasRef seqAliasRef = new SqlAliasRef(seqAlias);

            // evaluate the key expression relative to original sequence
            this.map[keyLambda.Parameters[0]] = seqAliasRef;
            SqlExpression keyExpr = this.VisitExpression(keyLambda.Body);

            // make a duplicate of the original sequence to use as a foundation of our group multiset
            SqlDuplicator sd = new SqlDuplicator();
            SqlSelect selDup = (SqlSelect)sd.Duplicate(seq);

            // rebind key in relative to the duplicate sequence
            SqlAlias selDupAlias = new SqlAlias(selDup);
            SqlAliasRef selDupRef = new SqlAliasRef(selDupAlias);
            this.map[keyLambda.Parameters[0]] = selDupRef;
            SqlExpression keyDup = this.VisitExpression(keyLambda.Body);

            SqlExpression elemExpr = null;
            SqlExpression elemOnGroupSource = null;
            if (elemLambda != null) {
                // evaluate element expression relative to the duplicate sequence
                this.map[elemLambda.Parameters[0]] = selDupRef;
                elemExpr = this.VisitExpression(elemLambda.Body);

                // evaluate element expression relative to original sequence
                this.map[elemLambda.Parameters[0]] = seqAliasRef;
                elemOnGroupSource = this.VisitExpression(elemLambda.Body);
            }
            else {
                // no elem expression supplied, so just use an alias ref to the duplicate sequence.
                // this will resolve to whatever was being produced by the sequence
                elemExpr = selDupRef;
                elemOnGroupSource = seqAliasRef;
            }

            // Make a sub expression out of the key.  This will allow a single definition of the 
            // expression to be shared at multiple points in the tree (via SqlSharedExpressionRef's)
            SqlSharedExpression keySubExpr = new SqlSharedExpression(keyExpr);
            keyExpr = new SqlSharedExpressionRef(keySubExpr);

            // construct the select clause that picks out the elements (this may be redundant...)
            SqlSelect selElem = new SqlSelect(elemExpr, selDupAlias, this.dominatingExpression);
            selElem.Where = sql.Binary(SqlNodeType.EQ2V, keyExpr, keyDup);

            // Finally, make the MULTISET node. this will be used as part of the final select
            SqlSubSelect ss = sql.SubSelect(SqlNodeType.Multiset, selElem);

            // add a layer to the original sequence before applying the actual group-by clause
            SqlSelect gsel = new SqlSelect(new SqlSharedExpressionRef(keySubExpr), seqAlias, this.dominatingExpression);
            gsel.GroupBy.Add(keySubExpr);
            SqlAlias gselAlias = new SqlAlias(gsel);

            SqlSelect result = null;
            if (resultSelector != null) {
                // Create final select to include construction of group multiset
                // select new Grouping { Key = key, Group = Multiset(select elem from seq where match) } from ...
                Type elementType = typeof(IGrouping<,>).MakeGenericType(keyExpr.ClrType, elemExpr.ClrType);

                SqlExpression keyGroup = new SqlGrouping(elementType, this.typeProvider.From(elementType), keyExpr, ss, this.dominatingExpression);
                SqlSelect keyGroupSel = new SqlSelect(keyGroup, gselAlias, this.dominatingExpression);
                SqlAlias kgAlias = new SqlAlias(keyGroupSel);
                SqlAliasRef kgAliasRef = new SqlAliasRef(kgAlias);

                this.map[resultSelector.Parameters[0]] = sql.Member(kgAliasRef, elementType.GetProperty("Key"));
                this.map[resultSelector.Parameters[1]] = kgAliasRef;

                // remember the select that has the actual group (for optimizing aggregates later)
                this.gmap[kgAliasRef] = new GroupInfo { SelectWithGroup = gsel, ElementOnGroupSource = elemOnGroupSource };

                SqlExpression resultExpr = this.VisitExpression(resultSelector.Body);
                result = new SqlSelect(resultExpr, kgAlias, this.dominatingExpression);

                // remember the select that has the actual group (for optimizing aggregates later)
                this.gmap[resultExpr] = new GroupInfo { SelectWithGroup = gsel, ElementOnGroupSource = elemOnGroupSource };
            }
            else {
                // Create final select to include construction of group multiset
                // select new Grouping { Key = key, Group = Multiset(select elem from seq where match) } from ...
                Type elementType = typeof(IGrouping<,>).MakeGenericType(keyExpr.ClrType, elemExpr.ClrType);

                SqlExpression resultExpr = new SqlGrouping(elementType, this.typeProvider.From(elementType), keyExpr, ss, this.dominatingExpression);
                result = new SqlSelect(resultExpr, gselAlias, this.dominatingExpression);

                // remember the select that has the actual group (for optimizing aggregates later)
                this.gmap[resultExpr] = new GroupInfo { SelectWithGroup = gsel, ElementOnGroupSource = elemOnGroupSource };
            }

            return result;
        }
Esempio n. 6
0
 protected virtual SqlExpression VisitGrouping(SqlGrouping expr)
 {
     return(expr);
 }
Esempio n. 7
0
 internal override SqlExpression VisitGrouping(SqlGrouping g) {
     g.Key = this.FetchExpression(g.Key);
     g.Group = this.FetchExpression(g.Group);
     return g;
 }
Esempio n. 8
0
 internal virtual SqlExpression VisitGrouping(SqlGrouping g) {
     g.Key = this.VisitExpression(g.Key);
     g.Group = this.VisitExpression(g.Group);
     return g;
 }
Esempio n. 9
0
 internal override SqlExpression VisitGrouping(SqlGrouping g) {
     g.Key = this.VisitNamedExpression(g.Key, "Key");
     g.Group = this.VisitNamedExpression(g.Group, "Group");
     return g;
 }
Esempio n. 10
0
 protected virtual SqlExpression VisitGrouping(SqlGrouping expr)
 {
     return expr;
 }
        internal static bool CanBeCompared(SqlExpression node)
        {
            if (node == null)
            {
                return(true);
            }
            switch (node.NodeType)
            {
            case SqlNodeType.New:
            {
                SqlNew new1 = (SqlNew)node;
                for (int i = 0, n = new1.Args.Count; i < n; i++)
                {
                    if (!CanBeCompared(new1.Args[i]))
                    {
                        return(false);
                    }
                }
                for (int i = 0, n = new1.Members.Count; i < n; i++)
                {
                    if (!CanBeCompared(new1.Members[i].Expression))
                    {
                        return(false);
                    }
                }
                return(true);
            }

            case SqlNodeType.ColumnRef:
            case SqlNodeType.Value:
            case SqlNodeType.UserColumn:
                return(true);

            case SqlNodeType.Link:
            {
                SqlLink l1 = (SqlLink)node;
                for (int i = 0, c = l1.KeyExpressions.Count; i < c; ++i)
                {
                    if (!CanBeCompared(l1.KeyExpressions[i]))
                    {
                        return(false);
                    }
                }
                return(true);
            }

            case SqlNodeType.OptionalValue:
                return(CanBeCompared(((SqlOptionalValue)node).Value));

            case SqlNodeType.ValueOf:
            case SqlNodeType.OuterJoinedValue:
                return(CanBeCompared(((SqlUnary)node).Operand));

            case SqlNodeType.Lift:
                return(CanBeCompared(((SqlLift)node).Expression));

            case SqlNodeType.Grouping:
            {
                SqlGrouping g1 = (SqlGrouping)node;
                return(CanBeCompared(g1.Key) && CanBeCompared(g1.Group));
            }

            case SqlNodeType.ClientArray:
            {
                if (node.SourceExpression.NodeType != ExpressionType.NewArrayInit &&
                    node.SourceExpression.NodeType != ExpressionType.NewArrayBounds)
                {
                    return(false);
                }
                SqlClientArray a1 = (SqlClientArray)node;
                for (int i = 0, n = a1.Expressions.Count; i < n; i++)
                {
                    if (!CanBeCompared(a1.Expressions[i]))
                    {
                        return(false);
                    }
                }
                return(true);
            }

            case SqlNodeType.ClientCase:
            {
                SqlClientCase c1 = (SqlClientCase)node;
                for (int i = 0, n = c1.Whens.Count; i < n; i++)
                {
                    if (!CanBeCompared(c1.Whens[i].Match) ||
                        !CanBeCompared(c1.Whens[i].Value))
                    {
                        return(false);
                    }
                }
                return(true);
            }

            case SqlNodeType.SearchedCase:
            {
                SqlSearchedCase c1 = (SqlSearchedCase)node;
                for (int i = 0, n = c1.Whens.Count; i < n; i++)
                {
                    if (!CanBeCompared(c1.Whens[i].Match) ||
                        !CanBeCompared(c1.Whens[i].Value))
                    {
                        return(false);
                    }
                }
                return(CanBeCompared(c1.Else));
            }

            case SqlNodeType.TypeCase:
            {
                SqlTypeCase c1 = (SqlTypeCase)node;
                if (!CanBeCompared(c1.Discriminator))
                {
                    return(false);
                }
                for (int i = 0, c = c1.Whens.Count; i < c; ++i)
                {
                    if (!CanBeCompared(c1.Whens[i].Match))
                    {
                        return(false);
                    }
                    if (!CanBeCompared(c1.Whens[i].TypeBinding))
                    {
                        return(false);
                    }
                }
                return(true);
            }

            case SqlNodeType.DiscriminatedType:
                return(CanBeCompared(((SqlDiscriminatedType)node).Discriminator));

            case SqlNodeType.JoinedCollection:
            {
                SqlJoinedCollection j1 = (SqlJoinedCollection)node;
                return(CanBeCompared(j1.Count) && CanBeCompared(j1.Expression));
            }

            case SqlNodeType.Member:
                return(CanBeCompared(((SqlMember)node).Expression));

            case SqlNodeType.MethodCall:
            {
                SqlMethodCall mc = (SqlMethodCall)node;
                if (mc.Object != null && !CanBeCompared(mc.Object))
                {
                    return(false);
                }
                for (int i = 0, n = mc.Arguments.Count; i < n; i++)
                {
                    if (!CanBeCompared(mc.Arguments[0]))
                    {
                        return(false);
                    }
                }
                return(true);
            }

            case SqlNodeType.ClientQuery:
                return(true);

            case SqlNodeType.ClientParameter:
            default:
                return(false);
            }
        }
        internal static bool AreSimilar(SqlExpression node1, SqlExpression node2)
        {
            if (node1 == node2)
            {
                return(true);
            }
            if (node1 == null || node2 == null)
            {
                return(false);
            }
            if (node1.NodeType != node2.NodeType ||
                node1.ClrType != node2.ClrType ||
                node1.SqlType != node2.SqlType)
            {
                return(false);
            }
            switch (node1.NodeType)
            {
            case SqlNodeType.New:
            {
                SqlNew new1 = (SqlNew)node1;
                SqlNew new2 = (SqlNew)node2;
                if (new1.Args.Count != new2.Args.Count ||
                    new1.Members.Count != new2.Members.Count)
                {
                    return(false);
                }
                for (int i = 0, n = new1.Args.Count; i < n; i++)
                {
                    if (!AreSimilar(new1.Args[i], new2.Args[i]))
                    {
                        return(false);
                    }
                }
                for (int i = 0, n = new1.Members.Count; i < n; i++)
                {
                    if (!MetaPosition.AreSameMember(new1.Members[i].Member, new2.Members[i].Member) ||
                        !AreSimilar(new1.Members[i].Expression, new2.Members[i].Expression))
                    {
                        return(false);
                    }
                }
                return(true);
            }

            case SqlNodeType.ColumnRef:
            {
                SqlColumnRef cref1 = (SqlColumnRef)node1;
                SqlColumnRef cref2 = (SqlColumnRef)node2;
                return(cref1.Column.Ordinal == cref2.Column.Ordinal);
            }

            case SqlNodeType.Link:
            {
                SqlLink l1 = (SqlLink)node1;
                SqlLink l2 = (SqlLink)node2;
                if (!MetaPosition.AreSameMember(l1.Member.Member, l2.Member.Member))
                {
                    return(false);
                }
                if (l1.KeyExpressions.Count != l2.KeyExpressions.Count)
                {
                    return(false);
                }
                for (int i = 0, c = l1.KeyExpressions.Count; i < c; ++i)
                {
                    if (!AreSimilar(l1.KeyExpressions[i], l2.KeyExpressions[i]))
                    {
                        return(false);
                    }
                }
                return(true);
            }

            case SqlNodeType.Value:
                return(Object.Equals(((SqlValue)node1).Value, ((SqlValue)node2).Value));

            case SqlNodeType.OptionalValue:
            {
                SqlOptionalValue ov1 = (SqlOptionalValue)node1;
                SqlOptionalValue ov2 = (SqlOptionalValue)node2;
                return(AreSimilar(ov1.Value, ov2.Value));
            }

            case SqlNodeType.ValueOf:
            case SqlNodeType.OuterJoinedValue:
                return(AreSimilar(((SqlUnary)node1).Operand, ((SqlUnary)node2).Operand));

            case SqlNodeType.Lift:
                return(AreSimilar(((SqlLift)node1).Expression, ((SqlLift)node2).Expression));

            case SqlNodeType.Grouping:
            {
                SqlGrouping g1 = (SqlGrouping)node1;
                SqlGrouping g2 = (SqlGrouping)node2;
                return(AreSimilar(g1.Key, g2.Key) && AreSimilar(g1.Group, g2.Group));
            }

            case SqlNodeType.ClientArray:
            {
                SqlClientArray a1 = (SqlClientArray)node1;
                SqlClientArray a2 = (SqlClientArray)node2;
                if (a1.Expressions.Count != a2.Expressions.Count)
                {
                    return(false);
                }
                for (int i = 0, n = a1.Expressions.Count; i < n; i++)
                {
                    if (!AreSimilar(a1.Expressions[i], a2.Expressions[i]))
                    {
                        return(false);
                    }
                }
                return(true);
            }

            case SqlNodeType.UserColumn:
                return(((SqlUserColumn)node1).Name == ((SqlUserColumn)node2).Name);

            case SqlNodeType.ClientCase:
            {
                SqlClientCase c1 = (SqlClientCase)node1;
                SqlClientCase c2 = (SqlClientCase)node2;
                if (c1.Whens.Count != c2.Whens.Count)
                {
                    return(false);
                }
                for (int i = 0, n = c1.Whens.Count; i < n; i++)
                {
                    if (!AreSimilar(c1.Whens[i].Match, c2.Whens[i].Match) ||
                        !AreSimilar(c1.Whens[i].Value, c2.Whens[i].Value))
                    {
                        return(false);
                    }
                }
                return(true);
            }

            case SqlNodeType.SearchedCase:
            {
                SqlSearchedCase c1 = (SqlSearchedCase)node1;
                SqlSearchedCase c2 = (SqlSearchedCase)node2;
                if (c1.Whens.Count != c2.Whens.Count)
                {
                    return(false);
                }
                for (int i = 0, n = c1.Whens.Count; i < n; i++)
                {
                    if (!AreSimilar(c1.Whens[i].Match, c2.Whens[i].Match) ||
                        !AreSimilar(c1.Whens[i].Value, c2.Whens[i].Value))
                    {
                        return(false);
                    }
                }
                return(AreSimilar(c1.Else, c2.Else));
            }

            case SqlNodeType.TypeCase:
            {
                SqlTypeCase c1 = (SqlTypeCase)node1;
                SqlTypeCase c2 = (SqlTypeCase)node2;
                if (!AreSimilar(c1.Discriminator, c2.Discriminator))
                {
                    return(false);
                }
                if (c1.Whens.Count != c2.Whens.Count)
                {
                    return(false);
                }
                for (int i = 0, c = c1.Whens.Count; i < c; ++i)
                {
                    if (!AreSimilar(c1.Whens[i].Match, c2.Whens[i].Match))
                    {
                        return(false);
                    }
                    if (!AreSimilar(c1.Whens[i].TypeBinding, c2.Whens[i].TypeBinding))
                    {
                        return(false);
                    }
                }
                return(true);
            }

            case SqlNodeType.DiscriminatedType:
            {
                SqlDiscriminatedType dt1 = (SqlDiscriminatedType)node1;
                SqlDiscriminatedType dt2 = (SqlDiscriminatedType)node2;
                return(AreSimilar(dt1.Discriminator, dt2.Discriminator));
            }

            case SqlNodeType.JoinedCollection:
            {
                SqlJoinedCollection j1 = (SqlJoinedCollection)node1;
                SqlJoinedCollection j2 = (SqlJoinedCollection)node2;
                return(AreSimilar(j1.Count, j2.Count) && AreSimilar(j1.Expression, j2.Expression));
            }

            case SqlNodeType.Member:
            {
                SqlMember m1 = (SqlMember)node1;
                SqlMember m2 = (SqlMember)node2;
                return(m1.Member == m2.Member && AreSimilar(m1.Expression, m2.Expression));
            }

            case SqlNodeType.ClientQuery:
            {
                SqlClientQuery cq1 = (SqlClientQuery)node1;
                SqlClientQuery cq2 = (SqlClientQuery)node2;
                if (cq1.Arguments.Count != cq2.Arguments.Count)
                {
                    return(false);
                }
                for (int i = 0, n = cq1.Arguments.Count; i < n; i++)
                {
                    if (!AreSimilar(cq1.Arguments[i], cq2.Arguments[i]))
                    {
                        return(false);
                    }
                }
                return(true);
            }

            case SqlNodeType.MethodCall:
            {
                SqlMethodCall mc1 = (SqlMethodCall)node1;
                SqlMethodCall mc2 = (SqlMethodCall)node2;
                if (mc1.Method != mc2.Method || !AreSimilar(mc1.Object, mc2.Object))
                {
                    return(false);
                }
                if (mc1.Arguments.Count != mc2.Arguments.Count)
                {
                    return(false);
                }
                for (int i = 0, n = mc1.Arguments.Count; i < n; i++)
                {
                    if (!AreSimilar(mc1.Arguments[i], mc2.Arguments[i]))
                    {
                        return(false);
                    }
                }
                return(true);
            }

            case SqlNodeType.ClientParameter:
            default:
                return(false);
            }
        }
Esempio n. 13
0
 internal override SqlExpression VisitGrouping(SqlGrouping g)
 {
     g.Key   = this.VisitNamedExpression(g.Key, "Key");
     g.Group = this.VisitNamedExpression(g.Group, "Group");
     return(g);
 }