Ejemplo n.º 1
0
        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);
            }
        }