Пример #1
0
        /// <summary>
        /// Run query definition into engine. Execute optimization to get query planner
        /// </summary>
        internal BsonDataReader ExecuteQuery(bool executionPlan)
        {
            var transaction = _engine.GetTransaction(true, out var isNew);

            transaction.OpenCursors++;

            try
            {
                // encapsulate all execution to catch any error
                return(new BsonDataReader(RunQuery(), _collection));
            }
            catch
            {
                // if any error, rollback transaction
                transaction.Rollback();
                throw;
            }

            IEnumerable <BsonDocument> RunQuery()
            {
                var snapshot = transaction.CreateSnapshot(_query.ForUpdate ? LockMode.Write : LockMode.Read, _collection, false);

                // no collection, no documents
                if (snapshot.CollectionPage == null && _source == null)
                {
                    if (--transaction.OpenCursors == 0 && transaction.ExplicitTransaction == false)
                    {
                        transaction.Commit();
                    }

                    yield break;
                }

                // execute optimization before run query (will fill missing _query properties instance)
                var optimizer = new QueryOptimization(snapshot, _query, _source);

                var queryPlan = optimizer.ProcessQuery();

                // if execution is just to get explan plan, return as single document result
                if (executionPlan)
                {
                    yield return(queryPlan.GetExecutionPlan());

                    if (--transaction.OpenCursors == 0 && transaction.ExplicitTransaction == false)
                    {
                        transaction.Commit();
                    }

                    yield break;
                }

                // get node list from query - distinct by dataBlock (avoid duplicate)
                var nodes = queryPlan.Index.Run(snapshot.CollectionPage, new IndexService(snapshot));

                // get current query pipe: normal or groupby pipe
                using (var pipe = queryPlan.GetPipe(transaction, snapshot, _engine.SortDisk, _engine.Settings.UtcDate))
                {
                    // commit transaction before close pipe
                    pipe.Disposing += (s, e) =>
                    {
                        if (--transaction.OpenCursors == 0 && transaction.ExplicitTransaction == false)
                        {
                            transaction.Commit();
                        }
                    };

                    // call safepoint just before return each document
                    foreach (var doc in pipe.Pipe(nodes, queryPlan))
                    {
                        yield return(doc);
                    }
                }
            };
        }
Пример #2
0
        /// <summary>
        /// Run query definition into engine. Execute optimization to get query planner
        /// </summary>
        internal BsonDataReader ExecuteQuery(bool executionPlan)
        {
            var transaction = _monitor.GetTransaction(true, out var isNew);

            transaction.OpenCursors.Add(_cursor);

            try
            {
                // encapsulate all execution to catch any error
                return(new BsonDataReader(RunQuery(), _collection));
            }
            catch
            {
                // if any error, rollback transaction
                transaction.Rollback();

                // remove cursor
                transaction.OpenCursors.Remove(_cursor);

                throw;
            }

            IEnumerable <BsonDocument> RunQuery()
            {
                var snapshot = transaction.CreateSnapshot(_query.ForUpdate ? LockMode.Write : LockMode.Read, _collection, false);

                // no collection, no documents
                if (snapshot.CollectionPage == null && _source == null)
                {
                    // if query use Source (*) need runs with empty data source
                    if (_query.Select.UseSource)
                    {
                        yield return(_query.Select.ExecuteScalar(_pragmas.Collation).AsDocument);
                    }

                    transaction.OpenCursors.Remove(_cursor);

                    if (transaction.OpenCursors.Count == 0 && transaction.ExplicitTransaction == false)
                    {
                        transaction.Commit();
                    }

                    yield break;
                }

                // execute optimization before run query (will fill missing _query properties instance)
                var optimizer = new QueryOptimization(snapshot, _query, _source, _pragmas.Collation);

                var queryPlan = optimizer.ProcessQuery();

                // if execution is just to get explan plan, return as single document result
                if (executionPlan)
                {
                    yield return(queryPlan.GetExecutionPlan());

                    transaction.OpenCursors.Remove(_cursor);

                    if (transaction.OpenCursors.Count == 0 && transaction.ExplicitTransaction == false)
                    {
                        transaction.Commit();
                    }

                    yield break;
                }

                // get node list from query - distinct by dataBlock (avoid duplicate)
                var nodes = queryPlan.Index.Run(snapshot.CollectionPage, new IndexService(snapshot, _pragmas.Collation));

                // get current query pipe: normal or groupby pipe
                var pipe = queryPlan.GetPipe(transaction, snapshot, _sortDisk, _pragmas);

                try
                {
                    // start cursor elapsed timer
                    _cursor.Elapsed.Start();

                    // call safepoint just before return each document
                    foreach (var doc in pipe.Pipe(nodes, queryPlan))
                    {
                        _cursor.Fetched++;
                        _cursor.Elapsed.Stop();

                        yield return(doc);

                        _cursor.Elapsed.Start();
                    }
                }
                finally
                {
                    // stop cursor elapsed
                    _cursor.Elapsed.Stop();

                    transaction.OpenCursors.Remove(_cursor);

                    if (transaction.OpenCursors.Count == 0 && transaction.ExplicitTransaction == false)
                    {
                        transaction.Commit();
                    }
                }
            };
        }
Пример #3
0
        /// <summary>
        /// Run query definition into engine. Execute optimization to get query planner
        /// </summary>
        internal BsonDataReader ExecuteQuery(bool executionPlan)
        {
            // get current transaction (if contains a explicit transaction) or a query-only transaction
            var transaction = _monitor.GetTransaction(true, true, out var isNew);

            transaction.OpenCursors.Add(_cursor);

            // return new BsonDataReader with IEnumerable source
            return(new BsonDataReader(RunQuery(), _collection));

            IEnumerable <BsonDocument> RunQuery()
            {
                try
                {
                    var snapshot = transaction.CreateSnapshot(_query.ForUpdate ? LockMode.Write : LockMode.Read, _collection, false);

                    // no collection, no documents
                    if (snapshot.CollectionPage == null && _source == null)
                    {
                        // if query use Source (*) need runs with empty data source
                        if (_query.Select.UseSource)
                        {
                            yield return(_query.Select.ExecuteScalar(_pragmas.Collation).AsDocument);
                        }
                        yield break;
                    }

                    // execute optimization before run query (will fill missing _query properties instance)
                    var optimizer = new QueryOptimization(snapshot, _query, _source, _pragmas.Collation);

                    var queryPlan = optimizer.ProcessQuery();

                    // if execution is just to get explan plan, return as single document result
                    if (executionPlan)
                    {
                        yield return(queryPlan.GetExecutionPlan());

                        yield break;
                    }

                    // get node list from query - distinct by dataBlock (avoid duplicate)
                    var nodes = queryPlan.Index.Run(snapshot.CollectionPage, new IndexService(snapshot, _pragmas.Collation));

                    // get current query pipe: normal or groupby pipe
                    var pipe = queryPlan.GetPipe(transaction, snapshot, _sortDisk, _pragmas);

                    try
                    {
                        // start cursor elapsed timer
                        _cursor.Elapsed.Start();

                        // call safepoint just before return each document
                        foreach (var doc in pipe.Pipe(nodes, queryPlan))
                        {
                            _cursor.Fetched++;
                            _cursor.Elapsed.Stop();

                            yield return(doc);

                            if (transaction.State != TransactionState.Active)
                            {
                                throw new LiteException(0, $"There is no more active transaction for this cursor: {_cursor.Query.ToSQL(_cursor.Collection)}");
                            }

                            _cursor.Elapsed.Start();
                        }
                    }
                    finally
                    {
                        // stop cursor elapsed
                        _cursor.Elapsed.Stop();
                    }
                }
                finally
                {
                    transaction.OpenCursors.Remove(_cursor);

                    if (isNew)
                    {
                        _monitor.ReleaseTransaction(transaction);
                    }
                }
            };
        }