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)); }
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); }
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);
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); }
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); }
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);
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) });
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); }
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)); }
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); }
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) });
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)); }
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)); }
/// <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); }
public SqlWhereExpression(SqlBinaryExpression predicate) { this.predicate = predicate; }