protected override Expression VisitBinary(BinaryExpression node) { if (_parsePhase.Get() == ParsePhase.Condition) { if (node.NodeType == ExpressionType.AndAlso) { // It's the AND of the WHERE/IF clause Visit(node.Left); // Add the new condition for the right portion _conditions.Add(new BinaryConditionItem()); Visit(node.Right); return(node); } var condition = _conditions.Last(); if (BinaryConditionItem.IsSupported(node.NodeType)) { if (node.NodeType == ExpressionType.Equal && IsBoolMember(node.Left)) { // Handle x.prop == boolValue explicitly FillBooleanCondition((MemberExpression)node.Left, condition); Visit(node.Right); return(node); } if (node.NodeType == ExpressionType.Equal && IsBoolMember(node.Right)) { // Handle boolValue == x.prop explicitly FillBooleanCondition((MemberExpression)node.Right, condition); Visit(node.Left); return(node); } Visit(DropNullableConversion(node.Left)); condition.SetOperator(node.NodeType); Visit(DropNullableConversion(node.Right)); return(node); } if (!CqlUnsupTags.Contains(node.NodeType)) { condition.SetParameter(Expression.Lambda(node).Compile().DynamicInvoke()); return(node); } } else if (_parsePhase.Get() == ParsePhase.SelectBinding) { var column = _pocoData.GetColumnByMemberName(_currentBindingName.Get()); if (column == null) { throw new ArgumentException("Trying to select a column does it excluded in the mappings"); } AddProjection(node, column); _selectFields.Add(column.ColumnName); return(node); } throw new CqlLinqNotSupportedException(node, _parsePhase.Get()); }
protected override Expression VisitUnary(UnaryExpression node) { if (_parsePhase.Get() == ParsePhase.Condition) { var condition = _conditions.Last(); if (node.NodeType == ExpressionType.Not && node.Operand.NodeType == ExpressionType.MemberAccess) { // We are evaluating a boolean expression parameter, the value we are trying to match is false FillBooleanCondition((MemberExpression)node.Operand, condition, false); return(node); } if (BinaryConditionItem.IsSupported(node.NodeType)) { condition.SetOperator(node.NodeType); Visit(DropNullableConversion(node.Operand)); } else if (node.NodeType == ExpressionType.Convert) { Visit(node.Operand); } else { var val = Expression.Lambda(node).Compile().DynamicInvoke(); condition.SetParameter(val); } return(node); } if (_parsePhase.Get() == ParsePhase.SelectBinding) { if (node.NodeType == ExpressionType.Convert && node.Type.Name == "Nullable`1") { // ReSharper disable once AssignNullToNotNullAttribute return(Visit(node.Operand)); } var column = _pocoData.GetColumnByMemberName(_currentBindingName.Get()); if (column != null && column.IsCounter) { var value = Expression.Lambda(node).Compile().DynamicInvoke(); if (!(value is long || value is int)) { throw new ArgumentException("Only Int64 and Int32 values are supported as counter increment of decrement values"); } _projections.Add(Tuple.Create(column, value, ExpressionType.Increment)); _selectFields.Add(column.ColumnName); return(node); } } throw new CqlLinqNotSupportedException(node, _parsePhase.Get()); }
private Expression EvaluateConditionFunction(MethodCallExpression node) { var condition = _conditions.Last(); switch (node.Method.Name) { case nameof(Enumerable.Contains): EvaluateContainsMethod(node); return(node); case nameof(Tuple.Create) when node.Method.DeclaringType == typeof(Tuple): EvaluateCompositeColumn(node); return(node); case nameof(string.StartsWith) when node.Method.DeclaringType == typeof(string): Visit(node.Object); var startsWithArgument = node.Arguments[0]; var startString = (string)Expression.Lambda(startsWithArgument).Compile().DynamicInvoke(); var endString = startString + Utf8MaxValue; // Create 2 conditions, ie: WHERE col1 >= startString AND col2 < endString var column = condition.Column; condition.SetOperator(ExpressionType.GreaterThanOrEqual) .SetParameter(startString); condition = new BinaryConditionItem(); condition.SetColumn(column) .SetOperator(ExpressionType.LessThan) .SetParameter(endString); _conditions.Add(condition); return(node); case nameof(IComparable.CompareTo): // Allow comparison to zero condition.SetAsCompareTo(); Visit(node.Object); Visit(node.Arguments[0]); return(node); case nameof(Equals): Visit(node.Object); condition.SetOperator(ExpressionType.Equal); Visit(node.Arguments[0]); return(node); case nameof(CqlToken.Create) when node.Method.DeclaringType == typeof(CqlToken): case nameof(CqlFunction.Token) when node.Method.DeclaringType == typeof(CqlFunction): condition.SetFunctionName("token").AllowMultipleColumns().AllowMultipleParameters(); foreach (var argument in node.Arguments) { Visit(argument); } return(node); case nameof(CqlFunction.MaxTimeUuid): case nameof(CqlFunction.MinTimeUuid): condition.SetFunctionName(node.Method.Name.ToLowerInvariant()); Visit(node.Arguments[0]); return(node); } // Try to invoke to obtain the parameter value condition.SetParameter(Expression.Lambda(node).Compile().DynamicInvoke()); return(node); }