private HqlBooleanExpression VisitNew(NewExpression innerKeySelector, NewExpression outerKeySelector) { if (innerKeySelector.Arguments.Count != outerKeySelector.Arguments.Count) { throw new NotSupportedException(); } HqlBooleanExpression hql = GenerateEqualityNode(innerKeySelector, outerKeySelector, 0); for (int i = 1; i < innerKeySelector.Arguments.Count; i++) { hql = _hqlTreeBuilder.BooleanAnd(hql, GenerateEqualityNode(innerKeySelector, outerKeySelector, i)); } return(hql); }
protected HqlTreeNode VisitBinaryExpression(BinaryExpression expression) { if (expression.NodeType == ExpressionType.Equal) { return(TranslateEqualityComparison(expression)); } if (expression.NodeType == ExpressionType.NotEqual) { return(TranslateInequalityComparison(expression)); } var lhs = VisitExpression(expression.Left).AsExpression(); var rhs = VisitExpression(expression.Right).AsExpression(); switch (expression.NodeType) { case ExpressionType.And: return(_hqlTreeBuilder.BitwiseAnd(lhs, rhs)); case ExpressionType.AndAlso: return(_hqlTreeBuilder.BooleanAnd(lhs.ToBooleanExpression(), rhs.ToBooleanExpression())); case ExpressionType.Or: return(_hqlTreeBuilder.BitwiseOr(lhs, rhs)); case ExpressionType.OrElse: return(_hqlTreeBuilder.BooleanOr(lhs.ToBooleanExpression(), rhs.ToBooleanExpression())); case ExpressionType.Add: if (expression.Left.Type == typeof(string) && expression.Right.Type == typeof(string)) { return(_hqlTreeBuilder.MethodCall("concat", lhs, rhs)); } return(_hqlTreeBuilder.Add(lhs, rhs)); case ExpressionType.Subtract: return(_hqlTreeBuilder.Subtract(lhs, rhs)); case ExpressionType.Multiply: return(_hqlTreeBuilder.Multiply(lhs, rhs)); case ExpressionType.Divide: return(_hqlTreeBuilder.Divide(lhs, rhs)); case ExpressionType.Modulo: return(_hqlTreeBuilder.MethodCall("mod", lhs, rhs)); case ExpressionType.LessThan: return(_hqlTreeBuilder.LessThan(lhs, rhs)); case ExpressionType.LessThanOrEqual: return(_hqlTreeBuilder.LessThanOrEqual(lhs, rhs)); case ExpressionType.GreaterThan: return(_hqlTreeBuilder.GreaterThan(lhs, rhs)); case ExpressionType.GreaterThanOrEqual: return(_hqlTreeBuilder.GreaterThanOrEqual(lhs, rhs)); case ExpressionType.Coalesce: return(_hqlTreeBuilder.Coalesce(lhs.ToArithmeticExpression(), rhs.ToArithmeticExpression())); } throw new InvalidOperationException(); }
protected HqlTreeNode VisitBinaryExpression(BinaryExpression expression) { var lhs = VisitExpression(expression.Left).AsExpression(); var rhs = VisitExpression(expression.Right).AsExpression(); switch (expression.NodeType) { case ExpressionType.Equal: // Need to check for boolean equality if (lhs is HqlBooleanExpression || rhs is HqlBooleanExpression) { lhs = _hqlTreeBuilder.Case( new [] { _hqlTreeBuilder.When(lhs, _hqlTreeBuilder.Constant(1)) }, _hqlTreeBuilder.Constant(0)); rhs = _hqlTreeBuilder.Case( new [] { _hqlTreeBuilder.When(rhs, _hqlTreeBuilder.Constant(1)) }, _hqlTreeBuilder.Constant(0)); return(_hqlTreeBuilder.Equality(lhs, rhs)); } // Also check for nullability if (expression.Left.Type.IsNullableOrReference() || expression.Right.Type.IsNullableOrReference()) { // TODO - yuck. This clone is needed because the AST tree nodes are not immutable, // and sharing nodes between multiple branches will cause issues in the hqlSqlWalker phase - // a node, x, gets visited during the walk and updated to refer to a real property. Later in // the walk, x get revisited (since we copied it here), but now the type doesn't match what // the parser expects. So we can't share. Implementing Clone() on HqlTreeNode would be better // that doing a full visit of the Expression tree. Allowing shared nodes in the AST would be better // still, but might be more work var lhs2 = VisitExpression(expression.Left).AsExpression(); var rhs2 = VisitExpression(expression.Right).AsExpression(); return(_hqlTreeBuilder.BooleanOr( _hqlTreeBuilder.BooleanAnd( _hqlTreeBuilder.IsNull(lhs), _hqlTreeBuilder.IsNull(rhs)), _hqlTreeBuilder.Equality(lhs2, rhs2) )); } return(_hqlTreeBuilder.Equality(lhs, rhs)); case ExpressionType.NotEqual: // Need to check for boolean in-equality if (lhs is HqlBooleanExpression || rhs is HqlBooleanExpression) { lhs = _hqlTreeBuilder.Case( new [] { _hqlTreeBuilder.When(lhs, _hqlTreeBuilder.Constant(1)) }, _hqlTreeBuilder.Constant(0)); rhs = _hqlTreeBuilder.Case( new [] { _hqlTreeBuilder.When(rhs, _hqlTreeBuilder.Constant(1)) }, _hqlTreeBuilder.Constant(0)); return(_hqlTreeBuilder.Inequality(lhs, rhs)); } // Also check for nullability if (expression.Left.Type.IsNullableOrReference() || expression.Right.Type.IsNullableOrReference()) { var lhs2 = VisitExpression(expression.Left).AsExpression(); var rhs2 = VisitExpression(expression.Right).AsExpression(); var lhs3 = VisitExpression(expression.Left).AsExpression(); var rhs3 = VisitExpression(expression.Right).AsExpression(); return (_hqlTreeBuilder.BooleanOr( _hqlTreeBuilder.BooleanOr( _hqlTreeBuilder.BooleanAnd( _hqlTreeBuilder.IsNull(lhs), _hqlTreeBuilder.IsNotNull(rhs)), _hqlTreeBuilder.BooleanAnd( _hqlTreeBuilder.IsNotNull(lhs2), _hqlTreeBuilder.IsNull(rhs2)) ), _hqlTreeBuilder.Inequality(lhs3, rhs3))); } return(_hqlTreeBuilder.Inequality(lhs, rhs)); case ExpressionType.And: return(_hqlTreeBuilder.BitwiseAnd(lhs, rhs)); case ExpressionType.AndAlso: return(_hqlTreeBuilder.BooleanAnd(lhs.AsBooleanExpression(), rhs.AsBooleanExpression())); case ExpressionType.Or: return(_hqlTreeBuilder.BitwiseOr(lhs, rhs)); case ExpressionType.OrElse: return(_hqlTreeBuilder.BooleanOr(lhs.AsBooleanExpression(), rhs.AsBooleanExpression())); case ExpressionType.Add: return(_hqlTreeBuilder.Add(lhs, rhs)); case ExpressionType.Subtract: return(_hqlTreeBuilder.Subtract(lhs, rhs)); case ExpressionType.Multiply: return(_hqlTreeBuilder.Multiply(lhs, rhs)); case ExpressionType.Divide: return(_hqlTreeBuilder.Divide(lhs, rhs)); case ExpressionType.LessThan: return(_hqlTreeBuilder.LessThan(lhs, rhs)); case ExpressionType.LessThanOrEqual: return(_hqlTreeBuilder.LessThanOrEqual(lhs, rhs)); case ExpressionType.GreaterThan: return(_hqlTreeBuilder.GreaterThan(lhs, rhs)); case ExpressionType.GreaterThanOrEqual: return(_hqlTreeBuilder.GreaterThanOrEqual(lhs, rhs)); } throw new InvalidOperationException(); }
protected HqlTreeNode VisitBinaryExpression(BinaryExpression expression) { var lhs = VisitExpression(expression.Left).AsExpression(); var rhs = VisitExpression(expression.Right).AsExpression(); switch (expression.NodeType) { case ExpressionType.Equal: // Need to check for boolean equality if (lhs is HqlBooleanExpression || rhs is HqlBooleanExpression) { return(ResolveBooleanEquality(expression, lhs, rhs, (l, r) => _hqlTreeBuilder.Equality(l, r))); } // Check for nulls on left or right. if (expression.Right is ConstantExpression && expression.Right.Type.IsNullableOrReference() && ((ConstantExpression)expression.Right).Value == null) { return(_hqlTreeBuilder.IsNull(lhs)); } if (expression.Left is ConstantExpression && expression.Left.Type.IsNullableOrReference() && ((ConstantExpression)expression.Left).Value == null) { return(_hqlTreeBuilder.IsNull(rhs)); } // Nothing was null, use standard equality. return(_hqlTreeBuilder.Equality(lhs, rhs)); case ExpressionType.NotEqual: // Need to check for boolean in-equality if (lhs is HqlBooleanExpression || rhs is HqlBooleanExpression) { return(ResolveBooleanEquality(expression, lhs, rhs, (l, r) => _hqlTreeBuilder.Inequality(l, r))); } // Check for nulls on left or right. if (expression.Right is ConstantExpression && expression.Right.Type.IsNullableOrReference() && ((ConstantExpression)expression.Right).Value == null) { return(_hqlTreeBuilder.IsNotNull(lhs)); } if (expression.Left is ConstantExpression && expression.Left.Type.IsNullableOrReference() && ((ConstantExpression)expression.Left).Value == null) { return(_hqlTreeBuilder.IsNotNull(rhs)); } // Nothing was null, use standard inequality. return(_hqlTreeBuilder.Inequality(lhs, rhs)); case ExpressionType.And: return(_hqlTreeBuilder.BitwiseAnd(lhs, rhs)); case ExpressionType.AndAlso: return(_hqlTreeBuilder.BooleanAnd(lhs.AsBooleanExpression(), rhs.AsBooleanExpression())); case ExpressionType.Or: return(_hqlTreeBuilder.BitwiseOr(lhs, rhs)); case ExpressionType.OrElse: return(_hqlTreeBuilder.BooleanOr(lhs.AsBooleanExpression(), rhs.AsBooleanExpression())); case ExpressionType.Add: if (expression.Left.Type == typeof(string) && expression.Right.Type == typeof(string)) { return(_hqlTreeBuilder.MethodCall("concat", lhs, rhs)); } return(_hqlTreeBuilder.Add(lhs, rhs)); case ExpressionType.Subtract: return(_hqlTreeBuilder.Subtract(lhs, rhs)); case ExpressionType.Multiply: return(_hqlTreeBuilder.Multiply(lhs, rhs)); case ExpressionType.Divide: return(_hqlTreeBuilder.Divide(lhs, rhs)); case ExpressionType.Modulo: return(_hqlTreeBuilder.MethodCall("mod", lhs, rhs)); case ExpressionType.LessThan: return(_hqlTreeBuilder.LessThan(lhs, rhs)); case ExpressionType.LessThanOrEqual: return(_hqlTreeBuilder.LessThanOrEqual(lhs, rhs)); case ExpressionType.GreaterThan: return(_hqlTreeBuilder.GreaterThan(lhs, rhs)); case ExpressionType.GreaterThanOrEqual: return(_hqlTreeBuilder.GreaterThanOrEqual(lhs, rhs)); case ExpressionType.Coalesce: return(_hqlTreeBuilder.Coalesce(lhs, rhs)); } throw new InvalidOperationException(); }
protected HqlTreeNode VisitBinaryExpression(BinaryExpression expression) { // There are some cases where we do not want to add a sql cast: // - When comparing numeric types that do not have their own operator (e.g. short == short) // - When comparing a member expression with a parameter of similar type (e.g. o.Short == intParameter) var leftType = GetExpressionType(expression.Left); var rightType = GetExpressionType(expression.Right); if (leftType != null && leftType == rightType) { _notCastableExpressions[expression.Left] = leftType; _notCastableExpressions[expression.Right] = rightType; } if (expression.NodeType == ExpressionType.Equal) { return(TranslateEqualityComparison(expression)); } if (expression.NodeType == ExpressionType.NotEqual) { return(TranslateInequalityComparison(expression)); } _nullableExpressionDetector.SearchForNotNullMemberChecks(expression); var lhs = VisitExpression(expression.Left).AsExpression(); var rhs = VisitExpression(expression.Right).AsExpression(); switch (expression.NodeType) { case ExpressionType.And: return(_hqlTreeBuilder.BitwiseAnd(lhs, rhs)); case ExpressionType.AndAlso: return(_hqlTreeBuilder.BooleanAnd(lhs.ToBooleanExpression(), rhs.ToBooleanExpression())); case ExpressionType.Or: return(_hqlTreeBuilder.BitwiseOr(lhs, rhs)); case ExpressionType.OrElse: return(_hqlTreeBuilder.BooleanOr(lhs.ToBooleanExpression(), rhs.ToBooleanExpression())); case ExpressionType.Add: if (expression.Left.Type == typeof(string) && expression.Right.Type == typeof(string)) { return(_hqlTreeBuilder.MethodCall("concat", lhs, rhs)); } return(_hqlTreeBuilder.Add(lhs, rhs)); case ExpressionType.Subtract: return(_hqlTreeBuilder.Subtract(lhs, rhs)); case ExpressionType.Multiply: return(_hqlTreeBuilder.Multiply(lhs, rhs)); case ExpressionType.Divide: return(_hqlTreeBuilder.Divide(lhs, rhs)); case ExpressionType.Modulo: return(_hqlTreeBuilder.MethodCall("mod", lhs, rhs)); case ExpressionType.LessThan: return(_hqlTreeBuilder.LessThan(lhs, rhs)); case ExpressionType.LessThanOrEqual: return(_hqlTreeBuilder.LessThanOrEqual(lhs, rhs)); case ExpressionType.GreaterThan: return(_hqlTreeBuilder.GreaterThan(lhs, rhs)); case ExpressionType.GreaterThanOrEqual: return(_hqlTreeBuilder.GreaterThanOrEqual(lhs, rhs)); case ExpressionType.Coalesce: return(_hqlTreeBuilder.Coalesce(lhs.ToArithmeticExpression(), rhs.ToArithmeticExpression())); } throw new InvalidOperationException(); }