Exemplo n.º 1
0
            internal override SqlExpression VisitMultiset(SqlSubSelect sms)
            {
                // allow one big-join per query?
                if ((this.options & Options.EnableBigJoin) != 0 &&
                    !this.hasBigJoin && this.canJoin && this.isTopLevel && this.outerSelect != null &&
                    !MultisetChecker.HasMultiset(sms.Select.Selection) &&
                    BigJoinChecker.CanBigJoin(sms.Select))
                {
                    sms.Select = this.VisitSelect(sms.Select);

                    SqlAlias alias = new SqlAlias(sms.Select);
                    SqlJoin  join  = new SqlJoin(SqlJoinType.OuterApply, this.outerSelect.From, alias, null, sms.SourceExpression);
                    this.outerSelect.From         = join;
                    this.outerSelect.OrderingType = SqlOrderingType.Always;

                    // make joined expression
                    SqlExpression expr = (SqlExpression)SqlDuplicator.Copy(sms.Select.Selection);

                    // make count expression
                    SqlSelect copySelect  = (SqlSelect)SqlDuplicator.Copy(sms.Select);
                    SqlAlias  copyAlias   = new SqlAlias(copySelect);
                    SqlSelect countSelect = new SqlSelect(sql.Unary(SqlNodeType.Count, null, sms.SourceExpression), copyAlias, sms.SourceExpression);
                    countSelect.OrderingType = SqlOrderingType.Never;
                    SqlExpression count = sql.SubSelect(SqlNodeType.ScalarSubSelect, countSelect);

                    // make joined collection
                    SqlJoinedCollection jc = new SqlJoinedCollection(sms.ClrType, sms.SqlType, expr, count, sms.SourceExpression);
                    this.hasBigJoin = true;
                    return(jc);
                }
                else
                {
                    return(QueryExtractor.Extract(sms, this.parentParameters));
                }
            }
Exemplo n.º 2
0
        private List <SqlExpression> GetIdentityExpressions(MetaType type, SqlExpression expr)
        {
            var list  = GetIdentityMembers(type).ToList();
            var list2 = new List <SqlExpression>(list.Count);

            foreach (var item in list)
            {
                list2.Add(sql.Member((SqlExpression)SqlDuplicator.Copy(expr), item));
            }
            return(list2);
        }
Exemplo n.º 3
0
        private List <SqlExpression> GetIdentityExpressions(MetaType type, SqlExpression expr)
        {
            List <MetaDataMember> members = GetIdentityMembers(type).ToList();

            System.Diagnostics.Debug.Assert(members.Count > 0);
            List <SqlExpression> exprs = new List <SqlExpression>(members.Count);

            foreach (MetaDataMember mm in members)
            {
                exprs.Add(sql.Member((SqlExpression)SqlDuplicator.Copy(expr), mm));
            }
            return(exprs);
        }
Exemplo n.º 4
0
        private SqlExpression TranslateEqualsOp(SqlNodeType op, SqlExpression left, SqlExpression right, bool allowExpand)
        {
            switch (op)
            {
            case SqlNodeType.EQ:
            case SqlNodeType.NE:
                return(sql.Binary(op, left, right));

            case SqlNodeType.EQ2V:
                if (SqlExpressionNullability.CanBeNull(left) != false &&
                    SqlExpressionNullability.CanBeNull(right) != false)
                {
                    SqlNodeType eqOp = allowExpand ? SqlNodeType.EQ2V : SqlNodeType.EQ;
                    return
                        (sql.Binary(SqlNodeType.Or,
                                    sql.Binary(SqlNodeType.And,
                                               sql.Unary(SqlNodeType.IsNull, (SqlExpression)SqlDuplicator.Copy(left)),
                                               sql.Unary(SqlNodeType.IsNull, (SqlExpression)SqlDuplicator.Copy(right))
                                               ),
                                    sql.Binary(SqlNodeType.And,
                                               sql.Binary(SqlNodeType.And,
                                                          sql.Unary(SqlNodeType.IsNotNull, (SqlExpression)SqlDuplicator.Copy(left)),
                                                          sql.Unary(SqlNodeType.IsNotNull, (SqlExpression)SqlDuplicator.Copy(right))
                                                          ),
                                               sql.Binary(eqOp, left, right)
                                               )
                                    ));
                }
                else
                {
                    SqlNodeType eqOp = allowExpand ? SqlNodeType.EQ2V : SqlNodeType.EQ;
                    return(sql.Binary(eqOp, left, right));
                }

            case SqlNodeType.NE2V:
                if (SqlExpressionNullability.CanBeNull(left) != false &&
                    SqlExpressionNullability.CanBeNull(right) != false)
                {
                    SqlNodeType eqOp = allowExpand ? SqlNodeType.EQ2V : SqlNodeType.EQ;
                    return
                        (sql.Unary(SqlNodeType.Not,
                                   sql.Binary(SqlNodeType.Or,
                                              sql.Binary(SqlNodeType.And,
                                                         sql.Unary(SqlNodeType.IsNull, (SqlExpression)SqlDuplicator.Copy(left)),
                                                         sql.Unary(SqlNodeType.IsNull, (SqlExpression)SqlDuplicator.Copy(right))
                                                         ),
                                              sql.Binary(SqlNodeType.And,
                                                         sql.Binary(SqlNodeType.And,
                                                                    sql.Unary(SqlNodeType.IsNotNull, (SqlExpression)SqlDuplicator.Copy(left)),
                                                                    sql.Unary(SqlNodeType.IsNotNull, (SqlExpression)SqlDuplicator.Copy(right))
                                                                    ),
                                                         sql.Binary(eqOp, left, right)
                                                         )
                                              )
                                   ));
                }
                else
                {
                    SqlNodeType neOp = allowExpand ? SqlNodeType.NE2V : SqlNodeType.NE;
                    return(sql.Binary(neOp, left, right));
                }

            default:
                throw Error.UnexpectedNode(op);
            }
        }
Exemplo n.º 5
0
            internal override SqlRowNumber VisitRowNumber(SqlRowNumber rowNumber) {
                if (rowNumber.OrderBy.Count > 0) return rowNumber;

                SqlDuplicator dup = new SqlDuplicator(true);
                List<SqlOrderExpression> orderBy = new List<SqlOrderExpression>();
                List<SqlOrderExpression> existingOrders = new List<SqlOrderExpression>();

                if (this.rowNumberOrders != null && this.rowNumberOrders.Count != 0) {
                    existingOrders = new List<SqlOrderExpression>(this.rowNumberOrders);
                }
                else if (this.orders != null) {
                    existingOrders = new List<SqlOrderExpression>(this.orders);
                }

                foreach (SqlOrderExpression expr in existingOrders) {
                    if (!expr.Expression.IsConstantColumn) {
                        orderBy.Add(expr);
                        if (this.rowNumberOrders != null) {
                            this.rowNumberOrders.Remove(expr);
                        }
                        if (this.orders != null) {
                            this.orders.Remove(expr);
                        }
                    }
                }

                rowNumber.OrderBy.Clear();

                if (orderBy.Count == 0) {
                    List<SqlColumn> columns = SqlGatherColumnsProduced.GatherColumns(this.currentSelect.From);

                    foreach (SqlColumn col in columns) {
                        if (col.Expression.SqlType.IsOrderable) {
                            orderBy.Add(new SqlOrderExpression(SqlOrderType.Ascending, new SqlColumnRef(col)));
                        }
                    }

                    if (orderBy.Count == 0) {
                        // insert simple column
                        SqlColumn col =
                            new SqlColumn(
                                "rowNumberOrder",
                                sql.Value(typeof(int), this.typeProvider.From(typeof(int)), 1, false, rowNumber.SourceExpression)
                            );
                        this.PushDown(col);
                        orderBy.Add(new SqlOrderExpression(SqlOrderType.Ascending, new SqlColumnRef(col)));
                    }
                }

                foreach (SqlOrderExpression sox in orderBy) {
                    rowNumber.OrderBy.Add(new SqlOrderExpression(sox.OrderType, (SqlExpression)dup.Duplicate(sox.Expression)));
                }

                return rowNumber;
            }
Exemplo n.º 6
0
            internal override SqlSelect VisitSelect(SqlSelect select) {
                bool saveTop = this.topSelect;
                bool savePK = this.addPrimaryKeys;

                SqlSelect saveSelect = this.currentSelect;
                this.currentSelect = select;

                if (select.OrderingType == SqlOrderingType.Always) {
                    this.addPrimaryKeys = true;
                }

                this.topSelect = false;

                // can't forward ordering information through a group-by
                if (select.GroupBy.Count > 0) {
                    this.Visit(select.From);
                    this.orders = null;
                }
                else {
                    this.Visit(select.From);
                }

                if (select.OrderBy.Count > 0) {
                    this.PrependOrderExpressions(select.OrderBy);
                }

                List<SqlOrderExpression> save = this.orders;
                this.orders = null;
                this.rowNumberOrders = save; // lest orders be null when we need info

                /* do all the lower level stuff */
                select.Where = this.VisitExpression(select.Where);
                for (int i = 0, n = select.GroupBy.Count; i < n; i++) {
                    select.GroupBy[i] = this.VisitExpression(select.GroupBy[i]);
                }
                select.Having = this.VisitExpression(select.Having);
                for (int i = 0, n = select.OrderBy.Count; i < n; i++) {
                    select.OrderBy[i].Expression = this.VisitExpression(select.OrderBy[i].Expression);
                }
                select.Top = this.VisitExpression(select.Top);
                select.Selection = this.VisitExpression(select.Selection);
                select.Row = (SqlRow)this.Visit(select.Row);

                this.topSelect = saveTop;
                this.addPrimaryKeys = savePK;

                this.orders = save;

                // all ordering is blocked for this layer and above
                if (select.OrderingType == SqlOrderingType.Blocked) {
                    this.orders = null;
                }

                // rebuild orderby expressions, provided this select doesn't contain a SqlRowNumber
                // otherwise, replace the orderby with a reference to that column
                select.OrderBy.Clear();
                var rowNumberChecker = new SqlRowNumberChecker();

                if (rowNumberChecker.HasRowNumber(select) && rowNumberChecker.RowNumberColumn != null) {
                    select.Row.Columns.Remove(rowNumberChecker.RowNumberColumn);
                    this.PushDown(rowNumberChecker.RowNumberColumn);
                    this.Orders.Add(new SqlOrderExpression(SqlOrderType.Ascending, new SqlColumnRef(rowNumberChecker.RowNumberColumn)));
                } 
                if ((this.topSelect || select.Top != null) && select.OrderingType != SqlOrderingType.Never && this.orders != null) {
                    this.orders = new HashSet<SqlOrderExpression>(this.orders).ToList();
                    SqlDuplicator dup = new SqlDuplicator(true);
                    foreach (SqlOrderExpression sox in this.orders) {
                        select.OrderBy.Add(new SqlOrderExpression(sox.OrderType, (SqlExpression)dup.Duplicate(sox.Expression)));
                    }
                }
                this.currentSelect = saveSelect;

                return select;
            }
Exemplo n.º 7
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;
        }
Exemplo n.º 8
0
 private SqlExpression MakeCoalesce(SqlExpression left, SqlExpression right, Type resultType) {
     CompensateForLowerPrecedenceOfDateType(ref left, ref right);    // DevDiv 176874
     if (TypeSystem.IsSimpleType(resultType)) {
         return sql.Binary(SqlNodeType.Coalesce, left, right, resultType);
     }
     else {
         List<SqlWhen> whens = new List<SqlWhen>(1);
         whens.Add(new SqlWhen(sql.Unary(SqlNodeType.IsNull, left, left.SourceExpression), right));
         SqlDuplicator dup = new SqlDuplicator(true);
         return sql.SearchedCase(whens.ToArray(), (SqlExpression)dup.Duplicate(left), this.dominatingExpression);
     }
 }
Exemplo n.º 9
0
 private SqlNode VisitParameter(ParameterExpression p) {
     SqlExpression sqlExpr;
     if (this.map.TryGetValue(p, out sqlExpr))
         return sqlExpr;
     Expression expr;
     if (this.exprMap.TryGetValue(p, out expr))
         return this.Visit(expr);
     SqlNode nodeToDup;
     if (this.dupMap.TryGetValue(p, out nodeToDup)) {
         SqlDuplicator duplicator = new SqlDuplicator(true);
         return duplicator.Duplicate(nodeToDup);
     }
     throw Error.ParameterNotInScope(p.Name);
 }
Exemplo n.º 10
0
            internal override SqlRowNumber VisitRowNumber(SqlRowNumber rowNumber)
            {
                if (rowNumber.OrderBy.Count > 0)
                {
                    return(rowNumber);
                }

                SqlDuplicator             dup            = new SqlDuplicator(true);
                List <SqlOrderExpression> orderBy        = new List <SqlOrderExpression>();
                List <SqlOrderExpression> existingOrders = new List <SqlOrderExpression>();

                if (this.rowNumberOrders != null && this.rowNumberOrders.Count != 0)
                {
                    existingOrders = new List <SqlOrderExpression>(this.rowNumberOrders);
                }
                else if (this.orders != null)
                {
                    existingOrders = new List <SqlOrderExpression>(this.orders);
                }

                foreach (SqlOrderExpression expr in existingOrders)
                {
                    if (!expr.Expression.IsConstantColumn)
                    {
                        orderBy.Add(expr);
                        if (this.rowNumberOrders != null)
                        {
                            this.rowNumberOrders.Remove(expr);
                        }
                        if (this.orders != null)
                        {
                            this.orders.Remove(expr);
                        }
                    }
                }

                rowNumber.OrderBy.Clear();

                if (orderBy.Count == 0)
                {
                    List <SqlColumn> columns = SqlGatherColumnsProduced.GatherColumns(this.currentSelect.From);

                    foreach (SqlColumn col in columns)
                    {
                        if (col.Expression.SqlType.IsOrderable)
                        {
                            orderBy.Add(new SqlOrderExpression(SqlOrderType.Ascending, new SqlColumnRef(col)));
                        }
                    }

                    if (orderBy.Count == 0)
                    {
                        // insert simple column
                        SqlColumn col =
                            new SqlColumn(
                                "rowNumberOrder",
                                sql.Value(typeof(int), this.typeProvider.From(typeof(int)), 1, false, rowNumber.SourceExpression)
                                );
                        this.PushDown(col);
                        orderBy.Add(new SqlOrderExpression(SqlOrderType.Ascending, new SqlColumnRef(col)));
                    }
                }

                foreach (SqlOrderExpression sox in orderBy)
                {
                    rowNumber.OrderBy.Add(new SqlOrderExpression(sox.OrderType, (SqlExpression)dup.Duplicate(sox.Expression)));
                }

                return(rowNumber);
            }
Exemplo n.º 11
0
            internal override SqlSelect VisitSelect(SqlSelect select)
            {
                bool saveTop = this.topSelect;
                bool savePK  = this.addPrimaryKeys;

                SqlSelect saveSelect = this.currentSelect;

                this.currentSelect = select;

                if (select.OrderingType == SqlOrderingType.Always)
                {
                    this.addPrimaryKeys = true;
                }

                this.topSelect = false;

                // can't forward ordering information through a group-by
                if (select.GroupBy.Count > 0)
                {
                    this.Visit(select.From);
                    this.orders = null;
                }
                else
                {
                    this.Visit(select.From);
                }

                if (select.OrderBy.Count > 0)
                {
                    this.PrependOrderExpressions(select.OrderBy);
                }

                List <SqlOrderExpression> save = this.orders;

                this.orders          = null;
                this.rowNumberOrders = save; // lest orders be null when we need info

                /* do all the lower level stuff */
                select.Where = this.VisitExpression(select.Where);
                for (int i = 0, n = select.GroupBy.Count; i < n; i++)
                {
                    select.GroupBy[i] = this.VisitExpression(select.GroupBy[i]);
                }
                select.Having = this.VisitExpression(select.Having);
                for (int i = 0, n = select.OrderBy.Count; i < n; i++)
                {
                    select.OrderBy[i].Expression = this.VisitExpression(select.OrderBy[i].Expression);
                }
                select.Top       = this.VisitExpression(select.Top);
                select.Selection = this.VisitExpression(select.Selection);
                select.Row       = (SqlRow)this.Visit(select.Row);

                this.topSelect      = saveTop;
                this.addPrimaryKeys = savePK;

                this.orders = save;

                // all ordering is blocked for this layer and above
                if (select.OrderingType == SqlOrderingType.Blocked)
                {
                    this.orders = null;
                }

                // rebuild orderby expressions, provided this select doesn't contain a SqlRowNumber
                // otherwise, replace the orderby with a reference to that column
                select.OrderBy.Clear();
                var rowNumberChecker = new SqlRowNumberChecker();

                if (rowNumberChecker.HasRowNumber(select) && rowNumberChecker.RowNumberColumn != null)
                {
                    select.Row.Columns.Remove(rowNumberChecker.RowNumberColumn);
                    this.PushDown(rowNumberChecker.RowNumberColumn);
                    this.Orders.Add(new SqlOrderExpression(SqlOrderType.Ascending, new SqlColumnRef(rowNumberChecker.RowNumberColumn)));
                }
                if ((this.topSelect || select.Top != null) && select.OrderingType != SqlOrderingType.Never && this.orders != null)
                {
                    this.orders = new HashSet <SqlOrderExpression>(this.orders).ToList();
                    SqlDuplicator dup = new SqlDuplicator(true);
                    foreach (SqlOrderExpression sox in this.orders)
                    {
                        select.OrderBy.Add(new SqlOrderExpression(sox.OrderType, (SqlExpression)dup.Duplicate(sox.Expression)));
                    }
                }
                this.currentSelect = saveSelect;

                return(select);
            }