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; opNo<m_query->getNoOfOperations(); 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; opNo<m_countOperations; opNo++)
- {
- NdbResultStream& resultStream =
- emptyFrag.getResultStream(opNo);
-
- if (!resultStream.isSubScanComplete())
- {
- /**
- * Reset resultstream and all its descendants, since all these
- * streams will get a new set of rows in the next batch.
- */
- resultStream.reset();
- }
- }
-
Ndb& ndb = *getNdbTransaction().getNdb();
NdbApiSignal tSignal(&ndb);
tSignal.setSignal(GSN_SCAN_NEXTREQ, refToBlock(m_scanTransaction->m_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).
| Thread |
|---|
| • bzr push into mysql-5.1-telco-7.0-spj-scan-vs-scan branch(ole.john.aske:3534 to 3535) | Ole John Aske | 17 Aug |