Пример #1
0
        /// <summary>
        /// Parse and compile string expression and return BsonExpression
        /// </summary>
        internal static BsonExpression Parse(Tokenizer tokenizer, BsonExpressionParserMode mode, bool isRoot)
        {
            if (tokenizer == null)
            {
                throw new ArgumentNullException(nameof(tokenizer));
            }

            var source     = Expression.Parameter(typeof(IEnumerable <BsonDocument>), "source");
            var root       = Expression.Parameter(typeof(BsonDocument), "root");
            var current    = Expression.Parameter(typeof(BsonValue), "current");
            var parameters = Expression.Parameter(typeof(BsonDocument), "parameters");

            var expr =
                mode == BsonExpressionParserMode.Full ? BsonExpressionParser.ParseFullExpression(tokenizer, source, root, current, parameters, isRoot) :
                mode == BsonExpressionParserMode.Single ? BsonExpressionParser.ParseSingleExpression(tokenizer, source, root, current, parameters, isRoot) :
                mode == BsonExpressionParserMode.SelectDocument ? BsonExpressionParser.ParseSelectDocumentBuilder(tokenizer, source, root, current, parameters) :
                BsonExpressionParser.ParseUpdateDocumentBuilder(tokenizer, source, root, current, parameters);

            // before compile try find in cache if this source already has in cache (already compiled)
            var cached = _cache.GetOrAdd(expr.Source, (s) =>
            {
                // compile linq expression (with left+right expressions)
                Compile(expr, source, root, current, parameters);
                return(expr);
            });

            return(cached);
        }
Пример #2
0
        /// <summary>
        /// Parse and compile string expression and return BsonExpression
        /// </summary>
        internal static BsonExpression Parse(Tokenizer tokenizer, BsonExpressionParserMode mode, bool isRoot)
        {
            if (tokenizer == null)
            {
                throw new ArgumentNullException(nameof(tokenizer));
            }

            var context = new ExpressionContext();

            var expr =
                mode == BsonExpressionParserMode.Full ? BsonExpressionParser.ParseFullExpression(tokenizer, context, isRoot) :
                mode == BsonExpressionParserMode.Single ? BsonExpressionParser.ParseSingleExpression(tokenizer, context, isRoot) :
                mode == BsonExpressionParserMode.SelectDocument ? BsonExpressionParser.ParseSelectDocumentBuilder(tokenizer, context) :
                BsonExpressionParser.ParseUpdateDocumentBuilder(tokenizer, context);

            // before compile try find in cache if this source already has in cache (already compiled)
            var cached = _cache.GetOrAdd(expr.Source, (s) =>
            {
                // compile linq expression (with left+right expressions)
                Compile(expr, context);
                return(expr);
            });

            return(cached);
        }
Пример #3
0
        /// <summary>
        /// Returns documents that exists in ANY queries results (Union).
        /// </summary>
        public static BsonExpression Or(BsonExpression left, BsonExpression right)
        {
            if (left == null)
            {
                throw new ArgumentNullException(nameof(left));
            }
            if (right == null)
            {
                throw new ArgumentNullException(nameof(right));
            }

            return(BsonExpressionParser.CreateBinaryExpression("OR", left, right));
        }
Пример #4
0
        /// <summary>
        /// Returns document that exists in BOTH queries results. If both queries has indexes, left query has index preference (other side will be run in full scan)
        /// </summary>
        public static BsonExpression And(BsonExpression left, BsonExpression right)
        {
            if (left == null)
            {
                throw new ArgumentNullException(nameof(left));
            }
            if (right == null)
            {
                throw new ArgumentNullException(nameof(right));
            }

            return(BsonExpressionParser.CreateLogicExpression(BsonExpressionType.And, left, right));
        }
Пример #5
0
        public BsonExpression Resolve(bool predicate)
        {
            this.Visit(_expr);

            ENSURE(_nodes.Count == 0, "node stack must be empty when finish expression resolve");

            var expression = _builder.ToString();

            try
            {
                var e = BsonExpression.Create(expression, _parameters);

                // if expression must return an predicate but expression result is Path/Parameter/Call add `= true`
                if (predicate && (e.Type == BsonExpressionType.Path || e.Type == BsonExpressionType.Call || e.Type == BsonExpressionType.Parameter))
                {
                    expression = "(" + expression + " = true)";

                    e = BsonExpression.Create(expression, _parameters);
                }
                else if (e.Type == BsonExpressionType.And && e.Left.Type == BsonExpressionType.GreaterThanOrEqual && e.Right.Type == BsonExpressionType.LessThanOrEqual &&
                         e.Left.Left.Source == e.Right.Left.Source)
                //checks if expression is of the form "something >= x && something <= y", to be transformed into between expression
                {
                    BsonExpression arr = BsonExpressionParser.NewArray(e.Left.Right, e.Right.Right);

                    var op = BsonExpressionParser._operators["BETWEEN"];

                    e = new BsonExpression
                    {
                        Type        = BsonExpressionType.Between,
                        Parameters  = e.Parameters,
                        IsImmutable = e.Left.IsImmutable && e.Right.IsImmutable,
                        UseSource   = e.Left.UseSource || e.Right.UseSource,
                        IsScalar    = true,
                        Fields      = e.Fields,
                        Expression  = Expression.Call(op.Item2, new ExpressionContext().Collation, e.Left.Left.Expression, arr.Expression),
                        Left        = e.Left.Left,
                        Right       = arr,
                        Source      = e.Left.Left.Source + op.Item1 + arr.Source
                    };
                }

                return(e);
            }
            catch (Exception ex)
            {
                throw new NotSupportedException($"Invalid BsonExpression when converted from Linq expression: {_expr.ToString()} - `{expression}`", ex);
            }
        }
Пример #6
0
        /// <summary>
        /// Parse and compile string expression and return BsonExpression
        /// </summary>
        internal static BsonExpression ParseAndCompile(Tokenizer tokenizer, BsonExpressionParserMode mode, BsonDocument parameters, DocumentScope scope)
        {
            if (tokenizer == null)
            {
                throw new ArgumentNullException(nameof(tokenizer));
            }

            var context = new ExpressionContext();

            var expr =
                mode == BsonExpressionParserMode.Full ? BsonExpressionParser.ParseFullExpression(tokenizer, context, parameters, scope) :
                mode == BsonExpressionParserMode.Single ? BsonExpressionParser.ParseSingleExpression(tokenizer, context, parameters, scope) :
                mode == BsonExpressionParserMode.SelectDocument ? BsonExpressionParser.ParseSelectDocumentBuilder(tokenizer, context, parameters) :
                BsonExpressionParser.ParseUpdateDocumentBuilder(tokenizer, context, parameters);

            // compile linq expression (with left+right expressions)
            Compile(expr, context);

            return(expr);
        }