1 /*
2    Copyright (c) 2003, 2021, Oracle and/or its affiliates.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License, version 2.0,
6    as published by the Free Software Foundation.
7 
8    This program is also distributed with certain software (including
9    but not limited to OpenSSL) that is licensed under separate terms,
10    as designated in a particular file or component or in included license
11    documentation.  The authors of MySQL hereby grant you an additional
12    permission to link the program and your derivative works with the
13    separately licensed software that they have included with MySQL.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License, version 2.0, for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
23 */
24 
25 #ifndef NdbScanOperation_H
26 #define NdbScanOperation_H
27 
28 #include "NdbOperation.hpp"
29 
30 class NdbBlob;
31 class NdbResultSet;
32 class PollGuard;
33 
34 /**
35  * @class NdbScanOperation
36  * @brief Class of scan operations for use in transactions.
37  */
38 class NdbScanOperation : public NdbOperation {
39 #ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
40   friend class Ndb;
41   friend class NdbImpl;
42   friend class NdbTransaction;
43   friend class NdbResultSet;
44   friend class NdbOperation;
45   friend class NdbBlob;
46   friend class NdbScanFilter;
47   friend class NdbQueryOperationImpl;
48 #endif
49 
50 public:
51   /**
52    * Scan flags.  OR-ed together and passed as argument to
53    * readTuples, scanIndex, and scanTable. Note that SF_MultiRange
54    * has to be set if several ranges (bounds) are to be passed.
55    */
56   enum ScanFlag {
57     /* Scan in TUP order (the order of rows in memory). Table scan only. */
58     SF_TupScan = (1 << 16),
59     /* Scan in DISK order (the order of rows on disk). Table scan only. */
60     SF_DiskScan = (2 << 16),
61     /*
62       Return rows from an index scan sorted, ordered on the index key.
63       Both ascending order or descending order scans are affected by this flag.
64       This flag makes the API perform a merge-sort among the ordered scans of
65       each fragment, to get a single sorted result set.
66       Note that :
67       1) Ordered indexes are distributed - there is one for each fragment of a
68          table.
69       2) Range scans are often parallel - across all index fragments.
70          Occasionally they can be pruned to one index fragment.
71       3) Each index fragment range scan will return results in either ascending
72          or descending order.  Ascending is the default, but descending is
73          chosen if SF_Descending is set.
74       4) Where multiple index fragments are scanned in parallel, the results
75          are sent back to NdbApi where they can optionally be merge-sorted
76          before being returned to the user.  This merge sorting is controlled
77          via the SF_OrderBy and SF_OrderByFull flags.
78       5) Without SF_OrderBy* flags, the results from each index fragment will
79          be in-order (ascending or descending), but results from different
80          fragments may be interleaved.
81       6) With SF_OrderBy* flags, some extra constraints are imposed internally:
82         i) If the range scan is not pruned to one index fragment then all
83            index fragments must be scanned in parallel.  (Non SF_OrderBy* flag
84            scans can be executed with lower than full-parallelism)
85         ii) Results from every index fragment must be available before returning
86             any row, to ensure a correct merge sort.  This serialises the
87             'scrolling' of the scan, potentially resulting in lower row
88             throughput.
89         iii) Non SF_OrderBy* flag scans can return rows to the Api before all
90              index fragments have returned a batch, and can overlap next-batch
91              requests with Api row processing.
92     */
93     SF_OrderBy = (1 << 24),
94     /**
95      * Same as order by, except that it will automatically
96      *   add all key columns into the read-mask
97      */
98     SF_OrderByFull = (16 << 24),
99 
100     /* Index scan in descending order, instead of default ascending. */
101     SF_Descending = (2 << 24),
102     /*
103       Enable @ref get_range_no (index scan only).
104       When this flag is set, NdbIndexScanOperation::get_range_no() can be
105       called to read back the range_no defined in
106       NdbIndexScanOperation::setBound(). See @ref setBound() for
107       explanation.
108       Additionally, when this flag is set and SF_OrderBy* is also set, results
109       from ranges are returned in their entirety before any results are returned
110       from subsequent ranges.
111     */
112     SF_ReadRangeNo = (4 << 24),
113     /* Scan is part of multi-range scan. */
114     SF_MultiRange = (8 << 24),
115     /*
116       Request KeyInfo to be sent back.
117       This enables the option to take over the row lock taken by the scan using
118       lockCurrentTuple(), by making sure that the kernel sends back the
119       information needed to identify the row and the lock.
120       It is enabled by default for scans using LM_Exclusive, but must be
121       explicitly specified to enable the taking-over of LM_Read locks.
122     */
123     SF_KeyInfo = 1
124   };
125 
126 
127   /*
128    * ScanOptions
129    *  These are options passed to the NdbRecord based scanTable and
130    *  scanIndex methods of the NdbTransaction class.
131    *  Each option type is marked as present by setting the corresponding
132    *  bit in the optionsPresent field.  Only the option types marked
133    *  in the optionsPresent field need have sensible data.
134    *  All data is copied out of the ScanOptions structure (and any
135    *  subtended structures) at operation definition time.
136    *  If no options are required, then NULL may be passed as the
137    *  ScanOptions pointer.
138    *
139    *  Most methods take a supplementary sizeOfOptions parameter.  This
140    *  is optional, and is intended to allow the interface implementation
141    *  to remain backwards compatible with older un-recompiled clients
142    *  that may pass an older (smaller) version of the ScanOptions
143    *  structure.  This effect is achieved by passing
144    *  sizeof(NdbScanOperation::ScanOptions) into this parameter.
145    */
146   struct ScanOptions
147   {
148     /*
149       Size of the ScanOptions structure.
150     */
sizeNdbScanOperation::ScanOptions151     static inline Uint32 size()
152     {
153         return sizeof(ScanOptions);
154     }
155 
156     /* Which options are present - see below for possibilities */
157     Uint64 optionsPresent;
158 
159     enum Type { SO_SCANFLAGS    = 0x01,
160                 SO_PARALLEL     = 0x02,
161                 SO_BATCH        = 0x04,
162                 SO_GETVALUE     = 0x08,
163                 SO_PARTITION_ID = 0x10,
164                 SO_INTERPRETED  = 0x20,
165                 SO_CUSTOMDATA   = 0x40,
166                 SO_PART_INFO    = 0x80
167     };
168 
169     /* Flags controlling scan behaviour
170      * See NdbScanOperation::ScanFlag for details
171      */
172     Uint32 scan_flags;
173 
174     /* Desired scan parallelism.
175      * Default == 0 == Maximum parallelism
176      */
177     Uint32 parallel;
178 
179     /* Desired scan batchsize in rows
180      * for NDBD -> API transfers
181      * Default == 0 == Automatically chosen size
182      */
183     Uint32 batch;
184 
185     /* Extra values to be read for each row meeting
186      * scan criteria
187      */
188     NdbOperation::GetValueSpec *extraGetValues;
189     Uint32                     numExtraGetValues;
190 
191     /* Specific partition to limit this scan to
192      * Alternatively, an Ndb::PartitionSpec can be supplied.
193      * For Index Scans, partitioning information can be supplied for
194      * each range
195      */
196     Uint32 partitionId;
197 
198     /* Interpreted code to execute as part of the scan */
199     const NdbInterpretedCode *interpretedCode;
200 
201     /* CustomData ptr to associate with the scan operation */
202     void * customData;
203 
204     /* Partition information for bounding this scan */
205     const Ndb::PartitionSpec* partitionInfo;
206     Uint32 sizeOfPartInfo;
207   };
208 
209 
210   /**
211    * readTuples
212    * Method used in old scan Api to specify scan operation details
213    *
214    * @param lock_mode Lock mode
215    * @param scan_flags see @ref ScanFlag
216    * @param parallel Number of fragments to scan in parallel (0=max)
217    * @param batch Number of rows to fetch in each batch
218    */
219   virtual
220   int readTuples(LockMode lock_mode = LM_Read,
221                  Uint32 scan_flags = 0,
222 		 Uint32 parallel = 0,
223 		 Uint32 batch = 0);
224 
225 #ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
226   /**
227    * readTuples
228    * @param lock_mode Lock mode
229    * @param batch No of rows to fetch from each fragment at a time
230    * @param parallel No of fragments to scan in parallell
231    * @note specifying 0 for batch and parallel means max performance
232    */
233 #ifdef ndb_readtuples_impossible_overload
234   int readTuples(LockMode lock_mode = LM_Read,
235 		 Uint32 batch = 0, Uint32 parallel = 0,
236                  bool keyinfo = false, bool multi_range = false);
237 #endif
238 
readTuples(int parallell)239   inline int readTuples(int parallell){
240     return readTuples(LM_Read, 0, parallell);
241   }
242 
readTuplesExclusive(int parallell=0)243   inline int readTuplesExclusive(int parallell = 0){
244     return readTuples(LM_Exclusive, 0, parallell);
245   }
246 
247   /* First version of ScanOptions, defined here for backwards
248    * compatibility reasons
249    */
250   struct ScanOptions_v1
251   {
252     /* Which options are present - see below for possibilities */
253     Uint64 optionsPresent;
254 
255     enum Type { SO_SCANFLAGS    = 0x01,
256                 SO_PARALLEL     = 0x02,
257                 SO_BATCH        = 0x04,
258                 SO_GETVALUE     = 0x08,
259                 SO_PARTITION_ID = 0x10,
260                 SO_INTERPRETED  = 0x20,
261                 SO_CUSTOMDATA   = 0x40 };
262 
263     /* Flags controlling scan behaviour
264      * See NdbScanOperation::ScanFlag for details
265      */
266     Uint32 scan_flags;
267 
268     /* Desired scan parallelism.
269      * Default == 0 == Maximum parallelism
270      */
271     Uint32 parallel;
272 
273     /* Desired scan batchsize in rows
274      * for NDBD -> API transfers
275      * Default == 0 == Automatically chosen size
276      */
277     Uint32 batch;
278 
279     /* Extra values to be read for each row meeting
280      * scan criteria
281      */
282     NdbOperation::GetValueSpec *extraGetValues;
283     Uint32                     numExtraGetValues;
284 
285     /* Specific partition to limit this scan to
286      * Only applicable for tables defined with UserDefined partitioning
287      * For Index Scans, partitioning information can be supplied for
288      * each range
289      */
290     Uint32 partitionId;
291 
292     /* Interpreted code to execute as part of the scan */
293     const NdbInterpretedCode *interpretedCode;
294 
295     /* CustomData ptr to associate with the scan operation */
296     void * customData;
297   };
298 #endif
299 
300 #ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
301   virtual NdbBlob* getBlobHandle(const char* anAttrName);
302   virtual NdbBlob* getBlobHandle(Uint32 anAttrId);
303 
304   /**
305    * setInterpretedCode
306    *
307    * This method is used to set an interpreted program to be executed
308    * against every row returned by the scan.  This is used to filter
309    * rows out of the returned set.  This method is only supported for
310    * old Api scans.  For NdbRecord scans, pass the interpreted program
311    * via the ScanOptions structure.
312    *
313    * @param code The interpreted program to be executed for each
314    * candidate result row in this scan.
315    * @return 0 if successful, -1 otherwise
316    */
317   int setInterpretedCode(const NdbInterpretedCode *code);
318 
319 #endif
320 
321 
322   /**
323    * Get the next tuple in a scan transaction.
324    *
325    * After each call to nextResult
326    * the buffers and NdbRecAttr objects defined in
327    * NdbOperation::getValue are updated with values
328    * from the scanned tuple.
329    *
330    * @param fetchAllowed  If set to false, then fetching is disabled
331    * @param forceSend If true send will occur immediately (see @ref secAdapt)
332    *
333    * The NDB API will receive tuples from each fragment in batches, and
334    * needs to explicitly request from the NDB Kernel the sending of each new
335    * batch. When a new batch is requested, the NDB Kernel will remove any
336    * locks taken on rows in the previous batch, unless they have been already
337    * taken over by the application executing updateCurrentTuple(),
338    * lockCurrentTuple(), etc.
339    *
340    * The fetchAllowed parameter is used to control this release of
341    * locks from the application. When fetchAllowed is set to false,
342    * the NDB API will not request new batches from the NDB Kernel when
343    * all received rows have been exhausted, but will instead return 2
344    * from nextResult(), indicating that new batches must be
345    * requested. You must then call nextResult with fetchAllowed = true
346    * in order to contact the NDB Kernel for more records, after taking over
347    * locks as appropriate.
348    *
349    * fetchAllowed = false is useful when you want to update or
350    * delete all the records fetched in one transaction(This will save a
351    *  lot of round trip time and make updates or deletes of scanned
352    * records a lot faster).
353    *
354    * While nextResult(false) returns 0, take over the record to
355    * another transaction. When nextResult(false) returns 2 you must
356    * execute and commit the other transaction. This will cause the
357    * locks to be transferred to the other transaction, updates or
358    * deletes will be made and then the locks will be released.
359    *
360    * After that, call nextResult(true) which will fetch new records and
361    * cache them in the NdbApi.
362    *
363    * @note  If you don't take over the records to another transaction the
364    *        locks on those records will be released the next time NDB Kernel
365    *        is contacted for more records.
366    *
367    * @note  Please contact for examples of efficient scan
368    *        updates and deletes.
369    *
370    * @note  See ndb/examples/ndbapi_scan_example for usage.
371    *
372    * @return
373    * -  -1: if unsuccessful,<br>
374    * -   0: if another tuple was received, and<br>
375    * -   1: if there are no more tuples to scan.
376    * -   2: if there are no more cached records in NdbApi
377    */
378   int nextResult(bool fetchAllowed = true, bool forceSend = false);
379 
380   /*
381    * NdbRecord version of nextResult.
382    *
383    * When 0 is returned, this method updates out_row_ptr to point
384    * to the next result row.  The location pointed to is valid
385    * (only) until the next call to nextResult() with
386    * fetchAllowed == true.
387    * The NdbRecord object defining the row format was specified in the
388    * NdbTransaction::scanTable (or scanIndex) call.
389    * Note that this variant of nextResult has three parameters, and
390    * all must be supplied to avoid invoking the two-parameter, non
391    * NdbRecord variant of nextResult.
392    */
393   int nextResult(const char ** out_row_ptr,
394                  bool fetchAllowed,
395                  bool forceSend);
396 
397   /*
398    * Alternate NdbRecord version of nextResult.
399    *
400    * When 0 is returned, this method copies data from the result
401    * to the output buffer. The buffer must be long enough for the
402    * result NdbRecord row as returned by
403    * NdbDictionary::getRecordRowLength(const NdbRecord* record);
404    * The NdbRecord object defining the row format was specified in the
405    * NdbTransaction::scanTable (or scanIndex) call.
406    * @return
407    * -  -1: if unsuccessful
408    * -   0: if another tuple was received
409    * -   1: if there are no more tuples to scan
410    * -   2: if there are no more cached records in NdbApi
411    */
412   int nextResultCopyOut(char * buffer,
413                  bool fetchAllowed,
414                  bool forceSend);
415 
416   /**
417    * Close scan
418    */
419   void close(bool forceSend = false, bool releaseOp = false);
420 
421   /**
422    * Lock current tuple
423    *
424    * @return an NdbOperation or NULL.
425    */
426   NdbOperation* lockCurrentTuple();
427   /**
428    * Lock current tuple
429    *
430    * @param lockTrans Transaction that should perform the lock
431    *
432    * @return an NdbOperation or NULL.
433    */
434   NdbOperation*	lockCurrentTuple(NdbTransaction* lockTrans);
435   /**
436    * Update current tuple
437    *
438    * @return an NdbOperation or NULL.
439    */
440   NdbOperation* updateCurrentTuple();
441   /**
442    * Update current tuple
443    *
444    * @param updateTrans Transaction that should perform the update
445    *
446    * @return an NdbOperation or NULL.
447    */
448   NdbOperation*	updateCurrentTuple(NdbTransaction* updateTrans);
449 
450   /**
451    * Delete current tuple
452    * @return 0 on success or -1 on failure
453    */
454   int deleteCurrentTuple();
455   /**
456    * Delete current tuple
457    *
458    * @param takeOverTransaction Transaction that should perform the delete
459    *
460    * @return 0 on success or -1 on failure
461    */
462   int deleteCurrentTuple(NdbTransaction* takeOverTransaction);
463 
464   /*
465    * NdbRecord versions of scan lock take-over operations.
466    *
467    * Note that calling NdbRecord scan lock take-over on an NdbRecAttr-style
468    * scan is not valid, nor is calling NdbRecAttr-style scan lock take-over
469    * on an NdbRecord-style scan.
470    */
471 
472   /*
473    * Take over the lock without changing the row.
474    * Optionally also read from the row (call with default value NULL for
475    * result_row to not read any attributes.).
476    * The NdbRecord * is required even when not reading any attributes.
477    * Supported OperationOptions : OO_ABORTOPTION, OO_GETVALUE, OO_ANYVALUE
478    */
479   const NdbOperation *lockCurrentTuple(NdbTransaction *takeOverTrans,
480                                        const NdbRecord *result_rec,
481                                        char *result_row= 0,
482                                        const unsigned char *result_mask= 0,
483                                        const NdbOperation::OperationOptions *opts = 0,
484                                        Uint32 sizeOfOptions = 0);
485 
486   /*
487    * Update the current tuple, NdbRecord version.
488    * Values to update with are contained in the passed-in row.
489    * Supported OperationOptions : OO_ABORTOPTION, OO_SETVALUE,
490    *                              OO_INTERPRETED, OO_ANYVALUE
491    */
492   const NdbOperation *updateCurrentTuple(NdbTransaction *takeOverTrans,
493                                          const NdbRecord *attr_rec,
494                                          const char *attr_row,
495                                          const unsigned char *mask= 0,
496                                          const NdbOperation::OperationOptions *opts = 0,
497                                          Uint32 sizeOfOptions = 0);
498 
499   /* Delete the current tuple. NdbRecord version.
500    * The tuple can be read before being deleted.  Specify the columns to read
501    * and the result storage as usual with result_rec, result_row and result_mask.
502    * Supported OperationOptions : OO_ABORTOPTION, OO_GETVALUE, OO_ANYVALUE
503    */
504   const NdbOperation *deleteCurrentTuple(NdbTransaction *takeOverTrans,
505                                          const NdbRecord *result_rec,
506                                          char *result_row = 0,
507                                          const unsigned char *result_mask = 0,
508                                          const NdbOperation::OperationOptions *opts = 0,
509                                          Uint32 sizeOfOptions = 0);
510 
511   /**
512    * Get NdbTransaction object for this scan operation
513    */
514   NdbTransaction* getNdbTransaction() const;
515 
516 
517   /**
518    * Is scan operation pruned to a single table partition?
519    * For NdbRecord defined scans, valid before+after execute.
520    * For Old Api defined scans, valid only after execute.
521    */
522   bool getPruned() const;
523 
524 protected:
525   NdbScanOperation(Ndb* aNdb,
526                    NdbOperation::Type aType = NdbOperation::TableScan);
527   virtual ~NdbScanOperation();
528 
529   virtual NdbRecAttr* getValue_impl(const NdbColumnImpl*, char* aValue = 0);
530   NdbRecAttr* getValue_NdbRecord_scan(const NdbColumnImpl*, char* aValue);
531   NdbRecAttr* getValue_NdbRecAttr_scan(const NdbColumnImpl*, char* aValue);
532 
533   int handleScanGetValuesOldApi();
534   int addInterpretedCode();
535   int handleScanOptionsVersion(const ScanOptions*& optionsPtr,
536                                Uint32 sizeOfOptions,
537                                ScanOptions& currOptions);
538   int handleScanOptions(const ScanOptions *options);
539   int validatePartInfoPtr(const Ndb::PartitionSpec*& partInfo,
540                           Uint32 sizeOfPartInfo,
541                           Ndb::PartitionSpec& partValue);
542   int getPartValueFromInfo(const Ndb::PartitionSpec* partInfo,
543                            const NdbTableImpl* table,
544                            Uint32* partValue);
545   int generatePackedReadAIs(const NdbRecord *reseult_record, bool& haveBlob,
546                             const Uint32 * readMask);
547   int scanImpl(const NdbScanOperation::ScanOptions *options,
548                const Uint32 * readMask);
549   int scanTableImpl(const NdbRecord *result_record,
550                     NdbOperation::LockMode lock_mode,
551                     const unsigned char *result_mask,
552                     const NdbScanOperation::ScanOptions *options,
553                     Uint32 sizeOfOptions);
554 
555   int nextResultNdbRecord(const char * & out_row,
556                           bool fetchAllowed, bool forceSend);
557   virtual void release();
558 
559   int close_impl(bool forceSend,
560                  PollGuard *poll_guard);
561 
562   /* Helper for NdbScanFilter to allocate an InterpretedCode
563    * object owned by the Scan operation
564    */
565   NdbInterpretedCode* allocInterpretedCodeOldApi();
566   void freeInterpretedCodeOldApi();
567 
568   int doSendSetAISectionSizes();
569 
570   // Overloaded methods from NdbCursorOperation
571   int executeCursor(int ProcessorId);
572 
573   // Overloaded private methods from NdbOperation
574   int init(const NdbTableImpl* tab, NdbTransaction*);
575   int prepareSend(Uint32  TC_ConnectPtr, Uint64  TransactionId,
576                   NdbOperation::AbortOption);
577   int doSend(int ProcessorId);
578   virtual void setReadLockMode(LockMode lockMode);
579 
580   virtual void setErrorCode(int aErrorCode) const;
581   virtual void setErrorCodeAbort(int aErrorCode) const;
582 
583   /* This is the transaction which defined this scan
584    *   The transaction(connection) used for the scan is
585    *   pointed to by NdbOperation::theNdbCon
586    */
587   NdbTransaction *m_transConnection;
588 
589   // Scan related variables
590   Uint32 theParallelism;
591   /*
592     Whether keyInfo is requested from Kernel.
593     KeyInfo is requested by application (using the SF_KeyInfo scan flag), and
594     also enabled automatically when using exclusive locking (lockmode
595     LM_Exclusive), or when requesting blobs (getBlobHandle()).
596   */
597   Uint32 m_keyInfo;
598 
599   int getFirstATTRINFOScan();
600   int doSendScan(int ProcessorId);
601   int finaliseScanOldApi();
602   int prepareSendScan(Uint32 TC_ConnectPtr, Uint64 TransactionId,
603                       const Uint32 * readMask);
604 
605   int fix_receivers(Uint32 parallel);
606   void reset_receivers(Uint32 parallel, Uint32 ordered);
607   Uint32* m_array; // containing all arrays below
608   Uint32 m_allocated_receivers;
609   NdbReceiver** m_receivers;      // All receivers
610 
611   Uint32* m_prepared_receivers;   // These are to be sent
612 
613   /*
614     Owned by API/user thread.
615 
616     These receivers, stored in the m_api_receivers array, have all attributes
617     from the current batch fully received, and the API thread has moved them
618     here (under mutex protection) from m_conf_receivers, so that all further
619     nextResult() can access them without extra mutex contention.
620 
621     The m_current_api_receiver member is the index (into m_api_receivers) of
622     the receiver that delivered the last row to the application in
623     nextResult(). If no rows have been delivered yet, it is set to 0 for table
624     scans and to one past the end of the array for ordered index scans.
625 
626     For ordered index scans, the m_api_receivers array is further kept sorted.
627     The entries from (m_current_api_receiver+1) to the end of the array are
628     kept in the order that their first row will be returned in nextResult().
629 
630     Note also that for table scans, the entries available to the API thread
631     are stored in entries 0..(m_api_receivers_count-1), while for ordered
632     index scans, they are stored in entries m_current_api_receiver..array end.
633    */
634   Uint32 m_current_api_receiver;
635   Uint32 m_api_receivers_count;
636   NdbReceiver** m_api_receivers;  // These are currently used by api
637 
638   /*
639     Shared by receiver thread and API thread.
640     These are receivers that the receiver thread has obtained all attribute
641     data for (of the current batch).
642     API thread will move them (under mutex protection) to m_api_receivers on
643     first access with nextResult().
644    */
645   Uint32 m_conf_receivers_count;  // NOTE needs mutex to access
646   NdbReceiver** m_conf_receivers; // receive thread puts them here
647 
648   /*
649    Owned by receiver thread
650    These are the receivers that the receiver thread is currently receiving
651    attribute data for (of the current batch).
652    Once all is received, they will be moved to m_conf_receivers.
653   */
654   Uint32 m_sent_receivers_count;  // NOTE needs mutex to access
655   NdbReceiver** m_sent_receivers; // receive thread puts them here
656 
657   int send_next_scan(Uint32 cnt, bool close);
658   void receiver_delivered(NdbReceiver*);
659   void receiver_completed(NdbReceiver*);
660   void execCLOSE_SCAN_REP();
661 
662   int getKeyFromKEYINFO20(Uint32* data, Uint32 & size);
663   NdbOperation*	takeOverScanOp(OperationType opType, NdbTransaction*);
664   NdbOperation* takeOverScanOpNdbRecord(OperationType opType,
665                                         NdbTransaction* pTrans,
666                                         const NdbRecord *record,
667                                         char *row,
668                                         const unsigned char *mask,
669                                         const NdbOperation::OperationOptions *opts,
670                                         Uint32 sizeOfOptions);
671   bool m_ordered;
672   bool m_descending;
673   Uint32 m_read_range_no;
674   /*
675     m_curr_row: Pointer to last returned row (linked list of NdbRecAttr
676     objects).
677     First comes keyInfo, if requested (explicitly with SF_KeyInfo, or
678     implicitly when using LM_Exclusive).
679     Then comes range_no, if requested with SF_ReadRangeNo, included first in
680     the list of sort columns to get sorting of multiple range scans right.
681     Then the 'real' columns that are participating in the scan.
682   */
683   NdbRecAttr *m_curr_row;
684   bool m_multi_range; // Mark if operation is part of multi-range scan
685   bool m_executed; // Marker if operation should be released at close
686 
687   /* Buffer given to NdbReceivers for batch of rows received
688      during NdbRecord scans, or NULL. Buffer is chunked up
689      to construct several NdbReceiverBuffer, but is allocated
690      as a single chunk from the NdbScanOperation
691   */
692   Uint32 *m_scan_buffer;
693 
694   /* Initialise scan operation with user provided information */
695   virtual int processTableScanDefs(LockMode lock_mode,
696                                    Uint32 scan_flags,
697                                    Uint32 parallel,
698                                    Uint32 batch);
699 
700   /* This flag indicates whether a scan operation is using the old API */
701   bool  m_scanUsingOldApi;
702 
703   /* Whether readTuples has been called - only valid for old Api scans */
704   bool m_readTuplesCalled;
705 
706   /* Scan definition information saved by RecAttr scan API */
707   LockMode m_savedLockModeOldApi;
708   Uint32 m_savedScanFlagsOldApi;
709   Uint32 m_savedParallelOldApi;
710   Uint32 m_savedBatchOldApi;
711 
712   /* NdbInterpretedCode object owned by ScanOperation to support
713    * old NdbScanFilter Api
714    */
715   NdbInterpretedCode* m_interpretedCodeOldApi;
716 
717   enum ScanPruningState {
718     SPS_UNKNOWN,           // Initial state
719     SPS_FIXED,             // Explicit partitionId passed in ScanOptions
720     SPS_ONE_PARTITION,     // Scan pruned to one partition by previous range
721     SPS_MULTI_PARTITION    // Scan cannot be pruned due to previous ranges
722   };
723 
724   ScanPruningState m_pruneState;
725   Uint32 m_pruningKey;  // Can be distr key hash or actual partition id.
726 private:
727   NdbScanOperation(const NdbScanOperation&); // Not impl.
728   NdbScanOperation&operator=(const NdbScanOperation&);
729 
730   /**
731    * Const variants overloaded...calling NdbOperation::getBlobHandle()
732    *  (const NdbOperation::getBlobHandle implementation
733    *   only returns existing Blob operations)
734    *
735    * I'm not sure...but these doesn't seem to be an users of this...
736    * so I make them private...
737    */
738   virtual NdbBlob* getBlobHandle(const char* anAttrName) const;
739   virtual NdbBlob* getBlobHandle(Uint32 anAttrId) const;
740 };
741 
742 inline
743 NdbOperation*
lockCurrentTuple()744 NdbScanOperation::lockCurrentTuple(){
745   return lockCurrentTuple(m_transConnection);
746 }
747 
748 inline
749 NdbOperation*
lockCurrentTuple(NdbTransaction * takeOverTrans)750 NdbScanOperation::lockCurrentTuple(NdbTransaction* takeOverTrans){
751   return takeOverScanOp(NdbOperation::ReadRequest,
752 			takeOverTrans);
753 }
754 
755 inline
756 NdbOperation*
updateCurrentTuple()757 NdbScanOperation::updateCurrentTuple(){
758   return updateCurrentTuple(m_transConnection);
759 }
760 
761 inline
762 NdbOperation*
updateCurrentTuple(NdbTransaction * takeOverTrans)763 NdbScanOperation::updateCurrentTuple(NdbTransaction* takeOverTrans){
764   return takeOverScanOp(NdbOperation::UpdateRequest,
765 			takeOverTrans);
766 }
767 
768 inline
769 int
deleteCurrentTuple()770 NdbScanOperation::deleteCurrentTuple(){
771   return deleteCurrentTuple(m_transConnection);
772 }
773 
774 inline
775 int
deleteCurrentTuple(NdbTransaction * takeOverTrans)776 NdbScanOperation::deleteCurrentTuple(NdbTransaction * takeOverTrans){
777   void * res = takeOverScanOp(NdbOperation::DeleteRequest,
778 			      takeOverTrans);
779   if(res == 0)
780     return -1;
781   return 0;
782 }
783 
784 inline
785 const NdbOperation *
updateCurrentTuple(NdbTransaction * takeOverTrans,const NdbRecord * attr_rec,const char * attr_row,const unsigned char * mask,const NdbOperation::OperationOptions * opts,Uint32 sizeOfOptions)786 NdbScanOperation::updateCurrentTuple(NdbTransaction *takeOverTrans,
787                                      const NdbRecord *attr_rec,
788                                      const char *attr_row,
789                                      const unsigned char *mask,
790                                      const NdbOperation::OperationOptions *opts,
791                                      Uint32 sizeOfOptions)
792 {
793   /*
794     We share the code implementing lockCurrentTuple() and updateCurrentTuple().
795     For lock the row may be updated, for update it is const.
796     Therefore we need to cast away const here, though we won't actually change
797     the row since we pass type 'UpdateRequest'.
798    */
799   return takeOverScanOpNdbRecord(NdbOperation::UpdateRequest, takeOverTrans,
800                                  attr_rec, (char *)attr_row, mask,
801                                  opts, sizeOfOptions);
802 }
803 
804 inline
805 const NdbOperation *
deleteCurrentTuple(NdbTransaction * takeOverTrans,const NdbRecord * result_rec,char * result_row,const unsigned char * result_mask,const NdbOperation::OperationOptions * opts,Uint32 sizeOfOptions)806 NdbScanOperation::deleteCurrentTuple(NdbTransaction *takeOverTrans,
807                                      const NdbRecord *result_rec,
808                                      char *result_row,
809                                      const unsigned char *result_mask,
810                                      const NdbOperation::OperationOptions *opts,
811                                      Uint32 sizeOfOptions)
812 {
813   return takeOverScanOpNdbRecord(NdbOperation::DeleteRequest, takeOverTrans,
814                                  result_rec, result_row, result_mask,
815                                  opts, sizeOfOptions);
816 }
817 
818 inline
819 NdbTransaction*
getNdbTransaction() const820 NdbScanOperation::getNdbTransaction() const
821 {
822   /* return the user visible transaction object ptr, not the
823    * scan's 'internal' / buddy transaction object
824    */
825   return m_transConnection;
826 }
827 
828 #endif
829