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