void ExSequenceTcb::advanceReturnHistoryRow() { if (currentRetOLAPBuffer_ == NULL) //initially currentRetOLAPBuffer_ is null { ex_assert(firstOLAPBuffer_ !=NULL,"ExSequenceTcb::advanceReturnHistoryRow() - firstOLAPBuffer is a NULL pointer"); currentRetOLAPBuffer_ = firstOLAPBuffer_; ex_assert(currentRetHistRowPtr_ == NULL,"ExSequenceTcb::advanceReturnHistoryRow() - currentRetHistRowPtr_ is not a NULL pointer"); currentRetHistRowPtr_ = currentRetOLAPBuffer_->getFirstRow(); currentRetHistRowInOLAPBuffer_ = 0; return; } currentRetHistRowInOLAPBuffer_ ++; if ( currentRetHistRowInOLAPBuffer_ == maxRowsInOLAPBuffer_ ) { // reached end of this buffer currentRetHistRowInOLAPBuffer_ = 0; if ( currentRetOLAPBuffer_->getNext() == NULL ) { //last buffer currentRetOLAPBuffer_ = firstOLAPBuffer_; currentRetHistRowPtr_ = currentRetOLAPBuffer_->getFirstRow(); } else { currentRetOLAPBuffer_ = currentRetOLAPBuffer_->getNext(); currentRetHistRowPtr_ = currentRetOLAPBuffer_->getFirstRow(); } } else { currentRetHistRowPtr_ = currentRetHistRowPtr_ + recLen(); } };
NABoolean ExSequenceTcb::advanceHistoryRow(NABoolean checkMemoryPressure) { histRowsToReturn_++; if (currentOLAPBuffer_ == NULL) { currentOLAPBuffer_ = firstOLAPBuffer_; ex_assert (currentHistRowPtr_ == NULL,"ExSequenceTcb::advanceHistoryRow() - currentHistRowPtr_ is not a NULL pointer"); currentHistRowPtr_ = currentOLAPBuffer_->getFirstRow() ; currentHistRowInOLAPBuffer_=0; } else { currentHistRowInOLAPBuffer_++; if ( currentHistRowInOLAPBuffer_ == maxRowsInOLAPBuffer_ ) { // reached end of this buffer currentHistRowInOLAPBuffer_ = 0; if ( currentOLAPBuffer_->getNext() == NULL ) { //last buffer if ( canAllocateOLAPBuffer() && ! isOverflowStarted() && // once overflowing - no more new buffers addNewOLAPBuffer(checkMemoryPressure) ) { currentOLAPBuffer_ = lastOLAPBuffer_; currentHistRowPtr_ = currentOLAPBuffer_->getFirstRow(); } else { currentOLAPBuffer_ = firstOLAPBuffer_; currentHistRowPtr_ = currentOLAPBuffer_->getFirstRow(); return TRUE; // no memory -- start overflow } } else { currentOLAPBuffer_ = currentOLAPBuffer_->getNext(); currentHistRowPtr_ = currentOLAPBuffer_->getFirstRow(); } } else { currentHistRowPtr_ = currentHistRowPtr_ + recLen(); } } if (numberHistoryRows_ < maxNumberHistoryRows_) { numberHistoryRows_++; } return FALSE; };
// // Constructor for sort_grby_tcb // ex_sort_grby_tcb::ex_sort_grby_tcb(const ex_sort_grby_tdb & sort_grby_tdb, const ex_tcb & child_tcb, // child queue pair ex_globals * glob ) : ex_tcb( sort_grby_tdb, 1, glob), pool_(NULL) { Space * space = (glob ? glob->getSpace() : 0); CollHeap * heap = (glob ? glob->getDefaultHeap() : 0); childTcb_ = &child_tcb; // Allocate the buffer pool #pragma nowarn(1506) // warning elimination pool_ = new(space) ExSimpleSQLBuffer(sort_grby_tdb.numBuffers_, sort_grby_tdb.bufferSize_, recLen(), space); #pragma warn(1506) // warning elimination // get the child queue pair qchild_ = child_tcb.getParentQueue(); // Allocate the queue to communicate with parent allocateParentQueues(qparent_); // Intialize processedInputs_ to the next request to process processedInputs_ = qparent_.down->getTailIndex(); // allocate work atp workAtp_ = allocateAtp(sort_grby_tdb.criDescUp_,getSpace()); // fixup aggr expression if (aggrExpr()) (void) aggrExpr()->fixup(0, getExpressionMode(), this, space, heap, glob->computeSpace()); // fixup move expression if (moveExpr()) (void) moveExpr()->fixup(0, getExpressionMode(), this, space, heap, glob->computeSpace()); // fixup grby expression if (grbyExpr()) (void) grbyExpr()->fixup(0, getExpressionMode(), this, space, heap, glob->computeSpace()); // fixup having expression if (havingExpr()) (void) havingExpr()->fixup(0, getExpressionMode(), this, space, heap, glob->computeSpace()); }
// work - doit... // // short ExSequenceTcb::work() { // If there are no parent requests on the queue, then there cannot // be anything to do here. // if (qparent_.down->isEmpty()) return WORK_OK; ex_queue_entry * pentry_down; ExSequencePrivateState * pstate; ex_queue::down_request request; // Take any new parent requests and pass them on to the child as long // as the child's queue is not full. processedInputs_ maintains the // Queue index of the last request that was passed on. // for(queue_index tail = qparent_.down->getTailIndex(); (processedInputs_ != tail) && (!qchild_.down->isFull()); processedInputs_++ ) { pentry_down = qparent_.down->getQueueEntry(processedInputs_); pstate = (ExSequencePrivateState*) pentry_down->pstate; request = pentry_down->downState.request; // If the request has already been cancelled don't pass it to the // child. Instead, just mark the request as done. This will trigger // a EOD reply when this request gets worked on. // if (request == ex_queue::GET_NOMORE) { // LCOV_EXCL_START pstate->step_ = ExSeq_DONE; // LCOV_EXCL_STOP } else { pstate->step_ = ExSeq_WORKING_READ; // Pass the request to the child // ex_queue_entry * centry = qchild_.down->getTailEntry(); centry->downState.request = ex_queue::GET_ALL; centry->downState.requestValue = 11; centry->downState.parentIndex = processedInputs_; centry->passAtp(pentry_down); qchild_.down->insert(); } } // end for processedInputs_ pentry_down = qparent_.down->getHeadEntry(); pstate = (ExSequencePrivateState*) pentry_down->pstate; request = pentry_down->downState.request; // Take any child replies and process them. Return the processed // rows as long the parent queue has room. // while (1) { // If we have satisfied the parent request (or it was cancelled), // then stop processing rows, cancel any outstanding child // requests, and set this request to the CANCELLED state. // if ((pstate->step_ == ExSeq_WORKING_READ) || (pstate->step_ == ExSeq_WORKING_RETURN)) { if ((request == ex_queue::GET_NOMORE) || ((request == ex_queue::GET_N) && (pentry_down->downState.requestValue <= (Lng32)pstate->matchCount_))) { qchild_.down->cancelRequestWithParentIndex (qparent_.down->getHeadIndex()); pstate->step_ = ExSeq_CANCELLED; } } switch (pstate->step_) { // ExSeq_CANCELLED // // Transition to this state from ... // 1. ExSeq_Error - After the error has been processed. // 2. ExSeq_Working - If enough rows have been returned. // 3. ExSeq_Working - If the request was cancelled. // // Remain in this state until .. // 1. All rows from the child including EOD are consumed // // Transition from this state to ... // 1. ExSeq_DONE - In all cases. // case ExSeq_CANCELLED: { // There are no extra rows to process from the child yet, // so try again later. // if (qchild_.up->isEmpty()) { return WORK_OK; } ex_queue_entry * centry = qchild_.up->getHeadEntry(); ex_queue::up_status child_status = centry->upState.status; // If this is the EOD, transition to the ExSeq_DONE state. // if (child_status == ex_queue::Q_NO_DATA) pstate->step_ = ExSeq_DONE; // Discard the child row. qchild_.up->removeHead(); break; } // ExSeq_ERROR // // Transition to this state from ... // 1. ExSeq_WORKING_READ - a child reply with the type SQLERROR. // 2. ExSeq_WORKING_RETURN // 3. ExSeq_OVERFLOW_READ // 4. ExSeq_OVERFLOW_WRITE // Remain in this state until .. // 1. The error row has been returned to the parent. // // Transition from this state to ... // 1. ExSeq_CANCELLED - In all cases. // case ExSeq_ERROR: { // If there is no room in the parent queue for the reply, // try again later. // if (qparent_.up->isFull()) // LCOV_EXCL_START return WORK_OK; // LCOV_EXCL_STOP ex_queue_entry *pentry_up = qparent_.up->getTailEntry(); // Cancel the child request - there must be a child request in // progress to get to the ExSeq_ERROR state. // qchild_.down->cancelRequestWithParentIndex (qparent_.down->getHeadIndex()); // Construct and return the error row. // if (workAtp_->getDiagsArea()) { ComDiagsArea * da = workAtp_->getDiagsArea(); pentry_up->setDiagsArea(da); da->incrRefCount(); workAtp_->setDiagsArea(0); } pentry_up->upState.status = ex_queue::Q_SQLERROR; pentry_up->upState.parentIndex = pentry_down->downState.parentIndex; pentry_up->upState.downIndex = qparent_.down->getHeadIndex(); pentry_up->upState.setMatchNo(pstate->matchCount_); qparent_.up->insert(); // Transition to the ExSeq_CANCELLED state. // pstate->step_ = ExSeq_CANCELLED; break; } // ExSeq_WORKING_READ // // Transition to this state from ... // 1. ExSeq_EMPTY - If a request is started. // 2. ExSeq_WORKING_RETURN - // 3. ExSeq_OVERFLOW_WRITE - // Remain in this state until ... // 1. All child replies including EOD have been processed. // 2. A SQLERROR row is received. // 3. Enough rows have been returned. // 4. The request is cancelled. // 5. End of partition is reached // Transition from this state to ... // 2. ExSeq_ERROR - If an SQLERROR rows is received. // 3. ExSeq_CANCELLED - If the request is cancelled. // 4. ExSeq_WORKING_RETURN // 5. ExSeq_OVERFLOW_WRITE - case ExSeq_WORKING_READ: { if(!isUnboundedFollowing() && isHistoryFull()) { pstate->step_ = ExSeq_WORKING_RETURN; break; } // If there are no replies, try again later. // if (qchild_.up->isEmpty()) return WORK_OK; ex_queue_entry * centry = qchild_.up->getHeadEntry(); switch (centry->upState.status) { // A data row from the child. // case ex_queue::Q_OK_MMORE: { tupp_descriptor histTupp; workAtp_->copyAtp(pentry_down->getAtp()); workAtp_->getTupp(myTdb().tuppIndex_) = &histTupp; if ( checkPartitionChangeExpr() && currentHistRowPtr_) { workAtp_->getTupp (myTdb().tuppIndex_).setDataPointer(currentHistRowPtr_); // Check whether the partition changed ex_expr::exp_return_type retCode = checkPartitionChangeExpr()->eval(workAtp_, centry->getAtp()); if (retCode == ex_expr::EXPR_ERROR) { // LCOV_EXCL_START updateDiagsArea(centry); pstate->step_ = ExSeq_ERROR; break; // LCOV_EXCL_STOP } if ( retCode == ex_expr::EXPR_FALSE) { setPartitionEnd(TRUE); pstate->step_ = ExSeq_END_OF_PARTITION; break; } } if (isUnboundedFollowing() ) { if (OLAPBuffersFlushed_) { OLAPBuffersFlushed_ = FALSE;// current row is the first one in first buffer already } else { NABoolean noMemory = advanceHistoryRow( TRUE /* checkMemoryPressure */); if (noMemory) { pstate->step_ = ExSeq_OVERFLOW_WRITE; cluster_->nextBufferToFlush_ = firstOLAPBuffer_; cluster_->afterLastBufferToFlush_ = NULL;//flush them all // If it is the first overflow, for this partition if ( ! memoryPressureDetected_ ) { memoryPressureDetected_ = TRUE; } // memory pressure detected break; } } } else { advanceHistoryRow(); } workAtp_->getTupp (myTdb().tuppIndex_).setDataPointer(currentHistRowPtr_); ex_expr::exp_return_type retCode = ex_expr::EXPR_OK; // Apply the read phase sequence function expression to compute // the values of the sequence functions. if (sequenceExpr()) { retCode = sequenceExpr()->eval(workAtp_, centry->getAtp()); if (retCode == ex_expr::EXPR_ERROR) { updateDiagsArea(centry); pstate->step_ = ExSeq_ERROR; break; } } // merge the child's diags area into the work atp updateDiagsArea(centry); qchild_.up->removeHead(); break; } // The EOD from the child. Transition to ExSeq_DONE. // case ex_queue::Q_NO_DATA: { setPartitionEnd(TRUE); if (isHistoryEmpty()) { pstate->step_ = ExSeq_DONE; qchild_.up->removeHead(); } else { pstate->step_ = ExSeq_END_OF_PARTITION; } } break; // An SQLERROR from the child. Transition to ExSeq_ERROR. // case ex_queue::Q_SQLERROR: updateDiagsArea(centry); pstate->step_ = ExSeq_ERROR; break; } } break; // ExSeq_WORKING_RETURN // // Transition to this state from ... // 1. ExSeq_WORKING_READ - // 2. ExSeq_OVERFLOW_READ - // 3. ExSeq_END_OF_PARTITION - // Remain in this state until ... // 1. All rows are returned. // 2. A SQLERROR row is received. // 3. Enough rows have been returned. // // Transition from this state to ... // 1. ExSeq_DONE - If all the child rows including EOD have // been processed. // 2. ExSeq_ERROR - If an SQLERROR rows is received. // 3. ExSeq_CANCELLED - If enough rows have been returned. // 4. ExSeq_CANCELLED - If the request is cancelled. // 5. ExSeq_WORKING_RETURN // 6. ExSeq_DONE // 7. ExSeq_OVERFLOW_READ case ExSeq_WORKING_RETURN: { // If there is not room in the parent Queue for the reply, // try again later. // if (qparent_.up->isFull()) return WORK_OK; if(isHistoryEmpty()) { ex_queue_entry * centry = NULL; if(!qchild_.up->isEmpty()) { centry = qchild_.up->getHeadEntry(); } if(centry && (centry->upState.status == ex_queue::Q_NO_DATA)) { pstate->step_ = ExSeq_DONE; qchild_.up->removeHead(); } else { pstate->step_ = ExSeq_WORKING_READ; if (getPartitionEnd()) { initializeHistory(); } } break; } if(!canReturnRows() && !getPartitionEnd() && !isUnboundedFollowing() && !isOverflowStarted()) // redundant? because not unbounded ... { pstate->step_ = ExSeq_WORKING_READ; break; } ex_queue_entry * pentry_up = qparent_.up->getTailEntry(); pentry_up->copyAtp(pentry_down); // Try to allocate a tupp. // if (pool_->get_free_tuple(pentry_up->getTupp(myTdb().tuppIndex_), recLen())) // LCOV_EXCL_START return WORK_POOL_BLOCKED; // LCOV_EXCL_STOP char *tuppData = pentry_up->getTupp (myTdb().tuppIndex_).getDataPointer(); advanceReturnHistoryRow(); char *histData = currentRetHistRowPtr_; pentry_up->getTupp (myTdb().tuppIndex_).setDataPointer(histData); ex_expr::exp_return_type retCode = ex_expr::EXPR_OK; // Apply the return phase expression if(returnExpr()) { retCode = returnExpr()->eval(pentry_up->getAtp(),workAtp_); if (retCode == ex_expr::EXPR_ERROR) { // LCOV_EXCL_START pstate->step_ = ExSeq_ERROR; break; // LCOV_EXCL_STOP } } retCode = ex_expr::EXPR_OK; //Apply post predicate expression if (postPred()) { retCode = postPred()->eval(pentry_up->getAtp(),pentry_up->getAtp()); if (retCode == ex_expr::EXPR_ERROR) { // LCOV_EXCL_START pstate->step_ = ExSeq_ERROR; break; // LCOV_EXCL_STOP } } //pentry_up->getAtp()->display("return eval result", myTdb().getCriDescUp()); // // Case-10-030724-7963: we are done pointing the tupp at the // history buffer, so point it back to the SQL buffer. // pentry_up->getTupp (myTdb().tuppIndex_).setDataPointer(tuppData); switch(retCode) { case ex_expr::EXPR_OK: case ex_expr::EXPR_TRUE: case ex_expr::EXPR_NULL: // Copy the row that was computed in the history buffer, // to the space previously allocated in the SQL buffer. str_cpy_all(tuppData, histData, recLen()); // Return the processed row. // // Finalize the queue entry, then insert it // pentry_up->upState.status = ex_queue::Q_OK_MMORE; pentry_up->upState.parentIndex = pentry_down->downState.parentIndex; pentry_up->upState.downIndex = qparent_.down->getHeadIndex(); pstate->matchCount_++; pentry_up->upState.setMatchNo(pstate->matchCount_); qparent_.up->insert(); break; // If the selection predicate returns FALSE, // do not return the child row. // case ex_expr::EXPR_FALSE: break; // If the selection predicate returns an ERROR, // go to the error processing state. // case ex_expr::EXPR_ERROR: // LCOV_EXCL_START pstate->step_ = ExSeq_ERROR; // LCOV_EXCL_STOP break; } // MV -- // Now, if there are no errors so far, evaluate the // cancel expression if ((pstate->step_ != ExSeq_ERROR) && cancelExpr()) { // Temporarily point the tupp to the tail of the // history buffer for evaluating the // expressions. // pentry_up->getTupp (myTdb().tuppIndex_).setDataPointer(histData); retCode = cancelExpr()->eval(pentry_up->getAtp(),pentry_up->getAtp()); // We are done pointing the tupp at the history // buffer, so point it back to the SQL buffer. // pentry_up->getTupp (myTdb().tuppIndex_).setDataPointer(tuppData); if (retCode == ex_expr::EXPR_TRUE) { qchild_.down->cancelRequestWithParentIndex (qparent_.down->getHeadIndex()); pstate->step_ = ExSeq_CANCELLED; } } updateHistRowsToReturn(); if ( isOverflowStarted() ) { numberOfRowsReturnedBeforeReadOF_ ++; if (numberOfRowsReturnedBeforeReadOF_ == maxNumberOfRowsReturnedBeforeReadOF_) { firstOLAPBufferFromOF_ = currentRetOLAPBuffer_->getNext(); if (firstOLAPBufferFromOF_ == NULL) { firstOLAPBufferFromOF_ = firstOLAPBuffer_; } for( Int32 i = 0; i < numberOfWinOLAPBuffers_; i++) { firstOLAPBufferFromOF_ = firstOLAPBufferFromOF_->getNext(); if (firstOLAPBufferFromOF_ == NULL) { firstOLAPBufferFromOF_ = firstOLAPBuffer_; } } numberOfOLAPBuffersFromOF_ = numberOfOLAPBuffers_ - numberOfWinOLAPBuffers_; cluster_->nextBufferToRead_ = firstOLAPBufferFromOF_; HashBuffer * afterLast = firstOLAPBufferFromOF_; // last buffer to read into is the current buffer - maybe ? for ( Lng32 bufcount = numberOfOLAPBuffersFromOF_ ; bufcount ; bufcount-- ) { afterLast = afterLast->getNext() ; // Don't cycle back if bufcount == 1 because the logic in // Cluster::read relies on the NULL ptr to stop reading if ( bufcount > 1 && ! afterLast ) afterLast = firstOLAPBuffer_; // cycle back } // The last buffer to read to is always the current buffer // ex_assert ( afterLast == currentRetOLAPBuffer_->getNext(), // "Miscalculated the last buffer to read into"); cluster_->afterLastBufferToRead_ = afterLast; pstate->step_ = ExSeq_OVERFLOW_READ; } } } break; // ExSeq_END_OF_PARTITION // // Transition to this state from ... // 1. ExSeq_WORKING_READ - // Transition from this state to ... // 1. ExSeq_OVERFLOW_WRITE // 2. ExSeq_WORKING_RETURN case ExSeq_END_OF_PARTITION: { setPartitionEnd(TRUE); if (lastRow_ && isUnboundedFollowing()) { ex_assert(currentHistRowPtr_ != NULL, "ExSequenceTcb::work() - currentHistRowPtr_ is a NULL pointer"); str_cpy_all(lastRow_, currentHistRowPtr_, recLen()); } if ( isOverflowStarted() ) // we are overflowing { cluster_->nextBufferToFlush_ = firstOLAPBuffer_; // do not flush beyond the current buffer cluster_->afterLastBufferToFlush_ = currentOLAPBuffer_->getNext(); pstate->step_ = ExSeq_OVERFLOW_WRITE; } else { pstate->step_ = ExSeq_WORKING_RETURN; } } break; // ExSeq_OVERFLOW_WRITE // // Transition to this state from ... // 1. ExSeq_WORKING_READ - // 2. ExSeq_END_OF_PARTITION - // Remain in this state until ... // 1. OLAPbuffers are written to oveflow space. // 2. An error occurs // // Transition from this state to ... // 1. ExSeq_OVERFLOW_READ // 2. ExSeq_ERROR - If an error occurs case ExSeq_OVERFLOW_WRITE: { if (!overflowEnabled_) { // LCOV_EXCL_START // used for debugging when CmpCommon::getDefault(EXE_BMO_DISABLE_OVERFLOW)is set to off ; updateDiagsArea(EXE_OLAP_OVERFLOW_NOT_SUPPORTED); pstate->step_ = ExSeq_ERROR; break; // LCOV_EXCL_STOP } ex_assert(isUnboundedFollowing(),""); if ( ! cluster_->flush(&rc_) ) { // flush the buffers // LCOV_EXCL_START // if no errors this code path is not visited if ( rc_ ) { // some error updateDiagsArea( rc_); pstate->step_ = ExSeq_ERROR; break; } // LCOV_EXCL_STOP // not all the buffers are completely flushed. An I/O is pending // LCOV_EXCL_START // maybe we cane remove in the future return WORK_OK; // LCOV_EXCL_STOP } // At this point -- all the buffers were completely flushed OLAPBuffersFlushed_ = TRUE; if (getPartitionEnd()) { firstOLAPBufferFromOF_ = firstOLAPBuffer_; numberOfOLAPBuffersFromOF_ = numberOfOLAPBuffers_; cluster_->nextBufferToRead_ = firstOLAPBufferFromOF_; // First time we read and fill all the buffers cluster_->afterLastBufferToRead_ = NULL; pstate->step_ = ExSeq_OVERFLOW_READ; } else { pstate->step_ = ExSeq_WORKING_READ; } } break; // ExSeq_OVERFLOW_READ // // Transition to this state from ... // 1. ExSeq_OVERFLOW_WRITE // 2. ExSeq_WORKING_RETURN // Remain in this state until ... // 1. OLAPbuffers are read from oveflow space. // 2. An error occurs // // Transition from this state to ... // 1. ExSeq_WORKING_RETURN // 2. ExSeq_ERROR - If an error occurs case ExSeq_OVERFLOW_READ: { assert(firstOLAPBufferFromOF_ && isUnboundedFollowing() ); if ( ! cluster_->read(&rc_) ) { // LCOV_EXCL_START if ( rc_ ) { // some error updateDiagsArea( rc_); pstate->step_ = ExSeq_ERROR; break; } // LCOV_EXCL_STOP // not all the buffers are completely read. An I/O is pending // LCOV_EXCL_START return WORK_OK; // LCOV_EXCL_STOP } numberOfRowsReturnedBeforeReadOF_ = 0; pstate->step_ = ExSeq_WORKING_RETURN; } break; // ExSeq_DONE // // Transition to the state from ... // 1. ExSeq_WORKING_RETURN - if all child rows have been processed. // 2. ExSeq_CANCELLED - if all child rows have been consumed. // 3. ExSeq_EMPTY - if the request was DOA. // // Remain in this state until ... // 1. The EOD is returned to the parent. // // Transition from this state to ... // 1. ExSeq_EMPTY - In all cases. // case ExSeq_DONE: { // If there is not any room in the parent's queue, // try again later. // if (qparent_.up->isFull()) // LCOV_EXCL_START return WORK_OK; // LCOV_EXCL_STOP ex_queue_entry * pentry_up = qparent_.up->getTailEntry(); pentry_up->upState.status = ex_queue::Q_NO_DATA; pentry_up->upState.parentIndex = pentry_down->downState.parentIndex; pentry_up->upState.downIndex = qparent_.down->getHeadIndex(); pentry_up->upState.setMatchNo(pstate->matchCount_); qparent_.down->removeHead(); qparent_.up->insert(); // Re-initialize pstate // pstate->step_ = ExSeq_EMPTY; pstate->matchCount_ = 0; workAtp_->release(); // Initialize the history buffer in preparation for the // next request. // initializeHistory(); // If there are no more requests, simply return. // if (qparent_.down->isEmpty()) return WORK_OK; // LCOV_EXCL_START // If we haven't given to our child the new head // index return and ask to be called again. // if (qparent_.down->getHeadIndex() == processedInputs_) return WORK_CALL_AGAIN; // Position at the new head of the request queue. // pentry_down = qparent_.down->getHeadEntry(); pstate = (ExSequencePrivateState*) pentry_down->pstate; request = pentry_down->downState.request; // LCOV_EXCL_STOP } break; } // switch pstate->step_ } // while }
void ExSequenceTcb::initializeHistory() { currentOLAPBuffer_ = NULL; currentHistRowInOLAPBuffer_ = 0; currentHistRowPtr_ = NULL; currentRetOLAPBuffer_ = NULL; currentRetHistRowInOLAPBuffer_ = 0; currentRetHistRowPtr_ = NULL; numberHistoryRows_ = 0; histRowsToReturn_ = 0; partitionEnd_ = FALSE; // allocate the minimum number of olap buffers if (firstOLAPBuffer_ == NULL) { for (Int32 i = 0 ; i < minNumberOfOLAPBuffers_; i++) { if ( ! addNewOLAPBuffer( FALSE /* No Memory Pressure Check */ ) ) // LCOV_EXCL_START ex_assert(0, "No memory for minimal OLAP window!"); // LCOV_EXCL_STOP } } else { if (!shrinkOLAPBufferList()) // LCOV_EXCL_START ex_assert(0,"initializeHistory-- can not shrink buffer list"); // LCOV_EXCL_STOP } // Initialize all the settings needed for unbounded following (and overflow) if ( isUnboundedFollowing() ) { //last row in partition if (lastRow_ == NULL) { lastRow_ = new(heap_) char[recLen()]; ex_assert( lastRow_ , "No memory available for OLAP Operator"); } // initialize parameters needed for overflow handling OLAPBuffersFlushed_ = FALSE; firstOLAPBufferFromOF_ = NULL; numberOfOLAPBuffersFromOF_ = 0; memoryPressureDetected_ = FALSE; numberOfRowsReturnedBeforeReadOF_ = 0; createCluster(); // Cluster needs to know the first buffer in the OLAP list of buffers // (Currently only used when reading buffers from overflow for // "bounded following", where Cluster::read() may need to jump back to // first buffer in the list.) cluster_->firstBufferInList_ = firstOLAPBuffer_ ; } // if ( isUnboundedFollowing() ) }