public ParsedRequest(bool forCache)
        {
            Select         = SelectStatementData.Create();
            BaseDataset    = BaseDatasetData.Create();
            Modify         = InsertUpdateDeleteStatementData.Create();
            BulkInput      = BulkInputData.Create();
            Params         = ParametersData.Create();
            SpecialCommand = SpecialCommandData.Create();

            Bulk = forCache ? null : new BufferedReaderStream(84980);
        }
        /// <summary>
        /// RequestProcessingManager's (RPM) <see cref="WriteTo"/> works in parallel with <see cref="DataEngine.ProducerThreadMethod"/>.
        /// RPM supplies empty buffers to be filled with data into <see cref="RequestExecutionContext.BuffersRing"/> and consumes them on the other end.
        /// The data ring has very limited number of buffers.
        /// RPM is limited by network throughput and Producer's speed.
        /// Producer is limited by underlying storage driver, local processing speed and RPM's consumption of complete buffers.
        /// The difference between the two: RPM <see cref="WriteTo"/> is scheduled for execution by service infrastructure (WCF),
        /// whereas <see cref="DataEngine.ProducerThreadMethod"/> is scheduled by RPM itself, when it invokes <see cref="IDataEngine.BeginExecution"/>.
        /// </summary>
        public void WriteTo(Stream output)
        {
            // We will not report to client any unhandled errors from producer thread.
            // As of our local errors, we can only send them to client BEFORE the first block of data is streamed out.
            var canReportLocalErrors = true;

            try
            {
                using (var binaryWriter = new BinaryWriter(output, Encoding.UTF8, true))
                {
                    // rotate through the buffers, flush them to output until producer stops
                    var cancellation      = m_executionContext.CancellationTokenSource.Token;
                    var buffersRing       = m_executionContext.BuffersRing;
                    var lastCompletedTask = buffersRing.TakeCompletedTask(cancellation);
                    while (lastCompletedTask != null)
                    {
                        // no more reporting of local errors after first block has been generated
                        // note that this block may itself contain error information, but this is unrelated
                        canReportLocalErrors = false;

                        var stream  = lastCompletedTask.Stream;
                        var toWrite = checked ((int)stream.Length);
                        if (toWrite == 0)
                        {
                            break;
                        }

                        // write block
                        var buffer = stream.GetBuffer();
                        BufferedReaderStream.WriteBlock(binaryWriter, toWrite, buffer);

                        ReportStats(toWrite, lastCompletedTask.RowsOutput);

                        // this task might have produced error information instead of real data
                        // or it might have finished producing rows
                        // in both cases, break further processing
                        if (lastCompletedTask.IsFailed || lastCompletedTask.RowsOutput == 0)
                        {
                            break;
                        }

                        // return buffer to the ring
                        buffersRing.AddTaskForProcessing(lastCompletedTask, cancellation);
                        // take next one
                        lastCompletedTask = buffersRing.TakeCompletedTask(cancellation);
                    }

                    BufferedReaderStream.WriteStreamEndMarker(binaryWriter);

                    // no more data in the input sequence, or just have to stop producing
                    buffersRing.CompleteAddingTasksForProcessing();
                }
            }
            catch (Exception e)
            {
                m_executionContext.Cancel(e);

                if (canReportLocalErrors)
                {
                    using (var errorWriter = new PqlErrorDataWriter(1, m_executionContext.LastError, true))
                    {
                        errorWriter.WriteTo(output);
                    }
                }

                if (!(e is OperationCanceledException))
                {
                    throw;
                }
            }
        }