From: Ole John Aske Date: August 16 2011 1:43pm Subject: bzr push into mysql-5.1-telco-7.0-spj-scan-vs-scan branch (ole.john.aske:3534 to 3535) List-Archive: http://lists.mysql.com/commits/140655 Message-Id: <20110816134323.2E8D5218@fimafeng09.norway.sun.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 3535 Ole John Aske 2011-08-16 [merge] Merge modified: storage/ndb/src/ndbapi/NdbQueryOperation.cpp 3534 Ole John Aske 2011-08-16 [merge] Merge modified: mysql-test/r/group_by.result mysql-test/t/group_by.test sql/sql_select.cc storage/ndb/src/kernel/blocks/dbtux/DbtuxNode.cpp storage/ndb/src/kernel/vm/ndbd_malloc_impl.cpp storage/ndb/src/kernel/vm/ndbd_malloc_impl.hpp storage/ndb/src/ndbapi/NdbQueryOperation.cpp === modified file 'storage/ndb/src/ndbapi/NdbQueryOperation.cpp' --- a/storage/ndb/src/ndbapi/NdbQueryOperation.cpp 2011-08-16 13:33:13 +0000 +++ b/storage/ndb/src/ndbapi/NdbQueryOperation.cpp 2011-08-16 13:42:49 +0000 @@ -247,6 +247,16 @@ public: */ bool isEmpty() const; + /** + * This method is used for marking which streams belonging to this + * NdbRootFragment which has remaining batches for a sub scan + * instantiated from the current batch of its parent operation. + */ + void setRemainingSubScans(Uint32 nodeMask) + { + m_remainingScans = nodeMask; + } + /** Release resources after last row has been returned */ void postFetchRelease(); @@ -280,6 +290,12 @@ private: * TCKEYCONF message has been received */ bool m_confReceived; + /** + * A bitmask of operation id's for which we will receive more + * ResultSets in a NEXTREQ. + */ + Uint32 m_remainingScans; + /** * Used for implementing a hash map from root receiver ids to a * NdbRootFragment instance. m_idMapHead is the index of the first @@ -353,7 +369,7 @@ public: * Update whatever required before the appl. are allowed to navigate the result. * @return true if node and all its siblings have returned all rows. */ - bool prepareResultSet(); + bool prepareResultSet(Uint32 remainingScans); /** * Navigate within the current result batch to resp. first and next row. @@ -373,29 +389,23 @@ public: { return m_iterState == Iter_finished; } /** - * This method is - * used for marking a stream as holding the last batch of a sub scan. - * This means that it is the last batch of the scan that was instantiated - * from the current batch of its parent operation. - */ - void setSubScanCompletion(bool complete) - { - // Lookups should always be 'complete' - assert(complete || isScanResult()); - m_subScanComplete = complete; - } - - /** * This method - * returns true if this result stream holds the last batch of a sub scan + * returns true if this result stream holds the last batch of a sub scan. * This means that it is the last batch of the scan that was instantiated * from the current batch of its parent operation. */ - bool isSubScanComplete() const + bool isSubScanComplete(Uint32 remainingScans) const { - // Lookups should always be 'complete' - assert(m_subScanComplete || isScanResult()); - return m_subScanComplete; + /** + * Find the node number seen by the SPJ block. Since a unique index + * operation will have two distincts nodes in the tree used by the + * SPJ block, this number may be different from 'opNo'. + */ + const Uint32 internalOpNo = m_operation.getQueryOperationDef().getQueryOperationId(); + + const bool complete = !((remainingScans >> internalOpNo) & 1); + assert(complete || isScanResult()); // Lookups should always be 'complete' + return complete; } bool isScanQuery() const @@ -508,14 +518,6 @@ private: */ Uint16 m_currentRow; - /** - * This field is only used for result streams of scan operations. If set, - * it indicates that the stream is holding the last batch of a sub scan. - * This means that it is the last batch of the scan that was instantiated - * from the current batch of its parent operation. - */ - bool m_subScanComplete; - /** Max #rows which this stream may recieve in its TupleSet structures */ Uint32 m_maxRows; @@ -611,7 +613,6 @@ NdbResultStream::NdbResultStream(NdbQuer m_rowCount(0), m_iterState(Iter_notStarted), m_currentRow(tupleNotFound), - m_subScanComplete(true), m_maxRows(0), m_tupleSet(NULL) {}; @@ -827,10 +828,10 @@ NdbResultStream::execTRANSID_AI(const Ui * rows. */ bool -NdbResultStream::prepareResultSet() +NdbResultStream::prepareResultSet(Uint32 remainingScans) { - bool isComplete = isSubScanComplete(); //Childs with more rows - assert(isComplete || isScanResult()); //Lookups always 'complete' + bool isComplete = isSubScanComplete(remainingScans); //Childs with more rows + assert(isComplete || isScanResult()); //Lookups always 'complete' // Set correct #rows received in the NdbReceiver. getReceiver().m_result_rows = getRowCount(); @@ -866,7 +867,7 @@ NdbResultStream::prepareResultSet() { const NdbQueryOperationImpl& child = m_operation.getChildOperation(childNo); NdbResultStream& childStream = m_rootFrag.getResultStream(child); - const bool allSubScansComplete = childStream.prepareResultSet(); + const bool allSubScansComplete = childStream.prepareResultSet(remainingScans); Uint32 childId = child.getQueryOperationDef().getQueryOperationIx(); @@ -1035,6 +1036,7 @@ NdbRootFragment::NdbRootFragment(): m_resultStreams(NULL), m_outstandingResults(0), m_confReceived(false), + m_remainingScans(0), m_idMapHead(-1), m_idMapNext(-1) { @@ -1097,13 +1099,25 @@ void NdbRootFragment::reset() assert(m_fragNo!=voidFragNo); assert(m_outstandingResults == 0); assert(m_confReceived); + + for (unsigned opNo=0; opNogetNoOfOperations(); opNo++) + { + if (!m_resultStreams[opNo].isSubScanComplete(m_remainingScans)) + { + /** + * Reset m_resultStreams[] and all its descendants, since all these + * streams will get a new set of rows in the next batch. + */ + m_resultStreams[opNo].reset(); + } + } m_confReceived = false; } void NdbRootFragment::prepareResultSet() { NdbResultStream& rootStream = getResultStream(0); - rootStream.prepareResultSet(); + rootStream.prepareResultSet(m_remainingScans); /* Position at the first (sorted?) row available from this fragments. */ @@ -3004,21 +3018,6 @@ NdbQueryImpl::sendFetchMore(NdbRootFragm emptyFrag.reset(); - for (unsigned opNo=0; opNom_tcRef)); @@ -4798,6 +4797,7 @@ NdbQueryOperationImpl::execSCAN_TABCONF( return false; } rootFrag->setConfReceived(); + rootFrag->setRemainingSubScans(nodeMask); rootFrag->incrOutstandingResults(rowCount); // Handle for SCAN_NEXTREQ, RNIL -> EOF @@ -4810,31 +4810,6 @@ NdbQueryOperationImpl::execSCAN_TABCONF( << endl; } - const NdbQueryDefImpl& queryDef = m_queryImpl.getQueryDef(); - /* Mark each scan node to indicate if the current batch is the last in the - * current sub-scan or not. - */ - for (Uint32 opNo = 0; opNo < queryDef.getNoOfOperations(); opNo++) - { - const NdbQueryOperationImpl& op = m_queryImpl.getQueryOperation(opNo); - /** - * Find the node number seen by the SPJ block. Since a unique index - * operation will have two distincts nodes in the tree used by the - * SPJ block, this number may be different from 'opNo'. - */ - const Uint32 internalOpNo = op.getQueryOperationDef().getQueryOperationId(); - assert(internalOpNo >= opNo); - const bool complete = ((nodeMask >> internalOpNo) & 1) == 0; - - // Lookups should always be 'complete' - assert(complete || op.getQueryOperationDef().isScanOperation()); - rootFrag->getResultStream(opNo).setSubScanCompletion(complete); - } - // Check that nodeMask does not have more bits than we have operations. - assert(nodeMask >> - (1+queryDef.getQueryOperation(queryDef.getNoOfOperations() - 1) - .getQueryOperationId()) == 0); - bool ret = false; if (rootFrag->isFragBatchComplete()) { No bundle (reason: useless for push emails).