/// <summary> /// create greater than or equal expression ( operator ">=" or "=ge=" ) /// </summary> /// <param name="parameter"></param> /// <param name="context"></param> /// <param name="jsonNamingPolicy"></param> /// <typeparam name="T"></typeparam> /// <returns></returns> public static Expression <Func <T, bool> > GetGeExpression <T>(ParameterExpression parameter, RSqlQueryParser.ComparisonContext context, JsonNamingPolicy jsonNamingPolicy = null) { var expressionValue = GetSelector <T>(parameter, context, jsonNamingPolicy); if (!RSqlQueryGetValueHelper.IsLowerOrGreaterComparisonType(expressionValue.Property.PropertyType)) { throw new ComparisonInvalidComparatorSelectionException(context); } var value = GetUniqueValue <T>(parameter, expressionValue, context, jsonNamingPolicy); var expression = value is ExpressionValue valueExp1 ? valueExp1.Expression : Expression.Constant(value, expressionValue.Property.PropertyType); if (value is ExpressionValue valueExp2 && valueExp2.Property.PropertyType != expressionValue.Property.PropertyType) { throw new ComparisonInvalidMatchTypeException(context); } return(Expression.Lambda <Func <T, bool> >(Expression.GreaterThanOrEqual( expressionValue.Expression, expression), parameter)); }
/// <summary> /// extract the selector /// </summary> /// <param name="parameter"></param> /// <param name="context"></param> /// <param name="jsonNamingPolicy"></param> /// <typeparam name="T"></typeparam> /// <returns></returns> /// <exception cref="ArgumentNullException"></exception> private static ExpressionValue GetSelector <T>(ParameterExpression parameter, RSqlQueryParser.ComparisonContext context, JsonNamingPolicy jsonNamingPolicy) { var result = ExpressionValue.Parse <T>(parameter, context.selector().GetText(), jsonNamingPolicy); return(result ?? throw new ComparisonUnknownSelectorException(context)); }
/// <summary> /// create not in expression ( operator "=out=" ) /// </summary> /// <returns></returns> public static Expression <Func <T, bool> > GetOutExpression <T>(ParameterExpression parameter, RSqlQueryParser.ComparisonContext context, JsonNamingPolicy namingStrategy = null) { var expression = GetInExpression <T>(parameter, context, namingStrategy); var body = Expression.Not(expression.Body); return(Expression.Lambda <Func <T, bool> >(body, parameter)); }
public static object GetTemporalValue <T>(ParameterExpression parameter, ExpressionValue expressionValue, RSqlQueryParser.ComparisonContext context, JsonNamingPolicy jsonNamingPolicy = null) { if (IsDateTimeOffset(expressionValue.Property.PropertyType)) { return(GetDateTimeOffset <T>(parameter, context.arguments().value()[0], jsonNamingPolicy)); } return(GetDateTime <T>(parameter, context.arguments().value()[0], jsonNamingPolicy)); }
public static object GetAlphabeticValue <T>(ParameterExpression parameter, ExpressionValue expressionValue, RSqlQueryParser.ComparisonContext context, JsonNamingPolicy jsonNamingPolicy = null) { if (IsChar(expressionValue.Property.PropertyType)) { return(GetChar <T>(parameter, context.arguments().value()[0], jsonNamingPolicy)); } return(GetString <T>(parameter, context.arguments().value()[0], jsonNamingPolicy)); }
/// <summary> /// extract the unique value /// </summary> /// <param name="parameter"></param> /// <param name="expressionValue"></param> /// <param name="context"></param> /// <param name="jsonNamingPolicy"></param> /// <typeparam name="T"></typeparam> /// <returns></returns> /// <exception cref="ComparisonNotEnoughArgumentException"></exception> /// <exception cref="ComparisonTooManyArgumentException"></exception> private static object GetUniqueValue <T>(ParameterExpression parameter, ExpressionValue expressionValue, RSqlQueryParser.ComparisonContext context, JsonNamingPolicy jsonNamingPolicy = null) { var value = context.arguments().value(); if (value.Length > 1) { throw new ComparisonTooManyArgumentException(context); } return(RSqlQueryGetValueHelper.GetValue <T>(parameter, expressionValue, context, jsonNamingPolicy)); }
/// <summary> /// create in expression ( operator "=in=" ) /// </summary> /// <returns></returns> public static Expression <Func <T, bool> > GetInExpression <T>(ParameterExpression parameter, RSqlQueryParser.ComparisonContext context, JsonNamingPolicy jsonNamingPolicy = null) { var expressionValue = GetSelector <T>(parameter, context, jsonNamingPolicy); var values = GetMultipleValue(expressionValue, context); var methodContainsInfo = QueryReflectionHelper.GetOrRegistryContainsMethodInfo(expressionValue.Property.PropertyType); return(Expression.Lambda <Func <T, bool> >( Expression.Call(Expression.Constant(methodContainsInfo.Convert(values)), methodContainsInfo.ContainsMethod, expressionValue.Expression), parameter)); }
/// <summary> /// visit a comparison expression /// </summary> /// <param name="context"></param> /// <returns></returns> public override Expression <Func <T, bool> > VisitComparison(RSqlQueryParser.ComparisonContext context) { var comparator = context.comparator().GetText().ToLowerInvariant(); switch (comparator) { case "=is-null=": case "=nil=": return(RSqlQueryExpressionHelper.GetIsNullExpression <T>(_parameter, context, _jsonNamingPolicy)); case "==": case "=eq=": return(RSqlQueryExpressionHelper.GetEqExpression <T>(_parameter, context, _jsonNamingPolicy)); case "!=": case "=neq=": return(RSqlQueryExpressionHelper.GetNeqExpression <T>(_parameter, context, _jsonNamingPolicy)); case "<": case "=lt=": return(RSqlQueryExpressionHelper.GetLtExpression <T>(_parameter, context, _jsonNamingPolicy)); case "<=": case "=le=": return(RSqlQueryExpressionHelper.GetLeExpression <T>(_parameter, context, _jsonNamingPolicy)); case ">": case "=gt=": return(RSqlQueryExpressionHelper.GetGtExpression <T>(_parameter, context, _jsonNamingPolicy)); case ">=": case "=ge=": return(RSqlQueryExpressionHelper.GetGeExpression <T>(_parameter, context, _jsonNamingPolicy)); case "=in=": return(RSqlQueryExpressionHelper.GetInExpression <T>(_parameter, context, _jsonNamingPolicy)); case "=out=": return(RSqlQueryExpressionHelper.GetOutExpression <T>(_parameter, context, _jsonNamingPolicy)); default: throw new ComparisonUnknownComparatorException(context); } }
/// <summary> /// create equal expression ( operator "==" or "=eq=" ) /// </summary> /// <param name="parameter"></param> /// <param name="context"></param> /// <param name="jsonNamingPolicy"></param> /// <typeparam name="T"></typeparam> /// <returns></returns> public static Expression <Func <T, bool> > GetEqExpression <T>(ParameterExpression parameter, RSqlQueryParser.ComparisonContext context, JsonNamingPolicy jsonNamingPolicy = null) { var expressionValue = GetSelector <T>(parameter, context, jsonNamingPolicy); if (!RSqlQueryGetValueHelper.IsEqualComparisonType(expressionValue.Property.PropertyType)) { throw new ComparisonInvalidComparatorSelectionException(context); } var value = GetUniqueValue <T>(parameter, expressionValue, context, jsonNamingPolicy); var expression = value is ExpressionValue valueExp1 ? valueExp1.Expression : Expression.Constant(value, expressionValue.Property.PropertyType); if (value is ExpressionValue valueExp2 && valueExp2.Property.PropertyType != expressionValue.Property.PropertyType) { throw new ComparisonInvalidMatchTypeException(context); } if (expressionValue.Property.PropertyType != typeof(string) || value is ExpressionValue) { return(Expression.Lambda <Func <T, bool> >(Expression.Equal( expressionValue.Expression, expression ), parameter)); } var v = ((string)value).Replace(@"\*", MaskLk); if (v.IndexOf('*') != -1) { return(GetLkExpression <T>(parameter, context, jsonNamingPolicy)); } value = v.Replace(MaskLk, "*"); return(Expression.Lambda <Func <T, bool> >(Expression.Equal( expressionValue.Expression, Expression.Constant(value, expressionValue.Property.PropertyType)), parameter)); }
/// <summary> /// create like expression /// </summary> /// <returns></returns> private static Expression <Func <T, bool> > GetLkExpression <T>(ParameterExpression parameter, RSqlQueryParser.ComparisonContext context, JsonNamingPolicy jsonNamingPolicy = null) { var expressionValue = GetSelector <T>(parameter, context, jsonNamingPolicy); var values = RSqlQueryGetValueHelper.GetValues(expressionValue.Property.PropertyType, context.arguments()); if (values.Count > 1) { throw new ComparisonTooManyArgumentException(context); } var criteria = Convert.ToString(values[0]) ?? string.Empty; var maskStar = "{" + Guid.NewGuid() + "}"; criteria = criteria.Replace(@"\*", maskStar); MethodInfo method; if (!criteria.Contains('*')) { criteria += '*'; } if (criteria.StartsWith("*", StringComparison.Ordinal) && criteria.EndsWith("*", StringComparison.Ordinal)) { method = QueryReflectionHelper.MethodStringContains; } else if (criteria.StartsWith("*", StringComparison.Ordinal)) { method = QueryReflectionHelper.MethodStringEndsWith; } else { method = QueryReflectionHelper.MethodStringStartsWith; } criteria = criteria.Replace("*", "").Replace(maskStar, "*"); return(Expression.Lambda <Func <T, bool> >(Expression.Call(expressionValue.Expression, method, Expression.Constant(criteria, expressionValue.Property.PropertyType)), parameter)); }
public static object GetValue <T>(ParameterExpression parameter, ExpressionValue expressionValue, RSqlQueryParser.ComparisonContext context, JsonNamingPolicy jsonNamingPolicy = null) { CheckParameters(parameter, expressionValue, context); if (IsNumeric(expressionValue.Property.PropertyType)) { return(GetNumericValue <T>(parameter, expressionValue, context, jsonNamingPolicy)); } if (IsTemporal(expressionValue.Property.PropertyType)) { return(GetTemporalValue <T>(parameter, expressionValue, context, jsonNamingPolicy)); } if (IsAlphabetic(expressionValue.Property.PropertyType)) { return(GetAlphabeticValue <T>(parameter, expressionValue, context, jsonNamingPolicy)); } if (IsBool(expressionValue.Property.PropertyType)) { return(GetBoolean <T>(parameter, context.arguments().value()[0], jsonNamingPolicy)); } if (IsEnum(expressionValue.Property.PropertyType)) { return(GetEnum <T>(parameter, context.arguments().value()[0], expressionValue.Property.PropertyType, jsonNamingPolicy)); } if (IsGuid(expressionValue.Property.PropertyType)) { return(GetGuid <T>(parameter, context.arguments().value()[0], jsonNamingPolicy)); } return(null); }
/// <summary> /// create is null expression ( operator "=is-null=" or "=nil=" ) /// </summary> /// <param name="parameter"></param> /// <param name="context"></param> /// <param name="jsonNamingPolicy"></param> /// <typeparam name="T"></typeparam> /// <returns></returns> public static Expression <Func <T, bool> > GetIsNullExpression <T>(ParameterExpression parameter, RSqlQueryParser.ComparisonContext context, JsonNamingPolicy jsonNamingPolicy = null) { var expressionValue = GetSelector <T>(parameter, context, jsonNamingPolicy); if (!RSqlQueryGetValueHelper.IsNullableComparisonType(expressionValue.Property.PropertyType)) { throw new ComparisonInvalidComparatorSelectionException(context); } var values = RSqlQueryGetValueHelper.GetValues(typeof(bool), context.arguments()); if (!values.Any()) { throw new ComparisonNotEnoughArgumentException(context); } if (values.Count > 1) { throw new ComparisonTooManyArgumentException(context); } var result = Expression.Lambda <Func <T, bool> >(Expression.Equal( expressionValue.Expression, Expression.Constant(null, typeof(object))), parameter); if ((bool)values[0]) { return(result); } var body = Expression.Not(result.Body); result = Expression.Lambda <Func <T, bool> >(body, parameter); return(result); }
public static object GetNumericValue <T>(ParameterExpression parameter, ExpressionValue expressionValue, RSqlQueryParser.ComparisonContext context, JsonNamingPolicy jsonNamingPolicy = null) { if (IsShort(expressionValue.Property.PropertyType)) { return(GetShort <T>(parameter, context.arguments().value()[0], jsonNamingPolicy)); } if (IsLong(expressionValue.Property.PropertyType)) { return(GetLong <T>(parameter, context.arguments().value()[0], jsonNamingPolicy)); } if (IsFloat(expressionValue.Property.PropertyType)) { return(GetFloat <T>(parameter, context.arguments().value()[0], jsonNamingPolicy)); } if (IsDouble(expressionValue.Property.PropertyType)) { return(GetDouble <T>(parameter, context.arguments().value()[0], jsonNamingPolicy)); } if (IsDecimal(expressionValue.Property.PropertyType)) { return(GetDecimal <T>(parameter, context.arguments().value()[0], jsonNamingPolicy)); } if (IsByte(expressionValue.Property.PropertyType)) { return(GetByte <T>(parameter, context.arguments().value()[0], jsonNamingPolicy)); } return(GetInt <T>(parameter, context.arguments().value()[0], jsonNamingPolicy)); }
/// <summary> /// Exit a parse tree produced by <see cref="RSqlQueryParser.comparison"/>. /// <para>The default implementation does nothing.</para> /// </summary> /// <param name="context">The parse tree.</param> public virtual void ExitComparison([NotNull] RSqlQueryParser.ComparisonContext context) { }
/// <summary> /// extract the multi value /// </summary> /// <param name="expressionValue"></param> /// <param name="context"></param> /// <returns></returns> /// <exception cref="ComparisonNotEnoughArgumentException"></exception> private static List <object> GetMultipleValue(ExpressionValue expressionValue, RSqlQueryParser.ComparisonContext context) { return(RSqlQueryGetValueHelper.GetValues(expressionValue.Property.PropertyType, context.arguments())); }
public ComparisonTooManyArgumentException(RSqlQueryParser.ComparisonContext origin, Exception innerException = null) : base(origin, $"Too many arguments : {origin?.selector()?.GetText()}", innerException) { }
private static void CheckParameters(ParameterExpression parameter, ExpressionValue expressionValue, RSqlQueryParser.ComparisonContext context) { if (parameter == null) { throw new ArgumentNullException(nameof(parameter)); } if (expressionValue == null) { throw new ArgumentNullException(nameof(expressionValue)); } if (context == null) { throw new ArgumentNullException(nameof(context)); } }
public ComparisonInvalidComparatorSelectionException(RSqlQueryParser.ComparisonContext origin, Exception innerException = null) : base(origin, $"Invalid selector : {origin?.selector()?.GetText()}", innerException) { }
public ComparisonInvalidMatchTypeException(RSqlQueryParser.ComparisonContext origin, Exception innerException = null) : base(origin, $"Invalid comparison match type : {origin?.selector()?.GetText()} and {origin?.arguments()?.GetText()}", innerException) { }
public ComparisonUnknownComparatorException(RSqlQueryParser.ComparisonContext origin, Exception innerException = null) : base(origin, $"Unknown comparator : {origin?.comparator()?.GetText()}", innerException) { }
public ComparisonNotEnoughArgumentException(RSqlQueryParser.ComparisonContext origin, Exception innerException = null) : base(origin, $"Not enough argument : {origin?.selector()?.GetText()}", innerException) { }
/// <summary> /// Visit a parse tree produced by <see cref="RSqlQueryParser.comparison"/>. /// <para> /// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/> /// on <paramref name="context"/>. /// </para> /// </summary> /// <param name="context">The parse tree.</param> /// <return>The visitor result.</return> public virtual Result VisitComparison([NotNull] RSqlQueryParser.ComparisonContext context) { return(VisitChildren(context)); }
public ComparisonUnknownSelectorException(RSqlQueryParser.ComparisonContext origin, Exception innerException = null) : base(origin, $"Unknown selector : '{origin?.selector()?.GetText()}'", innerException) { }