#At file:///net/fimafeng09/export/home/tmp/oleja/mysql/mysql-5.1-telco-7.0-spj-scan-scan/ based on revid:ole.john.aske@stripped
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
=== 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 <NdbQueryBuilder.hpp>
#include "NdbQueryBuilderImpl.hpp"
#include "NdbQueryOperationImpl.hpp"
+#include "NdbInterpretedCode.hpp"
#include <signaldata/TcKeyReq.hpp>
#include <signaldata/TcKeyRef.hpp>
@@ -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
Attachment: [text/bzr-bundle] bzr/ole.john.aske@oracle.com-20110211131209-035d51yxve08mctk.bundle
| Thread |
|---|
| • bzr commit into mysql-5.1-telco-7.0-spj-scan-vs-scan branch(ole.john.aske:3430) | Ole John Aske | 11 Feb |