/* Copyright (C) 2003 MySQL AB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef NdbScanOperation_H #define NdbScanOperation_H #include <NdbOperation.hpp> class NdbBlob; class NdbResultSet; /** * @class NdbScanOperation * @brief Class of scan operations for use in transactions. */ class NdbScanOperation : public NdbOperation { #ifndef DOXYGEN_SHOULD_SKIP_INTERNAL friend class Ndb; friend class NdbTransaction; friend class NdbResultSet; friend class NdbOperation; friend class NdbBlob; #endif public: /** * readTuples * * @param lock_mode Lock mode * @param batch No of rows to fetch from each fragment at a time * @param parallel No of fragments to scan in parallell * @note specifying 0 for batch and parallall means max performance */ int readTuples(LockMode lock_mode = LM_Read, Uint32 batch = 0, Uint32 parallel = 0); #ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED inline int readTuples(int parallell){ return readTuples(LM_Read, 0, parallell); } inline int readTuplesExclusive(int parallell = 0){ return readTuples(LM_Exclusive, 0, parallell); } #endif #ifndef DOXYGEN_SHOULD_SKIP_INTERNAL NdbBlob* getBlobHandle(const char* anAttrName); NdbBlob* getBlobHandle(Uint32 anAttrId); #endif /** * Get the next tuple in a scan transaction. * * After each call to nextResult * the buffers and NdbRecAttr objects defined in * NdbOperation::getValue are updated with values * from the scanned tuple. * * @param fetchAllowed If set to false, then fetching is disabled * * The NDB API will contact the NDB Kernel for more tuples * when necessary to do so unless you set the fetchAllowed * to false. * This will force NDB to process any records it * already has in it's caches. When there are no more cached * records it will return 2. You must then call nextResult * with fetchAllowed = true in order to contact NDB for more * records. * * fetchAllowed = false is useful when you want to update or * delete all the records fetched in one transaction(This will save a * lot of round trip time and make updates or deletes of scanned * records a lot faster). * While nextResult(false) * returns 0 take over the record to another transaction. When * nextResult(false) returns 2 you must execute and commit the other * transaction. This will cause the locks to be transferred to the * other transaction, updates or deletes will be made and then the * locks will be released. * After that, call nextResult(true) which will fetch new records and * cache them in the NdbApi. * * @note If you don't take over the records to another transaction the * locks on those records will be released the next time NDB Kernel * is contacted for more records. * * @note Please contact for examples of efficient scan * updates and deletes. * * @note See ndb/examples/ndbapi_scan_example for usage. * * @return * - -1: if unsuccessful,<br> * - 0: if another tuple was received, and<br> * - 1: if there are no more tuples to scan. * - 2: if there are no more cached records in NdbApi */ int nextResult(bool fetchAllowed = true, bool forceSend = false); /** * Close scan */ void close(bool forceSend = false); /** * Update current tuple * * @return an NdbOperation or NULL. */ NdbOperation* updateCurrentTuple(); NdbOperation* updateCurrentTuple(NdbTransaction* updateTrans); /** * Delete current tuple * @return 0 on success or -1 on failure */ int deleteCurrentTuple(); int deleteCurrentTuple(NdbTransaction* takeOverTransaction); /** * Restart scan with exactly the same * getValues and search conditions */ int restart(bool forceSend = false); protected: NdbScanOperation(Ndb* aNdb); virtual ~NdbScanOperation(); int nextResultImpl(bool fetchAllowed = true, bool forceSend = false); virtual void release(); int close_impl(class TransporterFacade*, bool forceSend = false); // Overloaded methods from NdbCursorOperation int executeCursor(int ProcessorId); // Overloaded private methods from NdbOperation int init(const NdbTableImpl* tab, NdbTransaction*); int prepareSend(Uint32 TC_ConnectPtr, Uint64 TransactionId); int doSend(int ProcessorId); void checkForceSend(bool forceSend); virtual void setErrorCode(int aErrorCode); virtual void setErrorCodeAbort(int aErrorCode); NdbTransaction *m_transConnection; // Scan related variables Uint32 theParallelism; Uint32 m_keyInfo; int getFirstATTRINFOScan(); int doSendScan(int ProcessorId); int prepareSendScan(Uint32 TC_ConnectPtr, Uint64 TransactionId); int fix_receivers(Uint32 parallel); void reset_receivers(Uint32 parallel, Uint32 ordered); Uint32* m_array; // containing all arrays below Uint32 m_allocated_receivers; NdbReceiver** m_receivers; // All receivers Uint32* m_prepared_receivers; // These are to be sent /** * owned by API/user thread */ Uint32 m_current_api_receiver; Uint32 m_api_receivers_count; NdbReceiver** m_api_receivers; // These are currently used by api /** * owned by receiver thread */ Uint32 m_conf_receivers_count; // NOTE needs mutex to access NdbReceiver** m_conf_receivers; // receive thread puts them here /** * owned by receiver thread */ Uint32 m_sent_receivers_count; // NOTE needs mutex to access NdbReceiver** m_sent_receivers; // receive thread puts them here int send_next_scan(Uint32 cnt, bool close, bool forceSend = false); void receiver_delivered(NdbReceiver*); void receiver_completed(NdbReceiver*); void execCLOSE_SCAN_REP(); int getKeyFromKEYINFO20(Uint32* data, unsigned size); NdbOperation* takeOverScanOp(OperationType opType, NdbTransaction*); bool m_ordered; bool m_descending; Uint32 m_read_range_no; }; inline NdbOperation* NdbScanOperation::updateCurrentTuple(){ return updateCurrentTuple(m_transConnection); } inline NdbOperation* NdbScanOperation::updateCurrentTuple(NdbTransaction* takeOverTrans){ return takeOverScanOp(NdbOperation::UpdateRequest, takeOverTrans); } inline int NdbScanOperation::deleteCurrentTuple(){ return deleteCurrentTuple(m_transConnection); } inline int NdbScanOperation::deleteCurrentTuple(NdbTransaction * takeOverTrans){ void * res = takeOverScanOp(NdbOperation::DeleteRequest, takeOverTrans); if(res == 0) return -1; return 0; } #endif