836 lines
30 KiB
C++
836 lines
30 KiB
C++
/*
|
|
Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License, version 2.0,
|
|
as published by the Free Software Foundation.
|
|
|
|
This program is also distributed with certain software (including
|
|
but not limited to OpenSSL) that is licensed under separate terms,
|
|
as designated in a particular file or component or in included license
|
|
documentation. The authors of MySQL hereby grant you an additional
|
|
permission to link the program and your derivative works with the
|
|
separately licensed software that they have included with MySQL.
|
|
|
|
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, version 2.0, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#ifndef NdbScanOperation_H
|
|
#define NdbScanOperation_H
|
|
|
|
#include "NdbOperation.hpp"
|
|
|
|
class NdbBlob;
|
|
class NdbResultSet;
|
|
class PollGuard;
|
|
|
|
/**
|
|
* @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 NdbImpl;
|
|
friend class NdbTransaction;
|
|
friend class NdbResultSet;
|
|
friend class NdbOperation;
|
|
friend class NdbBlob;
|
|
friend class NdbScanFilter;
|
|
friend class NdbQueryOperationImpl;
|
|
#endif
|
|
|
|
public:
|
|
/**
|
|
* Scan flags. OR-ed together and passed as argument to
|
|
* readTuples, scanIndex, and scanTable. Note that SF_MultiRange
|
|
* has to be set if several ranges (bounds) are to be passed.
|
|
*/
|
|
enum ScanFlag {
|
|
/* Scan in TUP order (the order of rows in memory). Table scan only. */
|
|
SF_TupScan = (1 << 16),
|
|
/* Scan in DISK order (the order of rows on disk). Table scan only. */
|
|
SF_DiskScan = (2 << 16),
|
|
/*
|
|
Return rows from an index scan sorted, ordered on the index key.
|
|
Both ascending order or descending order scans are affected by this flag.
|
|
This flag makes the API perform a merge-sort among the ordered scans of
|
|
each fragment, to get a single sorted result set.
|
|
Note that :
|
|
1) Ordered indexes are distributed - there is one for each fragment of a
|
|
table.
|
|
2) Range scans are often parallel - across all index fragments.
|
|
Occasionally they can be pruned to one index fragment.
|
|
3) Each index fragment range scan will return results in either ascending
|
|
or descending order. Ascending is the default, but descending is
|
|
chosen if SF_Descending is set.
|
|
4) Where multiple index fragments are scanned in parallel, the results
|
|
are sent back to NdbApi where they can optionally be merge-sorted
|
|
before being returned to the user. This merge sorting is controlled
|
|
via the SF_OrderBy and SF_OrderByFull flags.
|
|
5) Without SF_OrderBy* flags, the results from each index fragment will
|
|
be in-order (ascending or descending), but results from different
|
|
fragments may be interleaved.
|
|
6) With SF_OrderBy* flags, some extra constraints are imposed internally:
|
|
i) If the range scan is not pruned to one index fragment then all
|
|
index fragments must be scanned in parallel. (Non SF_OrderBy* flag
|
|
scans can be executed with lower than full-parallelism)
|
|
ii) Results from every index fragment must be available before returning
|
|
any row, to ensure a correct merge sort. This serialises the
|
|
'scrolling' of the scan, potentially resulting in lower row
|
|
throughput.
|
|
iii) Non SF_OrderBy* flag scans can return rows to the Api before all
|
|
index fragments have returned a batch, and can overlap next-batch
|
|
requests with Api row processing.
|
|
*/
|
|
SF_OrderBy = (1 << 24),
|
|
/**
|
|
* Same as order by, except that it will automatically
|
|
* add all key columns into the read-mask
|
|
*/
|
|
SF_OrderByFull = (16 << 24),
|
|
|
|
/* Index scan in descending order, instead of default ascending. */
|
|
SF_Descending = (2 << 24),
|
|
/*
|
|
Enable @ref get_range_no (index scan only).
|
|
When this flag is set, NdbIndexScanOperation::get_range_no() can be
|
|
called to read back the range_no defined in
|
|
NdbIndexScanOperation::setBound(). See @ref setBound() for
|
|
explanation.
|
|
Additionally, when this flag is set and SF_OrderBy* is also set, results
|
|
from ranges are returned in their entirety before any results are returned
|
|
from subsequent ranges.
|
|
*/
|
|
SF_ReadRangeNo = (4 << 24),
|
|
/* Scan is part of multi-range scan. */
|
|
SF_MultiRange = (8 << 24),
|
|
/*
|
|
Request KeyInfo to be sent back.
|
|
This enables the option to take over the row lock taken by the scan using
|
|
lockCurrentTuple(), by making sure that the kernel sends back the
|
|
information needed to identify the row and the lock.
|
|
It is enabled by default for scans using LM_Exclusive, but must be
|
|
explicitly specified to enable the taking-over of LM_Read locks.
|
|
*/
|
|
SF_KeyInfo = 1
|
|
};
|
|
|
|
|
|
/*
|
|
* ScanOptions
|
|
* These are options passed to the NdbRecord based scanTable and
|
|
* scanIndex methods of the NdbTransaction class.
|
|
* Each option type is marked as present by setting the corresponding
|
|
* bit in the optionsPresent field. Only the option types marked
|
|
* in the optionsPresent field need have sensible data.
|
|
* All data is copied out of the ScanOptions structure (and any
|
|
* subtended structures) at operation definition time.
|
|
* If no options are required, then NULL may be passed as the
|
|
* ScanOptions pointer.
|
|
*
|
|
* Most methods take a supplementary sizeOfOptions parameter. This
|
|
* is optional, and is intended to allow the interface implementation
|
|
* to remain backwards compatible with older un-recompiled clients
|
|
* that may pass an older (smaller) version of the ScanOptions
|
|
* structure. This effect is achieved by passing
|
|
* sizeof(NdbScanOperation::ScanOptions) into this parameter.
|
|
*/
|
|
struct ScanOptions
|
|
{
|
|
/*
|
|
Size of the ScanOptions structure.
|
|
*/
|
|
static inline Uint32 size()
|
|
{
|
|
return sizeof(ScanOptions);
|
|
}
|
|
|
|
/* Which options are present - see below for possibilities */
|
|
Uint64 optionsPresent;
|
|
|
|
enum Type { SO_SCANFLAGS = 0x01,
|
|
SO_PARALLEL = 0x02,
|
|
SO_BATCH = 0x04,
|
|
SO_GETVALUE = 0x08,
|
|
SO_PARTITION_ID = 0x10,
|
|
SO_INTERPRETED = 0x20,
|
|
SO_CUSTOMDATA = 0x40,
|
|
SO_PART_INFO = 0x80
|
|
};
|
|
|
|
/* Flags controlling scan behaviour
|
|
* See NdbScanOperation::ScanFlag for details
|
|
*/
|
|
Uint32 scan_flags;
|
|
|
|
/* Desired scan parallelism.
|
|
* Default == 0 == Maximum parallelism
|
|
*/
|
|
Uint32 parallel;
|
|
|
|
/* Desired scan batchsize in rows
|
|
* for NDBD -> API transfers
|
|
* Default == 0 == Automatically chosen size
|
|
*/
|
|
Uint32 batch;
|
|
|
|
/* Extra values to be read for each row meeting
|
|
* scan criteria
|
|
*/
|
|
NdbOperation::GetValueSpec *extraGetValues;
|
|
Uint32 numExtraGetValues;
|
|
|
|
/* Specific partition to limit this scan to
|
|
* Alternatively, an Ndb::PartitionSpec can be supplied.
|
|
* For Index Scans, partitioning information can be supplied for
|
|
* each range
|
|
*/
|
|
Uint32 partitionId;
|
|
|
|
/* Interpreted code to execute as part of the scan */
|
|
const NdbInterpretedCode *interpretedCode;
|
|
|
|
/* CustomData ptr to associate with the scan operation */
|
|
void * customData;
|
|
|
|
/* Partition information for bounding this scan */
|
|
const Ndb::PartitionSpec* partitionInfo;
|
|
Uint32 sizeOfPartInfo;
|
|
};
|
|
|
|
|
|
/**
|
|
* readTuples
|
|
* Method used in old scan Api to specify scan operation details
|
|
*
|
|
* @param lock_mode Lock mode
|
|
* @param scan_flags see @ref ScanFlag
|
|
* @param parallel Number of fragments to scan in parallel (0=max)
|
|
* @param batch Number of rows to fetch in each batch
|
|
*/
|
|
virtual
|
|
int readTuples(LockMode lock_mode = LM_Read,
|
|
Uint32 scan_flags = 0,
|
|
Uint32 parallel = 0,
|
|
Uint32 batch = 0);
|
|
|
|
#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
|
|
/**
|
|
* 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 parallel means max performance
|
|
*/
|
|
#ifdef ndb_readtuples_impossible_overload
|
|
int readTuples(LockMode lock_mode = LM_Read,
|
|
Uint32 batch = 0, Uint32 parallel = 0,
|
|
bool keyinfo = false, bool multi_range = false);
|
|
#endif
|
|
|
|
inline int readTuples(int parallell){
|
|
return readTuples(LM_Read, 0, parallell);
|
|
}
|
|
|
|
inline int readTuplesExclusive(int parallell = 0){
|
|
return readTuples(LM_Exclusive, 0, parallell);
|
|
}
|
|
|
|
/* First version of ScanOptions, defined here for backwards
|
|
* compatibility reasons
|
|
*/
|
|
struct ScanOptions_v1
|
|
{
|
|
/* Which options are present - see below for possibilities */
|
|
Uint64 optionsPresent;
|
|
|
|
enum Type { SO_SCANFLAGS = 0x01,
|
|
SO_PARALLEL = 0x02,
|
|
SO_BATCH = 0x04,
|
|
SO_GETVALUE = 0x08,
|
|
SO_PARTITION_ID = 0x10,
|
|
SO_INTERPRETED = 0x20,
|
|
SO_CUSTOMDATA = 0x40 };
|
|
|
|
/* Flags controlling scan behaviour
|
|
* See NdbScanOperation::ScanFlag for details
|
|
*/
|
|
Uint32 scan_flags;
|
|
|
|
/* Desired scan parallelism.
|
|
* Default == 0 == Maximum parallelism
|
|
*/
|
|
Uint32 parallel;
|
|
|
|
/* Desired scan batchsize in rows
|
|
* for NDBD -> API transfers
|
|
* Default == 0 == Automatically chosen size
|
|
*/
|
|
Uint32 batch;
|
|
|
|
/* Extra values to be read for each row meeting
|
|
* scan criteria
|
|
*/
|
|
NdbOperation::GetValueSpec *extraGetValues;
|
|
Uint32 numExtraGetValues;
|
|
|
|
/* Specific partition to limit this scan to
|
|
* Only applicable for tables defined with UserDefined partitioning
|
|
* For Index Scans, partitioning information can be supplied for
|
|
* each range
|
|
*/
|
|
Uint32 partitionId;
|
|
|
|
/* Interpreted code to execute as part of the scan */
|
|
const NdbInterpretedCode *interpretedCode;
|
|
|
|
/* CustomData ptr to associate with the scan operation */
|
|
void * customData;
|
|
};
|
|
#endif
|
|
|
|
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
|
|
virtual NdbBlob* getBlobHandle(const char* anAttrName);
|
|
virtual NdbBlob* getBlobHandle(Uint32 anAttrId);
|
|
|
|
/**
|
|
* setInterpretedCode
|
|
*
|
|
* This method is used to set an interpreted program to be executed
|
|
* against every row returned by the scan. This is used to filter
|
|
* rows out of the returned set. This method is only supported for
|
|
* old Api scans. For NdbRecord scans, pass the interpreted program
|
|
* via the ScanOptions structure.
|
|
*
|
|
* @param code The interpreted program to be executed for each
|
|
* candidate result row in this scan.
|
|
* @return 0 if successful, -1 otherwise
|
|
*/
|
|
int setInterpretedCode(const NdbInterpretedCode *code);
|
|
|
|
#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
|
|
* @param forceSend If true send will occur immediately (see @ref secAdapt)
|
|
*
|
|
* The NDB API will receive tuples from each fragment in batches, and
|
|
* needs to explicitly request from the NDB Kernel the sending of each new
|
|
* batch. When a new batch is requested, the NDB Kernel will remove any
|
|
* locks taken on rows in the previous batch, unless they have been already
|
|
* taken over by the application executing updateCurrentTuple(),
|
|
* lockCurrentTuple(), etc.
|
|
*
|
|
* The fetchAllowed parameter is used to control this release of
|
|
* locks from the application. When fetchAllowed is set to false,
|
|
* the NDB API will not request new batches from the NDB Kernel when
|
|
* all received rows have been exhausted, but will instead return 2
|
|
* from nextResult(), indicating that new batches must be
|
|
* requested. You must then call nextResult with fetchAllowed = true
|
|
* in order to contact the NDB Kernel for more records, after taking over
|
|
* locks as appropriate.
|
|
*
|
|
* 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);
|
|
|
|
/*
|
|
* NdbRecord version of nextResult.
|
|
*
|
|
* When 0 is returned, this method updates out_row_ptr to point
|
|
* to the next result row. The location pointed to is valid
|
|
* (only) until the next call to nextResult() with
|
|
* fetchAllowed == true.
|
|
* The NdbRecord object defining the row format was specified in the
|
|
* NdbTransaction::scanTable (or scanIndex) call.
|
|
* Note that this variant of nextResult has three parameters, and
|
|
* all must be supplied to avoid invoking the two-parameter, non
|
|
* NdbRecord variant of nextResult.
|
|
*/
|
|
int nextResult(const char ** out_row_ptr,
|
|
bool fetchAllowed,
|
|
bool forceSend);
|
|
|
|
/*
|
|
* Alternate NdbRecord version of nextResult.
|
|
*
|
|
* When 0 is returned, this method copies data from the result
|
|
* to the output buffer. The buffer must be long enough for the
|
|
* result NdbRecord row as returned by
|
|
* NdbDictionary::getRecordRowLength(const NdbRecord* record);
|
|
* The NdbRecord object defining the row format was specified in the
|
|
* NdbTransaction::scanTable (or scanIndex) call.
|
|
* @return
|
|
* - -1: if unsuccessful
|
|
* - 0: if another tuple was received
|
|
* - 1: if there are no more tuples to scan
|
|
* - 2: if there are no more cached records in NdbApi
|
|
*/
|
|
int nextResultCopyOut(char * buffer,
|
|
bool fetchAllowed,
|
|
bool forceSend);
|
|
|
|
/**
|
|
* Close scan
|
|
*/
|
|
void close(bool forceSend = false, bool releaseOp = false);
|
|
|
|
/**
|
|
* Lock current tuple
|
|
*
|
|
* @return an NdbOperation or NULL.
|
|
*/
|
|
NdbOperation* lockCurrentTuple();
|
|
/**
|
|
* Lock current tuple
|
|
*
|
|
* @param lockTrans Transaction that should perform the lock
|
|
*
|
|
* @return an NdbOperation or NULL.
|
|
*/
|
|
NdbOperation* lockCurrentTuple(NdbTransaction* lockTrans);
|
|
/**
|
|
* Update current tuple
|
|
*
|
|
* @return an NdbOperation or NULL.
|
|
*/
|
|
NdbOperation* updateCurrentTuple();
|
|
/**
|
|
* Update current tuple
|
|
*
|
|
* @param updateTrans Transaction that should perform the update
|
|
*
|
|
* @return an NdbOperation or NULL.
|
|
*/
|
|
NdbOperation* updateCurrentTuple(NdbTransaction* updateTrans);
|
|
|
|
/**
|
|
* Delete current tuple
|
|
* @return 0 on success or -1 on failure
|
|
*/
|
|
int deleteCurrentTuple();
|
|
/**
|
|
* Delete current tuple
|
|
*
|
|
* @param takeOverTransaction Transaction that should perform the delete
|
|
*
|
|
* @return 0 on success or -1 on failure
|
|
*/
|
|
int deleteCurrentTuple(NdbTransaction* takeOverTransaction);
|
|
|
|
/*
|
|
* NdbRecord versions of scan lock take-over operations.
|
|
*
|
|
* Note that calling NdbRecord scan lock take-over on an NdbRecAttr-style
|
|
* scan is not valid, nor is calling NdbRecAttr-style scan lock take-over
|
|
* on an NdbRecord-style scan.
|
|
*/
|
|
|
|
/*
|
|
* Take over the lock without changing the row.
|
|
* Optionally also read from the row (call with default value NULL for
|
|
* result_row to not read any attributes.).
|
|
* The NdbRecord * is required even when not reading any attributes.
|
|
* Supported OperationOptions : OO_ABORTOPTION, OO_GETVALUE, OO_ANYVALUE
|
|
*/
|
|
const NdbOperation *lockCurrentTuple(NdbTransaction *takeOverTrans,
|
|
const NdbRecord *result_rec,
|
|
char *result_row= 0,
|
|
const unsigned char *result_mask= 0,
|
|
const NdbOperation::OperationOptions *opts = 0,
|
|
Uint32 sizeOfOptions = 0);
|
|
|
|
/*
|
|
* Update the current tuple, NdbRecord version.
|
|
* Values to update with are contained in the passed-in row.
|
|
* Supported OperationOptions : OO_ABORTOPTION, OO_SETVALUE,
|
|
* OO_INTERPRETED, OO_ANYVALUE
|
|
*/
|
|
const NdbOperation *updateCurrentTuple(NdbTransaction *takeOverTrans,
|
|
const NdbRecord *attr_rec,
|
|
const char *attr_row,
|
|
const unsigned char *mask= 0,
|
|
const NdbOperation::OperationOptions *opts = 0,
|
|
Uint32 sizeOfOptions = 0);
|
|
|
|
/* Delete the current tuple. NdbRecord version.
|
|
* The tuple can be read before being deleted. Specify the columns to read
|
|
* and the result storage as usual with result_rec, result_row and result_mask.
|
|
* Supported OperationOptions : OO_ABORTOPTION, OO_GETVALUE, OO_ANYVALUE
|
|
*/
|
|
const NdbOperation *deleteCurrentTuple(NdbTransaction *takeOverTrans,
|
|
const NdbRecord *result_rec,
|
|
char *result_row = 0,
|
|
const unsigned char *result_mask = 0,
|
|
const NdbOperation::OperationOptions *opts = 0,
|
|
Uint32 sizeOfOptions = 0);
|
|
|
|
/**
|
|
* Get NdbTransaction object for this scan operation
|
|
*/
|
|
NdbTransaction* getNdbTransaction() const;
|
|
|
|
|
|
/**
|
|
* Is scan operation pruned to a single table partition?
|
|
* For NdbRecord defined scans, valid before+after execute.
|
|
* For Old Api defined scans, valid only after execute.
|
|
*/
|
|
bool getPruned() const;
|
|
|
|
protected:
|
|
NdbScanOperation(Ndb* aNdb,
|
|
NdbOperation::Type aType = NdbOperation::TableScan);
|
|
virtual ~NdbScanOperation();
|
|
|
|
virtual NdbRecAttr* getValue_impl(const NdbColumnImpl*, char* aValue = 0);
|
|
NdbRecAttr* getValue_NdbRecord_scan(const NdbColumnImpl*, char* aValue);
|
|
NdbRecAttr* getValue_NdbRecAttr_scan(const NdbColumnImpl*, char* aValue);
|
|
|
|
int handleScanGetValuesOldApi();
|
|
int addInterpretedCode();
|
|
int handleScanOptionsVersion(const ScanOptions*& optionsPtr,
|
|
Uint32 sizeOfOptions,
|
|
ScanOptions& currOptions);
|
|
int handleScanOptions(const ScanOptions *options);
|
|
int validatePartInfoPtr(const Ndb::PartitionSpec*& partInfo,
|
|
Uint32 sizeOfPartInfo,
|
|
Ndb::PartitionSpec& partValue);
|
|
int getPartValueFromInfo(const Ndb::PartitionSpec* partInfo,
|
|
const NdbTableImpl* table,
|
|
Uint32* partValue);
|
|
int generatePackedReadAIs(const NdbRecord *reseult_record, bool& haveBlob,
|
|
const Uint32 * readMask);
|
|
int scanImpl(const NdbScanOperation::ScanOptions *options,
|
|
const Uint32 * readMask);
|
|
int scanTableImpl(const NdbRecord *result_record,
|
|
NdbOperation::LockMode lock_mode,
|
|
const unsigned char *result_mask,
|
|
const NdbScanOperation::ScanOptions *options,
|
|
Uint32 sizeOfOptions);
|
|
|
|
int nextResultNdbRecord(const char * & out_row,
|
|
bool fetchAllowed, bool forceSend);
|
|
virtual void release();
|
|
|
|
int close_impl(bool forceSend,
|
|
PollGuard *poll_guard);
|
|
|
|
/* Helper for NdbScanFilter to allocate an InterpretedCode
|
|
* object owned by the Scan operation
|
|
*/
|
|
NdbInterpretedCode* allocInterpretedCodeOldApi();
|
|
void freeInterpretedCodeOldApi();
|
|
|
|
int doSendSetAISectionSizes();
|
|
|
|
// 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,
|
|
NdbOperation::AbortOption);
|
|
int doSend(int ProcessorId);
|
|
virtual void setReadLockMode(LockMode lockMode);
|
|
|
|
virtual void setErrorCode(int aErrorCode) const;
|
|
virtual void setErrorCodeAbort(int aErrorCode) const;
|
|
|
|
/* This is the transaction which defined this scan
|
|
* The transaction(connection) used for the scan is
|
|
* pointed to by NdbOperation::theNdbCon
|
|
*/
|
|
NdbTransaction *m_transConnection;
|
|
|
|
// Scan related variables
|
|
Uint32 theParallelism;
|
|
/*
|
|
Whether keyInfo is requested from Kernel.
|
|
KeyInfo is requested by application (using the SF_KeyInfo scan flag), and
|
|
also enabled automatically when using exclusive locking (lockmode
|
|
LM_Exclusive), or when requesting blobs (getBlobHandle()).
|
|
*/
|
|
Uint32 m_keyInfo;
|
|
|
|
int getFirstATTRINFOScan();
|
|
int doSendScan(int ProcessorId);
|
|
void finaliseScan();
|
|
int finaliseScanOldApi();
|
|
int prepareSendScan(Uint32 TC_ConnectPtr, Uint64 TransactionId,
|
|
const Uint32 * readMask);
|
|
|
|
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.
|
|
|
|
These receivers, stored in the m_api_receivers array, have all attributes
|
|
from the current batch fully received, and the API thread has moved them
|
|
here (under mutex protection) from m_conf_receivers, so that all further
|
|
nextResult() can access them without extra mutex contention.
|
|
|
|
The m_current_api_receiver member is the index (into m_api_receivers) of
|
|
the receiver that delivered the last row to the application in
|
|
nextResult(). If no rows have been delivered yet, it is set to 0 for table
|
|
scans and to one past the end of the array for ordered index scans.
|
|
|
|
For ordered index scans, the m_api_receivers array is further kept sorted.
|
|
The entries from (m_current_api_receiver+1) to the end of the array are
|
|
kept in the order that their first row will be returned in nextResult().
|
|
|
|
Note also that for table scans, the entries available to the API thread
|
|
are stored in entries 0..(m_api_receivers_count-1), while for ordered
|
|
index scans, they are stored in entries m_current_api_receiver..array end.
|
|
*/
|
|
Uint32 m_current_api_receiver;
|
|
Uint32 m_api_receivers_count;
|
|
NdbReceiver** m_api_receivers; // These are currently used by api
|
|
|
|
/*
|
|
Shared by receiver thread and API thread.
|
|
These are receivers that the receiver thread has obtained all attribute
|
|
data for (of the current batch).
|
|
API thread will move them (under mutex protection) to m_api_receivers on
|
|
first access with nextResult().
|
|
*/
|
|
Uint32 m_conf_receivers_count; // NOTE needs mutex to access
|
|
NdbReceiver** m_conf_receivers; // receive thread puts them here
|
|
|
|
/*
|
|
Owned by receiver thread
|
|
These are the receivers that the receiver thread is currently receiving
|
|
attribute data for (of the current batch).
|
|
Once all is received, they will be moved to m_conf_receivers.
|
|
*/
|
|
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);
|
|
void receiver_delivered(NdbReceiver*);
|
|
void receiver_completed(NdbReceiver*);
|
|
void execCLOSE_SCAN_REP();
|
|
|
|
int getKeyFromKEYINFO20(Uint32* data, Uint32 & size);
|
|
NdbOperation* takeOverScanOp(OperationType opType, NdbTransaction*);
|
|
NdbOperation* takeOverScanOpNdbRecord(OperationType opType,
|
|
NdbTransaction* pTrans,
|
|
const NdbRecord *record,
|
|
char *row,
|
|
const unsigned char *mask,
|
|
const NdbOperation::OperationOptions *opts,
|
|
Uint32 sizeOfOptions);
|
|
bool m_ordered;
|
|
bool m_descending;
|
|
Uint32 m_read_range_no;
|
|
/*
|
|
m_curr_row: Pointer to last returned row (linked list of NdbRecAttr
|
|
objects).
|
|
First comes keyInfo, if requested (explicitly with SF_KeyInfo, or
|
|
implicitly when using LM_Exclusive).
|
|
Then comes range_no, if requested with SF_ReadRangeNo, included first in
|
|
the list of sort columns to get sorting of multiple range scans right.
|
|
Then the 'real' columns that are participating in the scan.
|
|
*/
|
|
NdbRecAttr *m_curr_row;
|
|
bool m_multi_range; // Mark if operation is part of multi-range scan
|
|
bool m_executed; // Marker if operation should be released at close
|
|
|
|
/* Buffer given to NdbReceivers for batch of rows received
|
|
during NdbRecord scans, or NULL. Buffer is chunked up
|
|
to construct several NdbReceiverBuffer, but is allocated
|
|
as a single chunk from the NdbScanOperation
|
|
*/
|
|
Uint32 *m_scan_buffer;
|
|
|
|
/* Initialise scan operation with user provided information */
|
|
virtual int processTableScanDefs(LockMode lock_mode,
|
|
Uint32 scan_flags,
|
|
Uint32 parallel,
|
|
Uint32 batch);
|
|
|
|
/* This flag indicates whether a scan operation is using the old API */
|
|
bool m_scanUsingOldApi;
|
|
|
|
/* Whether readTuples has been called - only valid for old Api scans */
|
|
bool m_readTuplesCalled;
|
|
|
|
/* Scan definition information saved by RecAttr scan API */
|
|
LockMode m_savedLockModeOldApi;
|
|
Uint32 m_savedScanFlagsOldApi;
|
|
Uint32 m_savedParallelOldApi;
|
|
Uint32 m_savedBatchOldApi;
|
|
|
|
/* NdbInterpretedCode object owned by ScanOperation to support
|
|
* old NdbScanFilter Api
|
|
*/
|
|
NdbInterpretedCode* m_interpretedCodeOldApi;
|
|
|
|
enum ScanPruningState {
|
|
SPS_UNKNOWN, // Initial state
|
|
SPS_FIXED, // Explicit partitionId passed in ScanOptions
|
|
SPS_ONE_PARTITION, // Scan pruned to one partition by previous range
|
|
SPS_MULTI_PARTITION // Scan cannot be pruned due to previous ranges
|
|
};
|
|
|
|
ScanPruningState m_pruneState;
|
|
Uint32 m_pruningKey; // Can be distr key hash or actual partition id.
|
|
|
|
/**
|
|
* This flag indicates whether a scan operation was
|
|
* succesfully finalised
|
|
*/
|
|
bool m_scanFinalisedOk;
|
|
private:
|
|
NdbScanOperation(const NdbScanOperation&); // Not impl.
|
|
NdbScanOperation&operator=(const NdbScanOperation&);
|
|
|
|
/**
|
|
* Const variants overloaded...calling NdbOperation::getBlobHandle()
|
|
* (const NdbOperation::getBlobHandle implementation
|
|
* only returns existing Blob operations)
|
|
*
|
|
* I'm not sure...but these doesn't seem to be an users of this...
|
|
* so I make them private...
|
|
*/
|
|
virtual NdbBlob* getBlobHandle(const char* anAttrName) const;
|
|
virtual NdbBlob* getBlobHandle(Uint32 anAttrId) const;
|
|
};
|
|
|
|
inline
|
|
NdbOperation*
|
|
NdbScanOperation::lockCurrentTuple(){
|
|
return lockCurrentTuple(m_transConnection);
|
|
}
|
|
|
|
inline
|
|
NdbOperation*
|
|
NdbScanOperation::lockCurrentTuple(NdbTransaction* takeOverTrans){
|
|
return takeOverScanOp(NdbOperation::ReadRequest,
|
|
takeOverTrans);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
inline
|
|
const NdbOperation *
|
|
NdbScanOperation::updateCurrentTuple(NdbTransaction *takeOverTrans,
|
|
const NdbRecord *attr_rec,
|
|
const char *attr_row,
|
|
const unsigned char *mask,
|
|
const NdbOperation::OperationOptions *opts,
|
|
Uint32 sizeOfOptions)
|
|
{
|
|
/*
|
|
We share the code implementing lockCurrentTuple() and updateCurrentTuple().
|
|
For lock the row may be updated, for update it is const.
|
|
Therefore we need to cast away const here, though we won't actually change
|
|
the row since we pass type 'UpdateRequest'.
|
|
*/
|
|
return takeOverScanOpNdbRecord(NdbOperation::UpdateRequest, takeOverTrans,
|
|
attr_rec, const_cast<char *>(attr_row), mask,
|
|
opts, sizeOfOptions);
|
|
}
|
|
|
|
inline
|
|
const NdbOperation *
|
|
NdbScanOperation::deleteCurrentTuple(NdbTransaction *takeOverTrans,
|
|
const NdbRecord *result_rec,
|
|
char *result_row,
|
|
const unsigned char *result_mask,
|
|
const NdbOperation::OperationOptions *opts,
|
|
Uint32 sizeOfOptions)
|
|
{
|
|
return takeOverScanOpNdbRecord(NdbOperation::DeleteRequest, takeOverTrans,
|
|
result_rec, result_row, result_mask,
|
|
opts, sizeOfOptions);
|
|
}
|
|
|
|
inline
|
|
NdbTransaction*
|
|
NdbScanOperation::getNdbTransaction() const
|
|
{
|
|
/* return the user visible transaction object ptr, not the
|
|
* scan's 'internal' / buddy transaction object
|
|
*/
|
|
return m_transConnection;
|
|
}
|
|
|
|
#endif
|