From: Ole John Aske Date: February 11 2011 1:16pm Subject: bzr push into mysql-5.1-telco-7.0-spj-scan-vs-scan branch (ole.john.aske:3429 to 3431) List-Archive: http://lists.mysql.com/commits/131127 Message-Id: <20110211131658.770E5223@fimafeng09.norway.sun.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 3431 Ole John Aske 2011-02-11 SPJ-scan-scan: ::setInterpretedCode() as part of the NdbQueryDef instead of setting it as part of each instantiated NdbQuery. modified: sql/ha_ndbcluster.cc 3430 Ole John Aske 2011-02-11 Extend SPJ API with NdbQueryOptions::setInterpretedCode() which allows a filter condition to be defined as part of a NdbQueryDef. This filter will then be reused for all NdbQuery's instantiated from this NdbQueryDef - Usage of this feature will save the overhead of a seperate ::generate_scan_filter() for each instantiation of this NdbQueryDef. modified: storage/ndb/include/ndbapi/NdbInterpretedCode.hpp storage/ndb/include/ndbapi/NdbQueryBuilder.hpp storage/ndb/include/ndbapi/NdbQueryOperation.hpp storage/ndb/src/ndbapi/NdbQueryBuilder.cpp storage/ndb/src/ndbapi/NdbQueryBuilderImpl.hpp storage/ndb/src/ndbapi/NdbQueryOperation.cpp 3429 Ole John Aske 2011-02-10 spj-scan-scan: Fixed some more incorrect 'size' spec when using Bitmask. modified: storage/ndb/src/ndbapi/NdbQueryBuilder.cpp storage/ndb/src/ndbapi/NdbQueryBuilderImpl.hpp === modified file 'sql/ha_ndbcluster.cc' --- a/sql/ha_ndbcluster.cc 2011-02-09 14:59:39 +0000 +++ b/sql/ha_ndbcluster.cc 2011-02-11 13:16:37 +0000 @@ -486,6 +486,16 @@ ha_ndbcluster::make_pushed_join(ndb_push */ if (push_cnt == 0) { + NdbQueryOptions options; + if (m_cond) + { + NdbInterpretedCode code(m_table); + if (m_cond->generate_scan_filter(&code, NULL) != 0) + ERR_RETURN(code.getNdbError()); + + options.setInterpretedCode(code); + } + if (ndbcluster_is_lookup_operation(access_type)) { const KEY* const key= @@ -511,7 +521,7 @@ ha_ndbcluster::make_pushed_join(ndb_push DBUG_PRINT("info", ("Root operation is 'primary-key-lookup'")); DBUG_ASSERT(join_root->get_index_no() == static_cast(table->s->primary_key)); - query_op= builder->readTuple(m_table, root_key); + query_op= builder->readTuple(m_table, root_key, &options); } else { @@ -519,7 +529,7 @@ ha_ndbcluster::make_pushed_join(ndb_push const NdbDictionary::Index* const index = m_index[join_root->get_index_no()].unique_index; DBUG_ASSERT(index); - query_op= builder->readTuple(index, m_table, root_key); + query_op= builder->readTuple(index, m_table, root_key, &options); } } /** @@ -542,12 +552,12 @@ ha_ndbcluster::make_pushed_join(ndb_push // Bounds will be generated and supplied during execute query_op= - builder->scanIndex(m_index[join_root->get_index_no()].index, m_table); + builder->scanIndex(m_index[join_root->get_index_no()].index, m_table, 0, &options); } else if (access_type == AQP::AT_TABLE_SCAN) { DBUG_PRINT("info", ("Root operation is 'table scan'")); - query_op= builder->scanTable(m_table); + query_op= builder->scanTable(m_table, &options); } else { @@ -700,6 +710,14 @@ ha_ndbcluster::make_pushed_join(ndb_push DBUG_ASSERT(parent_op != NULL); options.setParent(parent_op); } + if (handler->m_cond) + { + NdbInterpretedCode code(table); + if (handler->m_cond->generate_scan_filter(&code, NULL) != 0) + ERR_RETURN(code.getNdbError()); + + options.setInterpretedCode(code); + } if (join_tab->get_access_type() == AQP::AT_ORDERED_INDEX_SCAN) { @@ -721,7 +739,6 @@ ha_ndbcluster::make_pushed_join(ndb_push query_op= builder->readTuple(index, table, linked_key, &options); } -// DBUG_ASSERT(query_op); if (unlikely(!query_op)) { const NdbError error = builder->getNdbError(); @@ -1019,7 +1036,6 @@ ha_ndbcluster::create_pushed_join(NdbQue ERR_RETURN(m_thd_ndb->trans->getNdbError()); // Bind to instantiated NdbQueryOperations. - // Append filters for for pushed conditions where available for (uint i= 0; i < m_pushed_join->get_operation_count(); i++) { const TABLE* const tab= m_pushed_join->get_table(i); @@ -1028,16 +1044,6 @@ ha_ndbcluster::create_pushed_join(NdbQue NdbQueryOperation* const op= query->getQueryOperation(i); handler->m_pushed_operation= op; - if (handler->m_cond) - { - NdbInterpretedCode code(handler->m_table); - if (handler->m_cond->generate_scan_filter(&code, NULL) != 0) - ERR_RETURN(code.getNdbError()); - - if (op->setInterpretedCode(code) != 0) - ERR_RETURN(query->getNdbError()); - } - // Bind to result buffers const NdbRecord* const resultRec= handler->m_ndb_record; int res= op->setResultRowRef( === modified file 'storage/ndb/include/ndbapi/NdbInterpretedCode.hpp' --- a/storage/ndb/include/ndbapi/NdbInterpretedCode.hpp 2011-02-08 15:13:13 +0000 +++ b/storage/ndb/include/ndbapi/NdbInterpretedCode.hpp 2011-02-11 13:12:09 +0000 @@ -544,6 +544,7 @@ private: friend class NdbOperation; friend class NdbScanOperation; friend class NdbQueryOperationImpl; + friend class NdbQueryOptionsImpl; static const Uint32 MaxReg= 8; static const Uint32 MaxLabels= 65535; === modified file 'storage/ndb/include/ndbapi/NdbQueryBuilder.hpp' --- a/storage/ndb/include/ndbapi/NdbQueryBuilder.hpp 2010-11-23 10:05:44 +0000 +++ b/storage/ndb/include/ndbapi/NdbQueryBuilder.hpp 2011-02-11 13:12:09 +0000 @@ -172,6 +172,26 @@ public: */ int setParent(const class NdbQueryOperationDef* parent); + /** + * Set the NdbInterpretedCode needed for defining a conditional filter + * (aka: predicate) for this operation. Might be used both on scan + * and lookup operations. + * + * Typically, one would create NdbScanFilter and NdbInterpretedCode objects + * on the stack, e.g.: + * NdbInterpretedCode code(table); + * NdbScanFilter filter(code); + * filter.begin(); + * filter.ge(0, 5U); // Check if column 1 is greater of equal to 5. + * filter.end(); + * queryOp->setInterpretedCode(code); + * + * @param code The interpreted code. This object is copied internally, + * meaning that 'code' may be destroyed as soon as this method returns. + * @return 0 if ok, -1 in case of error (call getNdbError() for details.) + */ + int setInterpretedCode(const class NdbInterpretedCode& code); + const NdbQueryOptionsImpl& getImpl() const; private: === modified file 'storage/ndb/include/ndbapi/NdbQueryOperation.hpp' --- a/storage/ndb/include/ndbapi/NdbQueryOperation.hpp 2010-11-23 10:05:44 +0000 +++ b/storage/ndb/include/ndbapi/NdbQueryOperation.hpp 2011-02-11 13:12:09 +0000 @@ -336,8 +336,9 @@ public: int setBatchSize(Uint32 batchSize); /** - * Set the NdbInterpretedCode needed for defining a scan filter for - * this operation. + * Set the NdbInterpretedCode needed for defining a conditional filter + * (aka: predicate) for this operation. Might be used both on scan + * and lookup operations. * * Typically, one would create NdbScanFilter and NdbInterpretedCode objects * on the stack, e.g.: @@ -346,9 +347,8 @@ public: * filter.begin(); * filter.ge(0, 5U); // Check if column 1 is greater of equal to 5. * filter.end(); - * scanOp->setInterpretedCode(code); + * queryOp->setInterpretedCode(code); * - * It is an error to call this method on a lookup operation. * @param code The interpreted code. This object is copied internally, * meaning that 'code' may be destroyed as soon as this method returns. * @return 0 if ok, -1 in case of error (call getNdbError() for details.) === modified file 'storage/ndb/src/ndbapi/NdbQueryBuilder.cpp' --- a/storage/ndb/src/ndbapi/NdbQueryBuilder.cpp 2011-02-10 11:54:23 +0000 +++ b/storage/ndb/src/ndbapi/NdbQueryBuilder.cpp 2011-02-11 13:12:09 +0000 @@ -29,6 +29,7 @@ #include "AttributeHeader.hpp" #include "NdbIndexScanOperation.hpp" #include "NdbOut.hpp" +#include "NdbInterpretedCode.hpp" /** * Implementation of all QueryBuilder objects are hidden from @@ -54,6 +55,7 @@ static const bool doPrintQueryTree = fal /* Various error codes that are not specific to NdbQuery. */ static const int Err_MemoryAlloc = 4000; +static const int Err_FinaliseNotCalled = 4519; static void setErrorCode(NdbQueryBuilderImpl* qb, int aErrorCode) @@ -474,6 +476,77 @@ NdbQueryOptions::setParent(const NdbQuer return 0; } +int +NdbQueryOptions::setInterpretedCode(const NdbInterpretedCode& code) +{ + if (m_pimpl==&defaultOptions) + { + m_pimpl = new NdbQueryOptionsImpl; + if (unlikely(m_pimpl==0)) + { + return Err_MemoryAlloc; + } + } + return m_pimpl->copyInterpretedCode(code); +} + + +NdbQueryOptionsImpl::~NdbQueryOptionsImpl() +{ + delete m_interpretedCode; +} + +NdbQueryOptionsImpl::NdbQueryOptionsImpl(const NdbQueryOptionsImpl& src) + : m_matchType(src.m_matchType), + m_scanOrder(src.m_scanOrder), + m_parent(src.m_parent), + m_interpretedCode(NULL) +{ + if (src.m_interpretedCode) + { + copyInterpretedCode(*src.m_interpretedCode); + } +} + +/* + * Make a deep copy, such that 'src' can be destroyed when this method + * returns. + */ +int +NdbQueryOptionsImpl::copyInterpretedCode(const NdbInterpretedCode& src) +{ + /* Check the program's finalised */ + if (unlikely(!(src.m_flags & NdbInterpretedCode::Finalised))) + { + return Err_FinaliseNotCalled; // NdbInterpretedCode::finalise() not called. + } + if (src.m_instructions_length == 0) + { + return 0; + } + + NdbInterpretedCode* interpretedCode = new NdbInterpretedCode(); + if (unlikely(interpretedCode==NULL)) + { + return Err_MemoryAlloc; + } + + const int error = interpretedCode->copy(src); + if (unlikely(error)) + { + delete interpretedCode; + return error; + } + + /* Replace existing NdbInterpretedCode */ + if (m_interpretedCode) + delete m_interpretedCode; + + m_interpretedCode = interpretedCode; + return 0; +} + + /**************************************************************************** * Glue layer between NdbQueryOperationDef interface and its Impl'ementation. ****************************************************************************/ @@ -1837,15 +1910,16 @@ NdbQueryOperationDefImpl::NdbQueryOperat error = Err_MemoryAlloc; return; } - if (m_options.m_parent!=NULL) + if (m_options.m_parent != NULL) { - m_parent = m_options.m_parent; - const int res = m_parent->addChild(this); - if (unlikely(res != 0)) - { - error = res; - } - } + m_parent = m_options.m_parent; + const int res = m_parent->addChild(this); + if (unlikely(res != 0)) + { + error = res; + return; + } + } // else, ::linkWithParent() will assign 'm_parent' } === modified file 'storage/ndb/src/ndbapi/NdbQueryBuilderImpl.hpp' --- a/storage/ndb/src/ndbapi/NdbQueryBuilderImpl.hpp 2011-02-10 11:54:23 +0000 +++ b/storage/ndb/src/ndbapi/NdbQueryBuilderImpl.hpp 2011-02-11 13:12:09 +0000 @@ -270,13 +270,25 @@ public: explicit NdbQueryOptionsImpl() : m_matchType(NdbQueryOptions::MatchAll), m_scanOrder(NdbQueryOptions::ScanOrdering_void), - m_parent(NULL) + m_parent(NULL), + m_interpretedCode(NULL) {}; + NdbQueryOptionsImpl(const NdbQueryOptionsImpl&); + ~NdbQueryOptionsImpl(); private: NdbQueryOptions::MatchType m_matchType; NdbQueryOptions::ScanOrdering m_scanOrder; NdbQueryOperationDefImpl* m_parent; + const NdbInterpretedCode* m_interpretedCode; + + /** + * Assign NdbInterpretedCode by taking a deep copy of 'src' + * @return possible error code. + */ + int copyInterpretedCode(const NdbInterpretedCode& src); + + NdbQueryOptionsImpl&operator=(const NdbQueryOptionsImpl&); // Not impl. }; @@ -330,6 +342,9 @@ public: enum NdbQueryOptions::ScanOrdering getOrdering() const { return m_options.m_scanOrder; } + const NdbInterpretedCode* getInterpretedCode() const + { return m_options.m_interpretedCode; } + Uint32 assignQueryOperationId(Uint32& nodeId) { if (getType()==NdbQueryOperationDef::UniqueIndexAccess) nodeId++; m_id = nodeId++; === modified file 'storage/ndb/src/ndbapi/NdbQueryOperation.cpp' --- a/storage/ndb/src/ndbapi/NdbQueryOperation.cpp 2011-02-10 11:10:54 +0000 +++ b/storage/ndb/src/ndbapi/NdbQueryOperation.cpp 2011-02-11 13:12:09 +0000 @@ -22,6 +22,7 @@ #include #include "NdbQueryBuilderImpl.hpp" #include "NdbQueryOperationImpl.hpp" +#include "NdbInterpretedCode.hpp" #include #include @@ -4803,29 +4804,35 @@ NdbQueryOperationImpl::getResultStream(U bool NdbQueryOperationImpl::hasInterpretedCode() const { - return m_interpretedCode && m_interpretedCode->m_instructions_length > 0; + return (m_interpretedCode && m_interpretedCode->m_instructions_length > 0) || + (getQueryOperationDef().getInterpretedCode() != NULL); } // NdbQueryOperationImpl::hasInterpretedCode int NdbQueryOperationImpl::prepareInterpretedCode(Uint32Buffer& attrInfo) const { + const NdbInterpretedCode* interpretedCode = + (m_interpretedCode && m_interpretedCode->m_instructions_length > 0) + ? m_interpretedCode + : getQueryOperationDef().getInterpretedCode(); + // There should be no subroutines in a filter. - assert(m_interpretedCode->m_first_sub_instruction_pos==0); - assert(m_interpretedCode->m_instructions_length > 0); - assert(m_interpretedCode->m_instructions_length <= 0xffff); + assert(interpretedCode->m_first_sub_instruction_pos==0); + assert(interpretedCode->m_instructions_length > 0); + assert(interpretedCode->m_instructions_length <= 0xffff); // Allocate space for program and length field. Uint32* const buffer = - attrInfo.alloc(1+m_interpretedCode->m_instructions_length); + attrInfo.alloc(1+interpretedCode->m_instructions_length); if(unlikely(buffer==NULL)) { return Err_MemoryAlloc; } - buffer[0] = m_interpretedCode->m_instructions_length; + buffer[0] = interpretedCode->m_instructions_length; memcpy(buffer+1, - m_interpretedCode->m_buffer, - m_interpretedCode->m_instructions_length * sizeof(Uint32)); + interpretedCode->m_buffer, + interpretedCode->m_instructions_length * sizeof(Uint32)); return 0; } // NdbQueryOperationImpl::prepareInterpretedCode No bundle (reason: useless for push emails).