internal override SqlExpression VisitSharedExpressionRef(SqlSharedExpressionRef sref)
 {
     if (this.ingoreExternalRefs && !this.nodeMap.ContainsKey(sref.SharedExpression))
     {
         return(sref);
     }
     return(new SqlSharedExpressionRef((SqlSharedExpression)this.Visit(sref.SharedExpression)));
 }
Пример #2
0
 internal override SqlExpression VisitSharedExpressionRef(SqlSharedExpressionRef sref) {
     if (!this.isDebugMode) {
         throw Error.InvalidFormatNode("SharedRef");
     }
     sb.Append("SHAREDREF(");
     this.Visit(sref.SharedExpression.Expression);
     sb.Append(")");
     return sref;
 }
Пример #3
0
 internal virtual SqlExpression VisitSharedExpressionRef(SqlSharedExpressionRef sref) {
     return sref;
 }
Пример #4
0
 internal override SqlExpression VisitSharedExpressionRef(SqlSharedExpressionRef sref) {
     if (this.ingoreExternalRefs && !this.nodeMap.ContainsKey(sref.SharedExpression)) {
         return sref;
     }
     return new SqlSharedExpressionRef((SqlSharedExpression)this.Visit(sref.SharedExpression));
 }
Пример #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;
        }
Пример #6
0
 internal override SqlExpression VisitSharedExpressionRef(SqlSharedExpressionRef sref) {
     // always make a copy
     return (SqlExpression) SqlDuplicator.Copy(sref.SharedExpression.Expression);
 }
Пример #7
0
 internal override SqlExpression VisitSharedExpressionRef(SqlSharedExpressionRef sref) {
     return this.VisitExpression(sref.SharedExpression.Expression);
 }
Пример #8
0
 internal virtual SqlExpression VisitSharedExpressionRef(SqlSharedExpressionRef sref) {
     return sref;
 }
Пример #9
0
 internal override SqlExpression VisitSharedExpressionRef(SqlSharedExpressionRef sref)
 {
     throw Error.UnexpectedSharedExpressionReference();
 }
 internal override SqlExpression VisitSharedExpressionRef(SqlSharedExpressionRef sref) {
     throw Error.UnexpectedSharedExpressionReference();
 }
Пример #11
0
 internal override SqlExpression VisitSharedExpressionRef(SqlSharedExpressionRef sref)
 {
     return(this.VisitExpression(sref.SharedExpression.Expression));
 }