Example #1
0
        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]));
        }
Example #2
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));
        }
Example #3
0
        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));
        }
Example #4
0
        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));
 }
Example #6
0
        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));
        }
Example #8
0
        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])));
        }
Example #9
0
        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));
        }
Example #14
0
 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()));
 }