Beispiel #1
0
            private SqlJoin GetLeftOuterWithUnreferencedSingletonOnLeft(SqlSource source)
            {
                SqlAlias alias = source as SqlAlias;

                if (alias != null)
                {
                    SqlSelect select = alias.Node as SqlSelect;
                    if (select != null &&
                        select.Where == null &&
                        select.Top == null &&
                        select.GroupBy.Count == 0 &&
                        select.OrderBy.Count == 0)
                    {
                        return(this.GetLeftOuterWithUnreferencedSingletonOnLeft(select.From));
                    }
                }
                SqlJoin join = source as SqlJoin;

                if (join == null || join.JoinType != SqlJoinType.LeftOuter)
                {
                    return(null);
                }
                if (!this.IsSingletonSelect(join.Left))
                {
                    return(null);
                }
                HashSet <SqlAlias> p = SqlGatherProducedAliases.Gather(join.Left);
                HashSet <SqlAlias> c = SqlGatherConsumedAliases.Gather(join.Right);

                if (p.Overlaps(c))
                {
                    return(null);
                }
                return(join);
            }
Beispiel #2
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));
                }
            }
Beispiel #3
0
            internal SqlAlias VisitAliasConsumed(SqlAlias a)
            {
                if (a == null)
                {
                    return(a);
                }

                bool match = false;

                foreach (SqlAlias alias in aliases)
                {
                    if (alias == a)
                    {
                        match = true;
                        break;
                    }
                }

                if (match)
                {
                    this.referencesAnyMatchingAliases = true;
                }

                return(a);
            }
            internal override SqlAlias VisitAlias(SqlAlias a)
            {
                SqlAlias n = new SqlAlias(a.Node);

                this.nodeMap[a] = n;
                n.Node          = this.Visit(a.Node);
                n.Name          = a.Name;
                return(n);
            }
Beispiel #5
0
            internal override SqlAlias VisitAlias(SqlAlias a)
            {
                var sqlAlias = new SqlAlias(a.Node);

                nodeMap[a]    = sqlAlias;
                sqlAlias.Node = Visit(a.Node);
                sqlAlias.Name = a.Name;
                return(sqlAlias);
            }
            internal override SqlAlias VisitAlias(SqlAlias sqlAlias)
            {
                SqlAlias save = this.alias;

                this.alias    = sqlAlias;
                sqlAlias.Node = this.Visit(sqlAlias.Node);
                this.alias    = save;
                return(sqlAlias);
            }
Beispiel #7
0
            private bool HasTrivialSource(SqlSource node)
            {
                SqlAlias alias = node as SqlAlias;

                if (alias == null)
                {
                    return(false);
                }
                return(alias.Node is SqlSelect);
            }
Beispiel #8
0
            internal override SqlExpression VisitAliasRef(SqlAliasRef aref)
            {
                SqlAlias alias = aref.Alias;
                SqlAlias value;

                if (this.removedMap.TryGetValue(alias, out value))
                {
                    throw Error.InvalidReferenceToRemovedAliasDuringDeflation();
                }
                return(aref);
            }
Beispiel #9
0
 internal SqlJoin MakeJoin(SqlJoinType joinType, SqlSource location, SqlAlias alias, SqlExpression condition, Expression source)
 {
     if (joinType == SqlJoinType.LeftOuter)
     {
         var sqlSelect = alias.Node as SqlSelect;
         if (sqlSelect != null && sqlSelect.Selection != null && sqlSelect.Selection.NodeType != SqlNodeType.OptionalValue)
         {
             sqlSelect.Selection = new SqlOptionalValue(new SqlColumn("test", Unary(SqlNodeType.OuterJoinedValue, Value(typeof(int?), TypeProvider.From(typeof(int)), 1, false, source))), sqlSelect.Selection);
         }
     }
     return(new SqlJoin(joinType, location, alias, condition, source));
 }
Beispiel #10
0
        internal SqlSelect BuildDefaultQuery(MetaType rowType, bool allowDeferred, SqlLink link, Expression source)
        {
            if (rowType.HasInheritance && rowType.InheritanceRoot != rowType)
            {
                throw Error.ArgumentWrongValue("rowType");
            }
            var sqlTable  = sql.Table(rowType.Table, rowType, source);
            var sqlAlias  = new SqlAlias(sqlTable);
            var item      = new SqlAliasRef(sqlAlias);
            var selection = BuildProjection(item, sqlTable.RowType, allowDeferred, link, source);

            return(new SqlSelect(selection, sqlAlias, source));
        }
Beispiel #11
0
            private SqlUnion GetUnion(SqlSource source)
            {
                SqlAlias alias = source as SqlAlias;

                if (alias != null)
                {
                    SqlUnion union = alias.Node as SqlUnion;
                    if (union != null)
                    {
                        return(union);
                    }
                }
                return(null);
            }
            internal override SqlExpression VisitScalarSubSelect(SqlSubSelect ss)
            {
                SqlSelect innerSelect = this.VisitSelect(ss.Select);

                if (!this.aggregateChecker.HasAggregates(innerSelect))
                {
                    innerSelect.Top = this.sql.ValueFromObject(1, ss.SourceExpression);
                }
                innerSelect.OrderingType = SqlOrderingType.Blocked;
                SqlAlias alias = new SqlAlias(innerSelect);

                this.currentSelect.From = new SqlJoin(SqlJoinType.OuterApply, this.currentSelect.From, alias, null, ss.SourceExpression);
                return(new SqlColumnRef(innerSelect.Row.Columns[0]));
            }
Beispiel #13
0
            internal override SqlAlias VisitAlias(SqlAlias a)
            {
                SqlTable tab = a.Node as SqlTable;
                SqlTableValuedFunctionCall tvf = a.Node as SqlTableValuedFunctionCall;

                if (this.addPrimaryKeys && (tab != null || tvf != null))
                {
                    List <SqlOrderExpression> list = new List <SqlOrderExpression>();

                    bool     isTable = tab != null;
                    MetaType rowType = isTable ? tab.RowType : tvf.RowType;
                    foreach (MetaDataMember mm in rowType.IdentityMembers)
                    {
                        string           name = mm.MappedName;
                        SqlColumn        col;
                        Expression       sourceExpression;
                        List <SqlColumn> columns;

                        if (isTable)
                        {
                            col = tab.Find(name);
                            sourceExpression = tab.SourceExpression;
                            columns          = tab.Columns;
                        }
                        else
                        {
                            col = tvf.Find(name);
                            sourceExpression = tvf.SourceExpression;
                            columns          = tvf.Columns;
                        }

                        if (col == null)
                        {
                            col       = new SqlColumn(mm.MemberAccessor.Type, typeProvider.From(mm.MemberAccessor.Type), name, mm, null, sourceExpression);
                            col.Alias = a;
                            columns.Add(col);
                        }
                        list.Add(new SqlOrderExpression(SqlOrderType.Ascending, new SqlColumnRef(col)));
                    }

                    this.PrependOrderExpressions(list);

                    return(a);
                }
                else
                {
                    return(base.VisitAlias(a));
                }
            }
Beispiel #14
0
        internal SqlSelect BuildDefaultQuery(MetaType rowType, bool allowDeferred, SqlLink link, Expression source)
        {
            System.Diagnostics.Debug.Assert(rowType != null && rowType.Table != null);
            if (rowType.HasInheritance && rowType.InheritanceRoot != rowType)
            {
                // RowType is expected to be an inheritance root.
                throw Error.ArgumentWrongValue("rowType");
            }
            SqlTable    table         = sql.Table(rowType.Table, rowType, source);
            SqlAlias    tableAlias    = new SqlAlias(table);
            SqlAliasRef tableAliasRef = new SqlAliasRef(tableAlias);

            SqlExpression projection = this.BuildProjection(tableAliasRef, table.RowType, allowDeferred, link, source);

            return(new SqlSelect(projection, tableAlias, source));
        }
Beispiel #15
0
            internal override SqlSource VisitSource(SqlSource node)
            {
                node = (SqlSource)this.Visit(node);
                SqlAlias alias = node as SqlAlias;

                if (alias != null)
                {
                    SqlSelect sel = alias.Node as SqlSelect;
                    if (sel != null && this.IsTrivialSelect(sel))
                    {
                        this.removedMap[alias] = alias;
                        node = sel.From;
                    }
                }
                return(node);
            }
Beispiel #16
0
            private bool IsSingletonSelect(SqlSource source)
            {
                SqlAlias alias = source as SqlAlias;

                if (alias == null)
                {
                    return(false);
                }
                SqlSelect select = alias.Node as SqlSelect;

                if (select == null)
                {
                    return(false);
                }
                if (select.From != null)
                {
                    return(false);
                }
                return(true);
            }
Beispiel #17
0
            private void GetSelectionsBeforeJoin(SqlSource source, List <List <SqlColumn> > selections)
            {
                SqlJoin join = source as SqlJoin;

                if (join != null)
                {
                    return;
                }
                SqlAlias alias = source as SqlAlias;

                if (alias != null)
                {
                    SqlSelect select = alias.Node as SqlSelect;
                    if (select != null)
                    {
                        this.GetSelectionsBeforeJoin(select.From, selections);
                        selections.Add(select.Row.Columns);
                    }
                }
            }
Beispiel #18
0
            private bool HasEmptySource(SqlSource node)
            {
                SqlAlias alias = node as SqlAlias;

                if (alias == null)
                {
                    return(false);
                }
                SqlSelect sel = alias.Node as SqlSelect;

                if (sel == null)
                {
                    return(false);
                }
                return(sel.Row.Columns.Count == 0 &&
                       sel.From == null &&
                       sel.Where == null &&
                       sel.GroupBy.Count == 0 &&
                       sel.Having == null &&
                       sel.OrderBy.Count == 0);
            }
 internal SqlJoin MakeJoin(SqlJoinType joinType, SqlSource location, SqlAlias alias, SqlExpression condition, Expression source)
 {
     // if the new item is on the right side of some outer join then fixup the projection to reflect that it can possibly be null
     if (joinType == SqlJoinType.LeftOuter)
     {
         SqlSelect sel = alias.Node as SqlSelect;
         if (sel != null && sel.Selection != null && sel.Selection.NodeType != SqlNodeType.OptionalValue)
         {
             // replace selection w/ optional + outer-joined-value
             sel.Selection = new SqlOptionalValue(
                 new SqlColumn(
                     "test",
                     this.Unary(SqlNodeType.OuterJoinedValue,
                                this.Value(typeof(int?), this.typeProvider.From(typeof(int)), 1, false, source))
                     ),
                 sel.Selection
                 );
         }
     }
     return(new SqlJoin(joinType, location, alias, condition, source));
 }
Beispiel #20
0
            internal override SqlSource VisitJoin(SqlJoin join)
            {
                base.VisitJoin(join);
                switch (join.JoinType)
                {
                case SqlJoinType.Cross:
                case SqlJoinType.Inner:
                    // reducing either side would effect cardinality of results
                    break;

                case SqlJoinType.LeftOuter:
                case SqlJoinType.CrossApply:
                case SqlJoinType.OuterApply:
                    // may reduce to left if no references to the right
                    if (this.HasEmptySource(join.Right))
                    {
                        SqlAlias a = (SqlAlias)join.Right;
                        this.removedMap[a] = a;
                        return(join.Left);
                    }
                    break;
                }
                return(join);
            }
Beispiel #21
0
        internal SqlExpression TranslateEquals(SqlBinary expr)
        {
            var sqlExpression  = expr.Left;
            var sqlExpression2 = expr.Right;

            if (sqlExpression2.NodeType == SqlNodeType.Element)
            {
                var sqlSubSelect = (SqlSubSelect)sqlExpression2;
                var sqlAlias     = new SqlAlias(sqlSubSelect.Select);
                var sqlAliasRef  = new SqlAliasRef(sqlAlias);
                var sqlSelect    = new SqlSelect(sqlAliasRef, sqlAlias, expr.SourceExpression)
                {
                    Where = sql.Binary(expr.NodeType, sql.DoNotVisitExpression(sqlExpression), sqlAliasRef)
                };
                return(sql.SubSelect(SqlNodeType.Exists, sqlSelect));
            }
            if (sqlExpression.NodeType == SqlNodeType.Element)
            {
                var sqlSubSelect2 = (SqlSubSelect)sqlExpression;
                var sqlAlias2     = new SqlAlias(sqlSubSelect2.Select);
                var sqlAliasRef2  = new SqlAliasRef(sqlAlias2);
                var sqlSelect2    = new SqlSelect(sqlAliasRef2, sqlAlias2, expr.SourceExpression)
                {
                    Where = sql.Binary(expr.NodeType, sql.DoNotVisitExpression(sqlExpression2), sqlAliasRef2)
                };
                return(sql.SubSelect(SqlNodeType.Exists, sqlSelect2));
            }
            MetaType sourceMetaType  = TypeSource.GetSourceMetaType(sqlExpression, services.Model);
            MetaType sourceMetaType2 = TypeSource.GetSourceMetaType(sqlExpression2, services.Model);

            if (sqlExpression.NodeType == SqlNodeType.TypeCase)
            {
                sqlExpression = BestIdentityNode((SqlTypeCase)sqlExpression);
            }
            if (sqlExpression2.NodeType == SqlNodeType.TypeCase)
            {
                sqlExpression2 = BestIdentityNode((SqlTypeCase)sqlExpression2);
            }
            if (sourceMetaType.IsEntity && sourceMetaType2.IsEntity && sourceMetaType.Table != sourceMetaType2.Table)
            {
                throw Error.CannotCompareItemsAssociatedWithDifferentTable();
            }
            if (!sourceMetaType.IsEntity && !sourceMetaType2.IsEntity && (sqlExpression.NodeType != SqlNodeType.New || sqlExpression.SqlType.CanBeColumn) && (sqlExpression2.NodeType != SqlNodeType.New || sqlExpression2.SqlType.CanBeColumn))
            {
                if (expr.NodeType == SqlNodeType.EQ2V || expr.NodeType == SqlNodeType.NE2V)
                {
                    return(TranslateEqualsOp(expr.NodeType, sql.DoNotVisitExpression(expr.Left), sql.DoNotVisitExpression(expr.Right), false));
                }
                return(expr);
            }
            if (sourceMetaType != sourceMetaType2 && sourceMetaType.InheritanceRoot != sourceMetaType2.InheritanceRoot)
            {
                return(sql.Binary(SqlNodeType.EQ, sql.ValueFromObject(0, expr.SourceExpression), sql.ValueFromObject(1, expr.SourceExpression)));
            }
            var           sqlLink        = sqlExpression as SqlLink;
            var           list           = (sqlLink == null || !sqlLink.Member.IsAssociation || !sqlLink.Member.Association.IsForeignKey) ? GetIdentityExpressions(sourceMetaType, sql.DoNotVisitExpression(sqlExpression)) : sqlLink.KeyExpressions;
            var           sqlLink2       = sqlExpression2 as SqlLink;
            var           list2          = (sqlLink2 == null || !sqlLink2.Member.IsAssociation || !sqlLink2.Member.Association.IsForeignKey) ? GetIdentityExpressions(sourceMetaType2, sql.DoNotVisitExpression(sqlExpression2)) : sqlLink2.KeyExpressions;
            SqlExpression sqlExpression3 = null;
            var           op             = (expr.NodeType == SqlNodeType.EQ2V || expr.NodeType == SqlNodeType.NE2V) ? SqlNodeType.EQ2V : SqlNodeType.EQ;
            var           i = 0;

            for (var count = list.Count; i < count; i++)
            {
                var sqlExpression4 = TranslateEqualsOp(op, list[i], list2[i], !sourceMetaType.IsEntity);
                sqlExpression3 = ((sqlExpression3 != null) ? sql.Binary(SqlNodeType.And, sqlExpression3, sqlExpression4) : sqlExpression4);
            }
            if (expr.NodeType == SqlNodeType.NE || expr.NodeType == SqlNodeType.NE2V)
            {
                sqlExpression3 = sql.Unary(SqlNodeType.Not, sqlExpression3, sqlExpression3.SourceExpression);
            }
            return(sqlExpression3);
        }
Beispiel #22
0
        internal SqlExpression TranslateEquals(SqlBinary expr)
        {
            System.Diagnostics.Debug.Assert(
                expr.NodeType == SqlNodeType.EQ || expr.NodeType == SqlNodeType.NE ||
                expr.NodeType == SqlNodeType.EQ2V || expr.NodeType == SqlNodeType.NE2V);
            SqlExpression eLeft  = expr.Left;
            SqlExpression eRight = expr.Right;

            if (eRight.NodeType == SqlNodeType.Element)
            {
                SqlSubSelect sub    = (SqlSubSelect)eRight;
                SqlAlias     alias  = new SqlAlias(sub.Select);
                SqlAliasRef  aref   = new SqlAliasRef(alias);
                SqlSelect    select = new SqlSelect(aref, alias, expr.SourceExpression);
                select.Where = sql.Binary(expr.NodeType, sql.DoNotVisitExpression(eLeft), aref);
                return(sql.SubSelect(SqlNodeType.Exists, select));
            }
            else if (eLeft.NodeType == SqlNodeType.Element)
            {
                SqlSubSelect sub    = (SqlSubSelect)eLeft;
                SqlAlias     alias  = new SqlAlias(sub.Select);
                SqlAliasRef  aref   = new SqlAliasRef(alias);
                SqlSelect    select = new SqlSelect(aref, alias, expr.SourceExpression);
                select.Where = sql.Binary(expr.NodeType, sql.DoNotVisitExpression(eRight), aref);
                return(sql.SubSelect(SqlNodeType.Exists, select));
            }

            MetaType mtLeft  = TypeSource.GetSourceMetaType(eLeft, this.services.Model);
            MetaType mtRight = TypeSource.GetSourceMetaType(eRight, this.services.Model);

            if (eLeft.NodeType == SqlNodeType.TypeCase)
            {
                eLeft = BestIdentityNode((SqlTypeCase)eLeft);
            }
            if (eRight.NodeType == SqlNodeType.TypeCase)
            {
                eRight = BestIdentityNode((SqlTypeCase)eRight);
            }

            if (mtLeft.IsEntity && mtRight.IsEntity && mtLeft.Table != mtRight.Table)
            {
                throw Error.CannotCompareItemsAssociatedWithDifferentTable();
            }

            // do simple or no translation for non-structural types
            if (!mtLeft.IsEntity && !mtRight.IsEntity &&
                (eLeft.NodeType != SqlNodeType.New || eLeft.SqlType.CanBeColumn) &&
                (eRight.NodeType != SqlNodeType.New || eRight.SqlType.CanBeColumn))
            {
                if (expr.NodeType == SqlNodeType.EQ2V || expr.NodeType == SqlNodeType.NE2V)
                {
                    return(this.TranslateEqualsOp(expr.NodeType, sql.DoNotVisitExpression(expr.Left), sql.DoNotVisitExpression(expr.Right), false));
                }
                return(expr);
            }

            // If the two types are not comparable, we return the predicate "1=0".
            if ((mtLeft != mtRight) && (mtLeft.InheritanceRoot != mtRight.InheritanceRoot))
            {
                return(sql.Binary(SqlNodeType.EQ, sql.ValueFromObject(0, expr.SourceExpression), sql.ValueFromObject(1, expr.SourceExpression)));
            }

            List <SqlExpression> exprs1;
            List <SqlExpression> exprs2;

            SqlLink link1 = eLeft as SqlLink;

            if (link1 != null && link1.Member.IsAssociation && link1.Member.Association.IsForeignKey)
            {
                exprs1 = link1.KeyExpressions;
            }
            else
            {
                exprs1 = this.GetIdentityExpressions(mtLeft, sql.DoNotVisitExpression(eLeft));
            }

            SqlLink link2 = eRight as SqlLink;

            if (link2 != null && link2.Member.IsAssociation && link2.Member.Association.IsForeignKey)
            {
                exprs2 = link2.KeyExpressions;
            }
            else
            {
                exprs2 = this.GetIdentityExpressions(mtRight, sql.DoNotVisitExpression(eRight));
            }

            System.Diagnostics.Debug.Assert(exprs1.Count > 0);
            System.Diagnostics.Debug.Assert(exprs2.Count > 0);
            System.Diagnostics.Debug.Assert(exprs1.Count == exprs2.Count);

            SqlExpression exp    = null;
            SqlNodeType   eqKind = (expr.NodeType == SqlNodeType.EQ2V || expr.NodeType == SqlNodeType.NE2V) ? SqlNodeType.EQ2V : SqlNodeType.EQ;

            for (int i = 0, n = exprs1.Count; i < n; i++)
            {
                SqlExpression eq = this.TranslateEqualsOp(eqKind, exprs1[i], exprs2[i], !mtLeft.IsEntity);
                if (exp == null)
                {
                    exp = eq;
                }
                else
                {
                    exp = sql.Binary(SqlNodeType.And, exp, eq);
                }
            }
            if (expr.NodeType == SqlNodeType.NE || expr.NodeType == SqlNodeType.NE2V)
            {
                exp = sql.Unary(SqlNodeType.Not, exp, exp.SourceExpression);
            }
            return(exp);
        }
 internal override SqlAlias VisitAlias(SqlAlias a)
 {
     Produced.Add(a);
     return(base.VisitAlias(a));
 }
 internal void VisitAliasConsumed(SqlAlias a)
 {
     Consumed.Add(a);
 }
Beispiel #25
0
 internal virtual SqlAlias VisitAlias(SqlAlias a)
 {
     a.Node = this.Visit(a.Node);
     return(a);
 }