internal override SqlExpression VisitSharedExpression(SqlSharedExpression sub)
        {
            SqlSharedExpression n = new SqlSharedExpression(sub.Expression);

            this.nodeMap[sub] = n;
            n.Expression      = this.VisitExpression(sub.Expression);
            return(n);
        }
 internal override SqlExpression VisitSharedExpression(SqlSharedExpression shared) {
     if (!this.isDebugMode) {
         throw Error.InvalidFormatNode("Shared");
     }
     sb.Append("SHARED(");
     this.Visit(shared.Expression);
     sb.Append(")");
     return shared;
 }
Example #3
0
 internal virtual SqlExpression VisitSharedExpression(SqlSharedExpression shared) {
     shared.Expression = this.VisitExpression(shared.Expression);
     return shared;
 }
 internal override SqlExpression VisitSharedExpression(SqlSharedExpression sub) {
     SqlSharedExpression n = new SqlSharedExpression(sub.Expression);
     this.nodeMap[sub] = n;
     n.Expression = this.VisitExpression(sub.Expression);
     return n;
 }
Example #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;
        }
 internal override SqlExpression VisitSharedExpression(SqlSharedExpression shared) {
     shared.Expression = this.VisitExpression(shared.Expression);
     // shared expressions in group-by/select must be only column refs
     if (shared.Expression.NodeType == SqlNodeType.ColumnRef) {
         return shared.Expression;
     }
     else {
         // not simple? better push it down (make a sub-select that projects the relevant bits
         shared.Expression = this.PushDownExpression(shared.Expression);
         return shared.Expression;
     }
 }
 internal override SqlExpression VisitSharedExpression(SqlSharedExpression shared) {
     return this.VisitExpression(shared.Expression);
 }
 internal virtual SqlExpression VisitSharedExpression(SqlSharedExpression shared) {
     shared.Expression = this.VisitExpression(shared.Expression);
     return shared;
 }
 internal SqlSharedExpressionRef(SqlSharedExpression expr)
     : base(SqlNodeType.SharedExpressionRef, expr.ClrType, expr.SourceExpression)
 {
     this.expr = expr;
 }
Example #10
0
 // Methods
 internal override SqlExpression VisitSharedExpression(SqlSharedExpression shared)
 {
     throw Error.UnexpectedSharedExpression();
 }
 internal override SqlExpression VisitSharedExpression(SqlSharedExpression shared) {
     throw Error.UnexpectedSharedExpression();
 }
Example #12
0
 internal override SqlExpression VisitSharedExpression(SqlSharedExpression shared)
 {
     return(this.VisitExpression(shared.Expression));
 }