protected override FilterExpression Transform(FilterCallExpression lx) { if (!Operators.SameOperator(lx.OperatorName.ToLowerInvariant(), Operators.IntermediateOpSqlIs) || lx.Operands.Length != 2) { return(base.Transform(lx)); } var nul = lx.Operands[1] as FilterConstantExpression; if (nul != null) { if (nul.ConstantValue != null) { return(base.Transform(lx)); } return(new FilterCallExpression(Operators.RuntimeOpIsNull, lx.Operands[0])); } var not = lx.Operands[1] as FilterCallExpression; if (not == null || not.Operands.Length != 1) { return(base.Transform(lx)); } nul = not.Operands[0] as FilterConstantExpression; if (nul == null || nul.ConstantValue != null) { return(base.Transform(lx)); } return(new FilterCallExpression(Operators.RuntimeOpIsNotNull, lx.Operands[0])); }
protected override FilterExpression Transform(FilterCallExpression lx) { var newOperands = lx.Operands.Select(Transform).ToArray(); if (Operators.SameOperator(lx.OperatorName, Operators.IntermediateOpSqlLike)) { if (newOperands.Length == 2 && newOperands[1] is FilterTextExpression) { return(Like(newOperands[0], (FilterTextExpression)newOperands[1])); } return(new FilterConstantExpression(Undefined.Value)); } if (Operators.SameOperator(lx.OperatorName, Operators.IntermediateOpSqlNotLike)) { if (newOperands.Length == 2 && newOperands[1] is FilterTextExpression) { return(new FilterCallExpression(Operators.RuntimeOpStrictNot, Like(newOperands[0], (FilterTextExpression)newOperands[1]))); } return(new FilterConstantExpression(Undefined.Value)); } return(new FilterCallExpression(lx.OperatorName, newOperands)); }
protected override FilterExpression Transform(FilterCallExpression lx) { if (!Operators.WildcardComparators.Contains(lx.OperatorName) || lx.Operands.Length != 2) { return(base.Transform(lx)); } var lhsIs = FilterExpressionWildcardSearch.FindElementAtWildcard(lx.Operands[0]); var rhsIs = FilterExpressionWildcardSearch.FindElementAtWildcard(lx.Operands[1]); if (lhsIs != null && rhsIs != null || lhsIs == null && rhsIs == null) { return(base.Transform(lx)); // N/A, or invalid } var wcpath = lhsIs != null ? lx.Operands[0] : lx.Operands[1]; var comparand = lhsIs != null ? lx.Operands[1] : lx.Operands[0]; var elmat = lhsIs ?? rhsIs; var parm = new FilterParameterExpression("p" + _nextParameter++); var nestedComparand = FilterExpressionNodeReplacer.Replace(wcpath, elmat, parm); var coll = elmat.Operands[0]; var wc = ((FilterWildcardExpression)elmat.Operands[1]).Wildcard; var comparisonArgs = lhsIs != null ? new[] { nestedComparand, comparand } : new[] { comparand, nestedComparand }; var body = new FilterCallExpression(lx.OperatorName, comparisonArgs); var lambda = new FilterLambdaExpression(new[] { parm }, body); var op = Operators.ToRuntimeWildcardOperator(wc); var call = new FilterCallExpression(op, new[] { coll, lambda }); return(Transform(call)); }
public override FilterExpression Rewrite(FilterCallExpression lx, TextMatchingTransformer rewriteArm) { if (lx.Operands.Length != 2) { return(base.Rewrite(lx, rewriteArm)); } var tx0 = lx.Operands[0] as FilterTextExpression; var tx1 = lx.Operands[1] as FilterTextExpression; if (tx1?.Matching == FilterTextMatching.RegularExpression || tx1?.Matching == FilterTextMatching.RegularExpressionInsensitive) { var ci = RegexOptions.None; if (UseCaseInsensitiveRegexMatching(tx0, tx1.Matching)) { ci = RegexOptions.IgnoreCase; } var refind = new Regex(tx1.Text, ci | RegexOptions.ExplicitCapture | RegexOptions.Compiled | RegexOptions.Multiline); return(new FilterCallExpression(Operators.ToRuntimePattern(lx.OperatorName), rewriteArm.Transform(lx.Operands[0]), new FilterConstantExpression(refind))); } return(new FilterCallExpression( UseCaseInsensitiveTextMatching(tx0, tx1) ? Operators.ToRuntimeIgnoreCase(lx.OperatorName) : lx.OperatorName, rewriteArm.Transform(lx.Operands[0]), rewriteArm.Transform(lx.Operands[1]))); }
protected override FilterExpression Transform(FilterCallExpression lx) { if (Operators.SameOperator(Operators.IntermediateOpSqlNotIn, lx.OperatorName)) { return(new FilterCallExpression(Operators.RuntimeOpStrictNot, new FilterCallExpression(Operators.RuntimeOpSqlIn, lx.Operands))); } return(base.Transform(lx)); }
protected override FilterExpression Transform(FilterCallExpression lx) { if (lx == _source) { return(_dest); } return(base.Transform(lx)); }
protected override FilterExpression Transform(FilterCallExpression lx) { MatchingRewriter comparison; if (!Rewriters.TryGetValue(lx.OperatorName, out comparison)) { return(base.Transform(lx)); } return(comparison.Rewrite(lx, this)); }
public override FilterExpression Rewrite(FilterCallExpression lx, TextMatchingTransformer rewriteArm) { if (lx.Operands.Length != 2) { return(base.Rewrite(lx, rewriteArm)); } // Just a rename to match the runtime function. return(new FilterCallExpression( Operators.RuntimeOpIndexOfIgnoreCase, rewriteArm.Transform(lx.Operands[0]), rewriteArm.Transform(lx.Operands[1]))); }
protected override FilterExpression Transform(FilterCallExpression lx) { if (!Operators.SameOperator(lx.OperatorName, Operators.OpElementAt) || lx.Operands.Length != 2) { return(base.Transform(lx)); } var p = lx.Operands[0] as FilterPropertyExpression; var n = lx.Operands[1] as FilterTextExpression; if (p == null || n == null || !p.IsBuiltIn || p.PropertyName != "Properties" || n.Matching == FilterTextMatching.RegularExpression || n.Matching == FilterTextMatching.RegularExpressionInsensitive) { return(base.Transform(lx)); } return(new FilterPropertyExpression(n.Text, false)); }
public override FilterExpression Rewrite(FilterCallExpression lx, TextMatchingTransformer rewriteArm) { if (lx.Operands.Length != 2) { return(base.Rewrite(lx, rewriteArm)); } var tx0 = lx.Operands[0] as FilterTextExpression; var tx1 = lx.Operands[1] as FilterTextExpression; if (tx0?.Matching == FilterTextMatching.RegularExpression || tx0?.Matching == FilterTextMatching.RegularExpressionInsensitive || tx1?.Matching == FilterTextMatching.RegularExpression || tx1?.Matching == FilterTextMatching.RegularExpressionInsensitive) { if (tx1?.Matching != FilterTextMatching.RegularExpression && tx1?.Matching != FilterTextMatching.RegularExpressionInsensitive) { // Make sure the regex is always second. return(Rewrite(new FilterCallExpression(lx.OperatorName, lx.Operands[1], lx.Operands[0]), rewriteArm)); } var ci = RegexOptions.None; if (UseCaseInsensitiveRegexMatching(tx0, tx1.Matching)) { ci |= RegexOptions.IgnoreCase; } var rewhole = new Regex("^" + tx1.Text + "$", ci | RegexOptions.ExplicitCapture); return(new FilterCallExpression(Operators.ToRuntimePattern(lx.OperatorName), rewriteArm.Transform(lx.Operands[0]), new FilterConstantExpression(rewhole))); } return(new FilterCallExpression( UseCaseInsensitiveTextMatching(tx0, tx1) ? Operators.ToRuntimeIgnoreCase(lx.OperatorName) : lx.OperatorName, rewriteArm.Transform(lx.Operands[0]), rewriteArm.Transform(lx.Operands[1]))); }
protected override Expression <CompiledFilterExpression> Transform(FilterCallExpression lx) { MethodInfo m; if (!OperatorMethods.TryGetValue(lx.OperatorName, out m)) { throw new ArgumentException($"The function name `{lx.OperatorName}` was not recognised; to search for text instead, enclose the filter in \"double quotes\"."); } if (m.GetParameters().Length != lx.Operands.Length) { throw new ArgumentException($"The function `{lx.OperatorName}` requires {m.GetParameters().Length} arguments; to search for text instead, enclose the filter in \"double quotes\"."); } var acceptUndefined = m.GetCustomAttribute <AcceptUndefinedAttribute>() != null; var acceptNull = m.GetCustomAttribute <AcceptNullAttribute>() != null; var numericOnly = m.GetCustomAttribute <NumericAttribute>() != null; var numericComparable = m.GetCustomAttribute <NumericComparableAttribute>() != null; var booleanOnly = m.GetCustomAttribute <BooleanAttribute>() != null; var operands = lx.Operands.Select(Transform).ToArray(); var returnUndefined = new List <Expression <Func <object, bool> > >(); if (!acceptUndefined) { returnUndefined.Add(v => v is Undefined); } if (!acceptNull) { returnUndefined.Add(v => v == null); } if (numericOnly) { returnUndefined.Add(v => !(v is decimal || v == null || v is Undefined)); } if (numericComparable) { returnUndefined.Add(v => !(v is decimal || v == null || v is Undefined)); } if (booleanOnly) { returnUndefined.Add(v => !(v is bool || v == null || v is Undefined)); } var context = Expression.Parameter(typeof(LogEvent)); var operandValues = operands.Select(o => Splice(o, context)); var operandVars = new List <ParameterExpression>(); var rtn = Expression.Label(typeof(object)); var statements = new List <Expression>(); var first = true; foreach (var op in operandValues) { var opam = Expression.Variable(typeof(object)); operandVars.Add(opam); statements.Add(Expression.Assign(opam, op)); if (first && lx.OperatorName.ToLowerInvariant() == "and") { Expression <Func <object, bool> > shortCircuitIf = v => !true.Equals(v); var scc = Splice(shortCircuitIf, opam); statements.Add(Expression.IfThen(scc, Expression.Return(rtn, Expression.Constant(false, typeof(object))))); } if (first && lx.OperatorName.ToLowerInvariant() == "or") { Expression <Func <object, bool> > shortCircuitIf = v => true.Equals(v); var scc = Splice(shortCircuitIf, opam); statements.Add(Expression.IfThen(scc, Expression.Return(rtn, Expression.Constant(true, typeof(object))))); } var checks = returnUndefined.Select(fv => Splice(fv, opam)).ToArray(); foreach (var check in checks) { statements.Add(Expression.IfThen(check, Expression.Return(rtn, Expression.Constant(Undefined.Value, typeof(object))))); } first = false; } statements.Add(Expression.Return(rtn, Expression.Call(m, operandVars))); statements.Add(Expression.Label(rtn, Expression.Constant(Undefined.Value, typeof(object)))); return(Expression.Lambda <CompiledFilterExpression>( Expression.Block(typeof(object), operandVars, statements), context)); }
protected override FilterExpression Transform(FilterCallExpression lx) { return(new FilterCallExpression(lx.OperatorName, lx.Operands.Select(Transform).ToArray())); }
protected override FilterExpressionCosting Transform(FilterCallExpression lx) { var operands = lx.Operands.Select(Transform).ToArray(); var operatorName = lx.OperatorName.ToLowerInvariant(); // To-do: the literal operator name comparisons here can be replaced with constants and IsSameOperator(). if ((operatorName == "and" || operatorName == "or") && operands.Length == 2) { var reorderable = new List <FilterExpressionCosting>(); foreach (var operand in operands) { if (operand.ReorderableOperator?.ToLowerInvariant() == operatorName) { foreach (var ro in operand.ReorderableOperands) { reorderable.Add(ro); } } else { reorderable.Add(operand); } } var remaining = new Stack <FilterExpressionCosting>(reorderable.OrderBy(r => r.Costing)); var top = remaining.Pop(); var rhsExpr = top.Expression; var rhsCosting = top.Costing; while (remaining.Count != 0) { var lhs = remaining.Pop(); rhsExpr = new FilterCallExpression(lx.OperatorName, lhs.Expression, rhsExpr); rhsCosting = lhs.Costing + 0.75 * rhsCosting; } return(new FilterExpressionCosting( rhsExpr, rhsCosting, lx.OperatorName, reorderable.ToArray())); } if ((operatorName == "any" || operatorName == "all") && operands.Length == 2) { return(new FilterExpressionCosting( new FilterCallExpression(lx.OperatorName, operands[0].Expression, operands[1].Expression), operands[0].Costing + 0.1 + operands[1].Costing * 7)); } if ((operatorName == "startswith" || operatorName == "endswith" || operatorName == "contains" || operatorName == "indexof" || operatorName == "equal" || operatorName == "notequal") && operands.Length == 2) { return(new FilterExpressionCosting( new FilterCallExpression(lx.OperatorName, operands[0].Expression, operands[1].Expression), operands[0].Costing + operands[1].Costing + 10)); } return(new FilterExpressionCosting( new FilterCallExpression(lx.OperatorName, operands.Select(o => o.Expression).ToArray()), operands.Sum(o => o.Costing) + 0.1)); }
protected abstract TResult Transform(FilterCallExpression lx);
public virtual FilterExpression Rewrite(FilterCallExpression lx, TextMatchingTransformer rewriteArm) { return(new FilterCallExpression(lx.OperatorName, lx.Operands.Select(rewriteArm.Transform).ToArray())); }