private void StartProduction( RequestExecutionContext context, RequestExecutionBuffer buffer, out IDriverDataEnumerator sourceEnumerator) { ReadRequest(context); context.AttachContainerDescriptor(m_containerDescriptor); if (!context.CacheInfo.HaveParsingResults) { lock (context.CacheInfo) { context.CacheInfo.CheckIsError(); if (!context.CacheInfo.HaveParsingResults) { try { ParseRequest(context.Request, context.RequestBulk, context.CacheInfo.ParsedRequest, context.CancellationTokenSource.Token); CompileClauses(context.ContainerDescriptor, context.CacheInfo); Thread.MemoryBarrier(); context.CacheInfo.HaveParsingResults = true; } catch (Exception e) { // make sure that partially complete results do not become visible context.CacheInfo.IsError(e); throw; } } } } context.CacheInfo.WriteParsingResults(context.ParsedRequest); if (context.ParsedRequest.SpecialCommand.IsSpecialCommand) { sourceEnumerator = null; ExecuteSpecialCommandStatement(context, buffer); return; } // structure of output buffer depends on which fields client is asking for // therefore, we re-create and re-attach a driver output buffer for every request context.AttachDriverOutputBufferAndInputParameters( QueryParser.CreateDriverRowDataBuffer(context.ParsedRequest.BaseDataset.BaseFields), context.ParsedRequest); // this enumerator will yield our own driverOutputBuffer for every source record // e.g. the very same context.DriverOutputBuffer is going to be yielded N times from this enumerator if (context.ParsedRequest.StatementType == StatementType.Insert) { if (context.ParsedRequest.IsBulk) { sourceEnumerator = CreateInputDataEnumerator(context); //m_storageDriver.AllocateCapacityForDocumentType(context.ParsedRequest.TargetEntity.DocumentType, context.RequestBulk.InputItemsCount); } else { sourceEnumerator = CreatePseudoEnumeratorForInsertValues(context); } } else { if (context.ParsedRequest.IsBulk) { // for SELECT and DELETE, we only use PK values from the input enumerator // for UPDATE, we use both PK values and other field values from input enumerator context.AttachInputDataEnumerator(CreateInputDataEnumerator(context)); } // driver returns set of rows related to given set of PK values // for a bulk request, sourceEnumerator will yield exactly one item for each item in input enumerator sourceEnumerator = m_storageDriver.GetData(context); } switch (context.ParsedRequest.StatementType) { case StatementType.Select: { context.AttachResponseHeaders(CreateResponseSchemeForSelect(context)); context.PrepareBuffersForSelect(); context.ResponseHeaders.RecordsAffected = 0; } break; case StatementType.Update: { context.AttachResponseHeaders(new DataResponse(0, "Update successful")); context.PrepareBuffersForUpdate(); ExecuteInsertUpdateStatement(context, buffer, sourceEnumerator, DriverChangeType.Update); context.ResponseHeaders.RecordsAffected = context.RecordsAffected; } break; case StatementType.Delete: { context.AttachResponseHeaders(new DataResponse(0, "Delete successful")); context.PrepareBuffersForDelete(); ExecuteDeleteStatement(context, buffer, sourceEnumerator); context.ResponseHeaders.RecordsAffected = context.RecordsAffected; } break; case StatementType.Insert: { context.AttachResponseHeaders(new DataResponse(0, "Insert successful")); context.PrepareChangeBufferForInsert(); ExecuteInsertUpdateStatement(context, buffer, sourceEnumerator, DriverChangeType.Insert); context.ResponseHeaders.RecordsAffected = context.RecordsAffected; } break; default: throw new Exception("Invalid statement type: " + context.ParsedRequest.StatementType); } }