private SqlBinaryExpression CreateJoinPredicate(
            ShapedQueryExpression outer,
            LambdaExpression outerKeySelector,
            ShapedQueryExpression inner,
            LambdaExpression innerKeySelector)
        {
            var outerSelectExpression = (SelectExpression)outer.QueryExpression;
            var innerSelectExpression = (SelectExpression)inner.QueryExpression;

            var outerKey = RemapLambdaBody(outer.ShaperExpression, outerKeySelector);
            var innerKey = RemapLambdaBody(inner.ShaperExpression, innerKeySelector);

            if (outerKey is NewExpression outerNew)
            {
                var innerNew = (NewExpression)innerKey;

                SqlBinaryExpression result = null;
                for (var i = 0; i < outerNew.Arguments.Count; i++)
                {
                    result = result == null
                        ? CreateJoinPredicate(outerSelectExpression, outerNew.Arguments[i], innerSelectExpression, innerNew.Arguments[i])
                        : _sqlExpressionFactory.AndAlso(
                        result,
                        CreateJoinPredicate(outerSelectExpression, outerNew.Arguments[i], innerSelectExpression, innerNew.Arguments[i]));
                }

                return(result);
            }

            return(CreateJoinPredicate(outerSelectExpression, outerKey, innerSelectExpression, innerKey));
        }
Example #2
0
        private SqlExpression VisitJoinPredicate(SqlBinaryExpression predicate)
        {
            var canOptimize = _canOptimize;

            _canOptimize = true;

            if (predicate.OperatorType == ExpressionType.Equal)
            {
                var newLeft  = (SqlExpression)Visit(predicate.Left);
                var newRight = (SqlExpression)Visit(predicate.Right);
                _canOptimize = canOptimize;

                return(predicate.Update(newLeft, newRight));
            }

            if (predicate.OperatorType == ExpressionType.AndAlso)
            {
                var newPredicate = (SqlExpression)VisitSqlBinary(predicate);
                _canOptimize = canOptimize;

                return(newPredicate);
            }

            throw new InvalidOperationException("Unexpected join predicate shape: " + predicate);
        }
Example #3
0
        protected virtual string VisitBinary(SqlBinaryExpression bex)
        {
            string result;

            if (IsSetExpression(bex))
            {
                _isParseringSet = true;
                result          = VisitSet(bex);
                _isParseringSet = false;
                return(result);
            }

            if (!_isParseringSet && IsNullExpression(bex))
            {
                result = VisitIsNull(bex);
            }
            else
            {
                if (bex.Operator == SqlOperator.Coalesce)
                {
                    result = $"{IfNull}({Visit(bex.Left)},{Visit(bex.Right)})";
                }
                else
                {
                    result = $"{Visit(bex.Left)} {OperatorText(bex.Operator)} {Visit(bex.Right)}";
                }
            }

            return(result.Braces(!bex.IsTop));
        }
        private SqlExpression OptimizeCompareTo(
            SqlBinaryExpression sqlBinaryExpression,
            int intValue,
            CaseExpression caseExpression)
        {
            var testLeft     = ((SqlBinaryExpression)caseExpression.WhenClauses[0].Test).Left;
            var testRight    = ((SqlBinaryExpression)caseExpression.WhenClauses[0].Test).Right;
            var operatorType = sqlBinaryExpression.Right is SqlConstantExpression
                ? sqlBinaryExpression.OperatorType
                : sqlBinaryExpression.OperatorType switch
            {
                ExpressionType.GreaterThan => ExpressionType.LessThan,
                ExpressionType.GreaterThanOrEqual => ExpressionType.LessThanOrEqual,
                ExpressionType.LessThan => ExpressionType.GreaterThan,
                ExpressionType.LessThanOrEqual => ExpressionType.GreaterThanOrEqual,
                _ => sqlBinaryExpression.OperatorType
            };

            switch (operatorType)
            {
            // CompareTo(a, b) != 0 -> a != b
            // CompareTo(a, b) != 1 -> a <= b
            // CompareTo(a, b) != -1 -> a >= b
            case ExpressionType.NotEqual:
                return((SqlExpression)Visit(intValue switch
                {
                    0 => _sqlExpressionFactory.NotEqual(testLeft, testRight),
                    1 => _sqlExpressionFactory.LessThanOrEqual(testLeft, testRight),
                    _ => _sqlExpressionFactory.GreaterThanOrEqual(testLeft, testRight),
                }));
 private static bool AttemptDecimalCompare(SqlBinaryExpression sqlBinary) =>
 GetProviderType(sqlBinary.Left) == typeof(decimal) &&
 GetProviderType(sqlBinary.Right) == typeof(decimal) &&
 new[]
 {
     ExpressionType.GreaterThan, ExpressionType.GreaterThanOrEqual, ExpressionType.LessThan, ExpressionType.LessThanOrEqual
 }.Contains(sqlBinary.OperatorType);
Example #6
0
        protected override Expression VisitSqlBinary(SqlBinaryExpression sqlBinaryExpression)
        {
            var parentIsSearchCondition = _isSearchCondition;

            switch (sqlBinaryExpression.OperatorType)
            {
            // Only logical operations need conditions on both sides
            case ExpressionType.AndAlso:
            case ExpressionType.OrElse:
                _isSearchCondition = true;
                break;

            default:
                _isSearchCondition = false;
                break;
            }

            var newLeft  = (SqlExpression)Visit(sqlBinaryExpression.Left);
            var newRight = (SqlExpression)Visit(sqlBinaryExpression.Right);

            _isSearchCondition = parentIsSearchCondition;

            sqlBinaryExpression = sqlBinaryExpression.Update(newLeft, newRight);
            var condition = sqlBinaryExpression.OperatorType == ExpressionType.AndAlso ||
                            sqlBinaryExpression.OperatorType == ExpressionType.OrElse ||
                            sqlBinaryExpression.OperatorType == ExpressionType.Equal ||
                            sqlBinaryExpression.OperatorType == ExpressionType.NotEqual ||
                            sqlBinaryExpression.OperatorType == ExpressionType.GreaterThan ||
                            sqlBinaryExpression.OperatorType == ExpressionType.GreaterThanOrEqual ||
                            sqlBinaryExpression.OperatorType == ExpressionType.LessThan ||
                            sqlBinaryExpression.OperatorType == ExpressionType.LessThanOrEqual;

            return(ApplyConversion(sqlBinaryExpression, condition));
        }
            protected override Expression VisitSqlBinaryExpression(SqlBinaryExpression sqlBinaryExpression)
            {
                var result = base.VisitSqlBinaryExpression(sqlBinaryExpression);

                if (result is SqlBinaryExpression sqlBinaryResult)
                {
                    var leftNullParameter = sqlBinaryResult.Left is SqlParameterExpression leftParameter &&
                                            _parametersValues[leftParameter.Name] == null;

                    var rightNullParameter = sqlBinaryResult.Right is SqlParameterExpression rightParameter &&
                                             _parametersValues[rightParameter.Name] == null;

                    if ((sqlBinaryResult.OperatorType == ExpressionType.Equal || sqlBinaryResult.OperatorType == ExpressionType.NotEqual) &&
                        (leftNullParameter || rightNullParameter))
                    {
                        return(SimplifyNullComparisonExpression(
                                   sqlBinaryResult.OperatorType,
                                   sqlBinaryResult.Left,
                                   sqlBinaryResult.Right,
                                   leftNullParameter,
                                   rightNullParameter,
                                   sqlBinaryResult.TypeMapping));
                    }
                }

                return(result);
            }
        public override ISqlExpression GetExpression(MemberInfo member, params ISqlExpression[] args)
        {
            var arr = new ISqlExpression[args.Length];

            for (var i = 0; i <= args.Length; i++)
            {
                var arg = args[i];
                if (arg.SystemType == typeof(string))
                {
                    arr[i] = arg;
                }
                else
                {
                    var len = arg.SystemType == null || arg.SystemType == typeof(object) ? 100 : SqlDataType.GetMaxDisplaySize(SqlDataType.GetDataType(arg.SystemType).Type.DataType);
                    arr[i] = new SqlFunction(typeof(string), "Convert", new SqlDataType(DataType.VarChar, len), arg);
                }
            }
            if (arr.Length == 1)
            {
                return(arr[0]);
            }
            var expr = new SqlBinaryExpression(typeof(string), arr[0], "+", arr[1]);
            var num2 = arr.Length - 1;

            for (var i = 2; i <= num2; i++)
            {
                expr = new SqlBinaryExpression(typeof(string), expr, "+", arr[i]);
            }
            return(expr);
        }
Example #9
0
        protected override Expression VisitSqlBinary(SqlBinaryExpression sqlBinaryExpression)
        {
            var left  = Visit(sqlBinaryExpression.Left) as SqlExpression;
            var right = Visit(sqlBinaryExpression.Right) as SqlExpression;

            return(sqlBinaryExpression.Update(left, right));
        }
        private SqlExpression ApplyTypeMappingOnSqlBinary(
            SqlBinaryExpression sqlBinaryExpression, RelationalTypeMapping typeMapping)
        {
            var left = sqlBinaryExpression.Left;
            var right = sqlBinaryExpression.Right;

            Type resultType;
            RelationalTypeMapping resultTypeMapping;
            RelationalTypeMapping inferredTypeMapping;
            switch (sqlBinaryExpression.OperatorType)
            {
                case ExpressionType.Equal:
                case ExpressionType.GreaterThan:
                case ExpressionType.GreaterThanOrEqual:
                case ExpressionType.LessThan:
                case ExpressionType.LessThanOrEqual:
                case ExpressionType.NotEqual:
                {
                    inferredTypeMapping = ExpressionExtensions.InferTypeMapping(left, right)
                        ?? _typeMappingSource.FindMapping(left.Type);
                    resultType = typeof(bool);
                    resultTypeMapping = _boolTypeMapping;
                    break;
                }

                case ExpressionType.AndAlso:
                case ExpressionType.OrElse:
                {
                    inferredTypeMapping = _boolTypeMapping;
                    resultType = typeof(bool);
                    resultTypeMapping = _boolTypeMapping;
                    break;
                }

                case ExpressionType.Add:
                case ExpressionType.Subtract:
                case ExpressionType.Multiply:
                case ExpressionType.Divide:
                case ExpressionType.Modulo:
                case ExpressionType.And:
                case ExpressionType.Or:
                {
                    inferredTypeMapping = typeMapping ?? ExpressionExtensions.InferTypeMapping(left, right);
                    resultType = left.Type;
                    resultTypeMapping = inferredTypeMapping;
                    break;
                }

                default:
                    throw new InvalidOperationException("Incorrect operatorType for SqlBinaryExpression");
            }

            return new SqlBinaryExpression(
                sqlBinaryExpression.OperatorType,
                ApplyTypeMapping(left, inferredTypeMapping),
                ApplyTypeMapping(right, inferredTypeMapping),
                resultType,
                resultTypeMapping);
        }
Example #11
0
        protected virtual string VisitIsNull(SqlBinaryExpression bex)
        {
            var activePart = bex.Left is SqlNullExpression ? bex.Right : bex.Left;
            var nullPart   = bex.Left is SqlNullExpression ? bex.Left : bex.Right;
            var ap         = Visit(activePart);

            return(IsNull(ap, null, bex.Operator == SqlOperator.NotEqual).Braces(!bex.IsTop));
        }
        /// <summary>
        ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to
        ///     the same compatibility standards as public APIs. It may be changed or removed without notice in
        ///     any release. You should only use it directly in your code with extreme caution and knowing that
        ///     doing so can result in application failures when updating to a new Entity Framework Core release.
        /// </summary>
        protected override string GenerateOperator(SqlBinaryExpression binaryExpression)
        {
            Check.NotNull(binaryExpression, nameof(binaryExpression));

            return(binaryExpression.OperatorType == ExpressionType.Add &&
                   binaryExpression.Type == typeof(string)
                    ? " || "
                    : base.GenerateOperator(binaryExpression));
        }
 private static bool AttemptDecimalCompare(SqlBinaryExpression sqlBinary)
 => AreOperandsDecimals(sqlBinary) &&
 new[]
 {
     ExpressionType.GreaterThan,
     ExpressionType.GreaterThanOrEqual,
     ExpressionType.LessThan,
     ExpressionType.LessThanOrEqual
 }.Contains(sqlBinary.OperatorType);
Example #14
0
        private static bool IsDateTimeBasedOperation(SqlBinaryExpression binaryExpression)
        {
            if (binaryExpression.TypeMapping != null &&
                (binaryExpression.TypeMapping.StoreType.StartsWith("date") || binaryExpression.TypeMapping.StoreType.StartsWith("time")))
            {
                return(true);
            }

            return(false);
        }
 protected override string GenerateOperator(SqlBinaryExpression e)
 {
     return(e.OperatorType switch
     {
         ExpressionType.Add when e.Type == typeof(string) => " & ",
         ExpressionType.And => " BAND ",
         ExpressionType.Modulo => " MOD ",
         ExpressionType.Or => " BOR ",
         _ => base.GenerateOperator(e),
     });
 protected override Expression VisitExtension(Expression extensionExpression)
 {
     return(extensionExpression switch
     {
         ProjectionExpression projectionExpression => VisitProjectionExpression(projectionExpression),
         ColumnExpression columnExpression => VisitColumn(columnExpression),
         SqlUnaryExpression sqlUnaryExpression => VisitSqlUnaryExpression(sqlUnaryExpression),
         SqlBinaryExpression sqlBinaryExpression => VisitSqlBinaryExpression(sqlBinaryExpression),
         _ => base.VisitExtension(extensionExpression)
     });
Example #17
0
        public void JoinTest()
        {
            var left      = new SqlTableExpression("Tab1", new SqlColumnExpression[] {});
            var right     = new SqlTableExpression("Tab2", new SqlColumnExpression[] { });
            var condition = new SqlBinaryExpression(SqlExpressionType.Equal, constants[0], constants[0]);
            var join      = new SqlJoinExpression(left, right, condition, SqlJoinType.Inner);
            var value     = _generator.GenerateSql(join);

            Assert.Equal("[Tab1] INNER JOIN [Tab2] ON (2 = 2)", value);
        }
Example #18
0
        protected virtual Expression VisitSqlBinaryExpression([NotNull] SqlBinaryExpression sqlBinaryExpression)
        {
            var newLeft  = (SqlExpression)Visit(sqlBinaryExpression.Left);
            var newRight = (SqlExpression)Visit(sqlBinaryExpression.Right);

            return(SimplifyBinaryExpression(
                       sqlBinaryExpression.OperatorType,
                       newLeft,
                       newRight,
                       sqlBinaryExpression.TypeMapping));
        }
        private Expression VisitSqlBinary(SqlBinaryExpression sqlBinaryExpression)
        {
            var newLeft  = (SqlExpression)Visit(sqlBinaryExpression.Left);
            var newRight = (SqlExpression)Visit(sqlBinaryExpression.Right);

            return(SimplifyBinaryExpression(
                       sqlBinaryExpression.OperatorType,
                       newLeft,
                       newRight,
                       sqlBinaryExpression.TypeMapping !));
        }
        protected override Expression VisitSqlBinary(SqlBinaryExpression sqlBinaryExpression)
        {
            if (_binaryFunctions.TryGetValue(sqlBinaryExpression.OperatorType, out var function))
            {
                WriteSqlBinaryFunction(function, sqlBinaryExpression);

                return(sqlBinaryExpression);
            }

            return(base.VisitSqlBinary(sqlBinaryExpression));
        }
        protected override Expression VisitExtension(Expression extensionExpression)
        {
            Check.NotNull(extensionExpression, nameof(extensionExpression));

            return(extensionExpression switch
            {
                SqlUnaryExpression sqlUnaryExpression => VisitSqlUnaryExpression(sqlUnaryExpression),
                SqlBinaryExpression sqlBinaryExpression => VisitSqlBinaryExpression(sqlBinaryExpression),
                SelectExpression selectExpression => VisitSelectExpression(selectExpression),
                _ => base.VisitExtension(extensionExpression),
            });
        protected virtual string VisitSet(SqlBinaryExpression bex)
        {
            if (bex.Operator == SqlOperator.Equal)
            {
                return(ProceedPart(bex));
            }
            var l = ProceedPart(bex.Left);
            var r = ProceedPart(bex.Right);

            return(SetConcat(l, r));
        }
Example #23
0
 protected override string GenerateOperator(SqlBinaryExpression binaryExpression)
 {
     if (binaryExpression.OperatorType == ExpressionType.Add)
     {
         if ((binaryExpression.Left.TypeMapping.StoreTypeNameBase == "STRING" || binaryExpression.Left.TypeMapping.StoreTypeNameBase == "BYTES") &&
             (binaryExpression.Right.TypeMapping.StoreTypeNameBase == "STRING" || binaryExpression.Right.TypeMapping.StoreTypeNameBase == "BYTES"))
         {
             return("||");
         }
     }
     return(base.GenerateOperator(binaryExpression));
 }
        protected override SqlExpression Visit(SqlBinaryExpression expression)
        {
            switch (expression.NodeType)
            {
            case SqlNodeType.And:
            case SqlNodeType.BitwiseAnd:
            case SqlNodeType.Or:
            case SqlNodeType.BitwiseOr:
                return(base.Visit(expression));
            }

            return(expression);
        }
        public void Ctor_WithLeftAndRightOperand_SetsPropertyValues()
        {
            var left = new SqlConstant(5);
            var @operator = SqlBinaryOperator.Equal;
            var right = new SqlConstant(1);
            var expression = new SqlBinaryExpression(left, @operator, right);

            Assert.NotNull(expression.Left);
            Assert.Same(left, expression.Left);
            Assert.Equal(@operator, expression.Operator);
            Assert.NotNull(expression.Right);
            Assert.Same(right, expression.Right);
        }
        protected virtual bool IsSetExpression(SqlBinaryExpression bex)
        {
            if (_isParseringSet)
            {
                return(false);
            }
            if (bex.IsTop)
            {
                return(Precends(SET, bex.Position));
            }

            return(false);
        }
Example #27
0
 private SqlExpression ApplyNewTypeMapping(SqlExpression sqlExpression, RelationalTypeMapping typeMapping)
 {
     return(sqlExpression switch
     {
         MySqlComplexFunctionArgumentExpression e => ApplyTypeMappingOnComplexFunctionArgument(e),
         MySqlCollateExpression e => ApplyTypeMappingOnCollate(e),
         MySqlRegexpExpression e => ApplyTypeMappingOnRegexp(e),
         MySqlBinaryExpression e => ApplyTypeMappingOnMySqlBinary(e, typeMapping),
         MySqlMatchExpression e => ApplyTypeMappingOnMatch(e),
         MySqlJsonArrayIndexExpression e => e.ApplyTypeMapping(typeMapping),
         SqlBinaryExpression e => ApplyTypeMappingOnSqlBinary(e, typeMapping),
         _ => base.ApplyTypeMapping(sqlExpression, typeMapping)
     });
        public void Ctor_WithLeftAndRightOperand_SetsPropertyValues()
        {
            var left       = new SqlConstant(5);
            var @operator  = SqlBinaryOperator.Equal;
            var right      = new SqlConstant(1);
            var expression = new SqlBinaryExpression(left, @operator, right);

            Assert.NotNull(expression.Left);
            Assert.Same(left, expression.Left);
            Assert.Equal(@operator, expression.Operator);
            Assert.NotNull(expression.Right);
            Assert.Same(right, expression.Right);
        }
Example #29
0
        protected override void BuildBinaryExpression(SqlBinaryExpression expr)
        {
            switch (expr.Operation[0])
            {
            case '%': expr = new SqlBinaryExpression(expr.SystemType, expr.Expr1, "MOD", expr.Expr2, Precedence.Additive - 1); break;

            case '&':
            case '|':
            case '^': throw new SqlException("Operator '{0}' is not supported by the {1}.", expr.Operation, GetType().Name);
            }

            base.BuildBinaryExpression(expr);
        }
        protected override Expression VisitSqlBinary(SqlBinaryExpression sqlBinaryExpression)
        {
            var parentOptimize        = _optimize;
            var columnExpression      = sqlBinaryExpression.Left as ColumnExpression ?? sqlBinaryExpression.Right as ColumnExpression;
            var sqlConstantExpression = sqlBinaryExpression.Left as SqlConstantExpression ?? sqlBinaryExpression.Right as SqlConstantExpression;

            // Optimize translation of the following expressions:
            //     context.Table.Where(t => t.BoolColumn == true)
            //         translate to: `boolColumn` = TRUE
            //         instead of:   (`boolColumn` = TRUE) = TRUE
            //     context.Table.Where(t => t.BoolColumn == false)
            //         translate to: `boolColumn` = FALSE
            //         instead of:   (`boolColumn` = TRUE) = FALSE
            //     context.Table.Where(t => t.BoolColumn != true)
            //         translate to: `boolColumn` <> TRUE
            //         instead of:   (`boolColumn` = TRUE) <> TRUE
            //     context.Table.Where(t => t.BoolColumn != false)
            //         translate to: `boolColumn` <> FALSE
            //         instead of:   (`boolColumn` = TRUE) <> FALSE
            if (_optimize &&
                (sqlBinaryExpression.OperatorType == ExpressionType.Equal || sqlBinaryExpression.OperatorType == ExpressionType.NotEqual) &&
                columnExpression != null &&
                sqlConstantExpression != null &&
                columnExpression.TypeMapping is MySqlBoolTypeMapping &&
                columnExpression.Type == typeof(bool) &&
                sqlConstantExpression.TypeMapping is MySqlBoolTypeMapping &&
                sqlConstantExpression.Type == typeof(bool))
            {
                _optimize = false;
            }

            var newLeft  = (SqlExpression)Visit(sqlBinaryExpression.Left);
            var newRight = (SqlExpression)Visit(sqlBinaryExpression.Right);

            _optimize = parentOptimize;

            sqlBinaryExpression = sqlBinaryExpression.Update(newLeft, newRight);

            var condition = sqlBinaryExpression.OperatorType == ExpressionType.AndAlso ||
                            sqlBinaryExpression.OperatorType == ExpressionType.OrElse ||
                            sqlBinaryExpression.OperatorType == ExpressionType.Equal ||
                            sqlBinaryExpression.OperatorType == ExpressionType.NotEqual ||
                            sqlBinaryExpression.OperatorType == ExpressionType.GreaterThan ||
                            sqlBinaryExpression.OperatorType == ExpressionType.GreaterThanOrEqual ||
                            sqlBinaryExpression.OperatorType == ExpressionType.LessThan ||
                            sqlBinaryExpression.OperatorType == ExpressionType.LessThanOrEqual;

            return(ApplyConversion(sqlBinaryExpression, condition));
        }
Example #31
0
 protected override string GenerateOperator(SqlBinaryExpression binaryExpression)
 {
     if (binaryExpression.OperatorType == ExpressionType.Add && binaryExpression.TypeMapping.ClrType == typeof(string))
     {
         return(" || ");
     }
     else if (binaryExpression.OperatorType == ExpressionType.AndAlso || binaryExpression.OperatorType == ExpressionType.And)
     {
         return(" AND ");
     }
     else if (binaryExpression.OperatorType == ExpressionType.OrElse || binaryExpression.OperatorType == ExpressionType.Or)
     {
         return(" OR ");
     }
     return(base.GenerateOperator(binaryExpression));
 }
Example #32
0
 /// <summary>
 /// Visits the specified <see cref="SqlBinaryExpression"/>.
 /// </summary>
 /// <param name="expression">
 /// The expression to visit.
 /// </param>
 public virtual void Visit(SqlBinaryExpression expression)
 {
 }
 public void ExpressionType_ReturnsBinary()
 {
     var expression = new SqlBinaryExpression((SqlConstant)1, SqlBinaryOperator.Equal, (SqlConstant)1);
     Assert.Equal(SqlExpressionType.Binary, expression.ExpressionType);
 }
Example #34
0
        protected override void BuildBinaryExpression(SqlBinaryExpression expr)
        {
            switch (expr.Operation[0])
            {
                case '%': expr = new SqlBinaryExpression(expr.SystemType, expr.Expr1, "MOD", expr.Expr2, Precedence.Additive - 1); break;
                case '&':
                case '|':
                case '^': throw new SqlException("Operator '{0}' is not supported by the {1}.", expr.Operation, GetType().Name);
            }

            base.BuildBinaryExpression(expr);
        }
Example #35
0
 public SqlWhereExpression(SqlBinaryExpression predicate)
 {
     this.predicate = predicate;
 }