Exemplo n.º 1
0
            /// <summary>
            /// For CASE statements which represent boolean values:
            ///
            ///  CASE XXX
            ///    WHEN AAA THEN true        ===>        (XXX==AAA) || (XXX==BBB)
            ///    WHEN BBB THEN true
            ///    ELSE false
            ///    etc.
            ///  END
            ///
            /// Also,
            ///
            ///  CASE XXX
            ///    WHEN AAA THEN false        ===>        (XXX!=AAA) && (XXX!=BBB)
            ///    WHEN BBB THEN false
            ///    ELSE true
            ///    etc.
            ///  END
            ///
            /// The reduce to a conjunction or disjunction of equality or inequality.
            /// The possibility of NULL in XXX is taken into account.
            /// </summary>
            private SqlExpression TryToWriteAsSimpleBooleanExpression(Type caseType, SqlExpression discriminator, List <SqlWhen> newWhens, bool allValuesLiteral)
            {
                SqlExpression rewrite = null;

                if (caseType == typeof(bool) && allValuesLiteral)
                {
                    bool?holdsNull = SqlExpressionNullability.CanBeNull(discriminator);
                    // The discriminator can't hold a NULL.
                    // In this case, we don't need the special fallback that CASE-ELSE gives.
                    // We can just construct a boolean operation.
                    bool?whenValue = null;
                    for (int i = 0; i < newWhens.Count; ++i)
                    {
                        SqlValue lit   = (SqlValue)newWhens[i].Value; // Must be SqlValue because of allValuesLiteral.
                        bool     value = (bool)lit.Value;             // Must be bool because of caseType==typeof(bool).
                        if (newWhens[i].Match != null)                // Skip the ELSE
                        {
                            if (value)
                            {
                                rewrite = sql.OrAccumulate(rewrite, sql.Binary(SqlNodeType.EQ, discriminator, newWhens[i].Match));
                            }
                            else
                            {
                                rewrite = sql.AndAccumulate(rewrite, sql.Binary(SqlNodeType.NE, discriminator, newWhens[i].Match));
                            }
                        }
                        else
                        {
                            whenValue = value;
                        }
                    }
                    // If it could possibly hold null values.
                    if (holdsNull != false && whenValue != null)
                    {
                        if (whenValue == true)
                        {
                            rewrite = sql.OrAccumulate(rewrite, sql.Unary(SqlNodeType.IsNull, discriminator, discriminator.SourceExpression));
                        }
                        else
                        {
                            rewrite = sql.AndAccumulate(rewrite, sql.Unary(SqlNodeType.IsNotNull, discriminator, discriminator.SourceExpression));
                        }
                    }
                }
                return(rewrite);
            }
Exemplo n.º 2
0
 internal override SqlExpression VisitBinaryOperator(SqlBinary bo)
 {
     base.VisitBinaryOperator(bo);
     if (bo.NodeType.IsComparisonOperator() &&
         bo.Left.ClrType != typeof(bool) && bo.Right.ClrType != typeof(bool))
     {
         // Strip unnecessary CONVERT calls.
         if (bo.Left.NodeType == SqlNodeType.Convert)
         {
             var conv = (SqlUnary)bo.Left;
             if (CanDbConvert(conv.Operand.ClrType, bo.Right.ClrType) &&
                 conv.Operand.SqlType.ComparePrecedenceTo(bo.Right.SqlType) != 1)
             {
                 return(VisitBinaryOperator(new SqlBinary(bo.NodeType, bo.ClrType, bo.SqlType, conv.Operand, bo.Right)));
             }
         }
         if (bo.Right.NodeType == SqlNodeType.Convert)
         {
             var conv = (SqlUnary)bo.Right;
             if (CanDbConvert(conv.Operand.ClrType, bo.Left.ClrType) &&
                 conv.Operand.SqlType.ComparePrecedenceTo(bo.Left.SqlType) != 1)
             {
                 return(VisitBinaryOperator(new SqlBinary(bo.NodeType, bo.ClrType, bo.SqlType, bo.Left, conv.Operand)));
             }
         }
     }
     if (bo.Right != null && bo.NodeType != SqlNodeType.Concat)
     {
         SqlExpression left  = bo.Left;
         SqlExpression right = bo.Right;
         this.CoerceBinaryArgs(ref left, ref right);
         if (bo.Left != left || bo.Right != right)
         {
             bo = sql.Binary(bo.NodeType, left, right);
         }
         bo.SetSqlType(typeProvider.PredictTypeForBinary(bo.NodeType, left.SqlType, right.SqlType));
     }
     if (bo.NodeType.IsComparisonOperator())
     {
         // When comparing a unicode value against a non-unicode column,
         // we want retype the parameter as non-unicode.
         Func <SqlExpression, SqlExpression, bool> needsRetype =
             (expr, val) => (val.NodeType == SqlNodeType.Value || val.NodeType == SqlNodeType.ClientParameter) &&
             !(expr.NodeType == SqlNodeType.Value || expr.NodeType == SqlNodeType.ClientParameter) &&
             val.SqlType.IsUnicodeType && !expr.SqlType.IsUnicodeType;
         SqlSimpleTypeExpression valueToRetype = null;
         if (needsRetype(bo.Left, bo.Right))
         {
             valueToRetype = (SqlSimpleTypeExpression)bo.Right;
         }
         else if (needsRetype(bo.Right, bo.Left))
         {
             valueToRetype = (SqlSimpleTypeExpression)bo.Left;
         }
         if (valueToRetype != null)
         {
             valueToRetype.SetSqlType(valueToRetype.SqlType.GetNonUnicodeEquivalent());
         }
     }
     return(bo);
 }
Exemplo n.º 3
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);
        }
Exemplo n.º 4
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);
        }
Exemplo n.º 5
0
            private SqlBinary MakeCompareTo(SqlExpression left, SqlExpression right, SqlNodeType op, int iValue)
            {
                if (iValue == 0)
                {
                    return(sql.Binary(op, left, right));
                }
                else if (op == SqlNodeType.EQ || op == SqlNodeType.EQ2V)
                {
                    switch (iValue)
                    {
                    case -1:
                        return(sql.Binary(SqlNodeType.LT, left, right));

                    case 1:
                        return(sql.Binary(SqlNodeType.GT, left, right));
                    }
                }
                return(null);
            }