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<size>.
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<int>(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 <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
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:3429 to 3431) | Ole John Aske | 11 Feb |