1 /*
2    Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
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 Street, Fifth Floor, Boston, MA 02110-1301, USA */
23 
24 #ifndef NdbQueryOperationImpl_H
25 #define NdbQueryOperationImpl_H
26 
27 #include "NdbQueryOperation.hpp"
28 #include "NdbQueryBuilderImpl.hpp"
29 #include "NdbIndexScanOperation.hpp"
30 #include <NdbError.hpp>
31 #include <ndb_limits.h>
32 #include <Vector.hpp>
33 
34 // Forward declarations
35 class NdbTableImpl;
36 class NdbIndexImpl;
37 class NdbApiSignal;
38 class NdbResultStream;
39 class NdbParamOperand;
40 class NdbTransaction;
41 class NdbReceiver;
42 class NdbOut;
43 class NdbRootFragment;
44 
45 /**
46  * This class simplifies the task of allocating memory for many instances
47  * of the same type at once and then constructing them later.
48  */
49 class NdbBulkAllocator
50 {
51 public:
52   /**
53    * @param[in] objSize Size (in bytes) of each object.
54    */
55   explicit NdbBulkAllocator(size_t objSize);
~NdbBulkAllocator()56   ~NdbBulkAllocator()
57   { reset(); };
58 
59   /**
60    * Allocate memory for a number of objects from the heap.
61    * @param[in] maxObjs The maximal number of objects this instance should
62    * accomodate.
63    * @return 0 or possible error code.
64    */
65   int init(Uint32 maxObjs);
66 
67   /** Release allocated memory to heap and reset *this to initial state.*/
68   void reset();
69 
70   /**
71    * Get an area large enough to hold 'noOfObjs' objects.
72    * @return The memory area.
73    */
74   void* allocObjMem(Uint32 noOfObjs);
75 private:
76   /** An end marker for checking for buffer overrun.*/
77   static const char endMarker = -15;
78 
79   /** Size of each object (in bytes).*/
80   const size_t m_objSize;
81 
82   /** The number of objects this instance can accomodate.*/
83   Uint32 m_maxObjs;
84 
85   /** The allocated memory area.*/
86   char* m_buffer;
87 
88   /** The number of object areas allocated so far.*/
89   Uint32 m_nextObjNo;
90 
91   // No copying.
92   NdbBulkAllocator(const NdbBulkAllocator&);
93   NdbBulkAllocator& operator= (const NdbBulkAllocator&);
94 };
95 
96 /** This class is the internal implementation of the interface defined by
97  * NdbQuery. This class should thus not be visible to the application
98  * programmer. @see NdbQuery.*/
99 class NdbQueryImpl {
100 
101   /* NdbQueryOperations are allowed to access it containing query */
102   friend class NdbQueryOperationImpl;
103 
104   /** For debugging.*/
105   friend NdbOut& operator<<(NdbOut& out, const class NdbQueryOperationImpl&);
106 
107 public:
108   /** Factory method which instantiate a query from its definition.
109    (There is no public constructor.)*/
110   static NdbQueryImpl* buildQuery(NdbTransaction& trans,
111                                   const NdbQueryDefImpl& queryDef);
112 
113   /** Return number of operations in query.*/
114   Uint32 getNoOfOperations() const;
115 
116   /**
117    * return number of leaf-operations
118    */
119   Uint32 getNoOfLeafOperations() const;
120 
121   // Get a specific NdbQueryOperation instance by ident specified
122   // when the NdbQueryOperationDef was created.
123   NdbQueryOperationImpl& getQueryOperation(Uint32 ident) const;
124   NdbQueryOperationImpl* getQueryOperation(const char* ident) const;
125   // Consider to introduce these as convenient shortcuts
126 //NdbQueryOperationDefImpl& getQueryOperationDef(Uint32 ident) const;
127 //NdbQueryOperationDefImpl* getQueryOperationDef(const char* ident) const;
128 
129   /** Return number of parameter operands in query.*/
130   Uint32 getNoOfParameters() const;
131   const NdbParamOperand* getParameter(const char* name) const;
132   const NdbParamOperand* getParameter(Uint32 num) const;
133 
134   /** Get the next tuple(s) from the global cursor on the query.
135    * @param fetchAllowed If true, the method may block while waiting for more
136    * results to arrive. Otherwise, the method will return immediately if no more
137    * results are buffered in the API.
138    * @param forceSend FIXME: Describe this.
139    * @return
140    * -  NextResult_error (-1):       if unsuccessful,<br>
141    * -  NextResult_gotRow (0):       if another tuple was received, and<br>
142    * -  NextResult_scanComplete (1): if there are no more tuples to scan.
143    * -  NextResult_bufferEmpty (2):  if there are no more cached records
144    *                                 in NdbApi
145    * @see NdbQueryOperation::nextResult()
146    */
147   NdbQuery::NextResultOutcome nextResult(bool fetchAllowed, bool forceSend);
148 
149   /** Close query:
150    *  - Release datanode resources,
151    *  - Discard pending result sets,
152    *  - Delete internal buffer and structures for receiving results.
153    *  - Disconnect with NdbQueryDef - it might now be destructed .
154    */
155   int close(bool forceSend);
156 
157   /** Deallocate 'this' NdbQuery object and its NdbQueryOperation objects.
158    *  If not already closed, it will also ::close() the NdbQuery.
159    */
160   void release();
161 
getNdbTransaction() const162   NdbTransaction& getNdbTransaction() const
163   { return m_transaction; }
164 
165   const NdbError& getNdbError() const;
166 
167   void setErrorCode(int aErrorCode);
168 
169   /** Assign supplied parameter values to the parameter placeholders
170    *  created when the query was defined.
171    *  Values are *copied* into this NdbQueryImpl object:
172    *  Memory location used as source for parameter values don't have
173    *  to be valid after this assignment.
174    */
175   int assignParameters(const NdbQueryParamValue paramValues[]);
176 
177   int setBound(const NdbRecord *keyRecord,
178                const NdbIndexScanOperation::IndexBound *bound);
179 
180   /** Prepare for execution.
181    *  @return possible error code.
182    */
183   int prepareSend();
184 
185   /** Send prepared signals from this NdbQuery to start execution
186    *  @return #signals sent, -1 if error.
187    */
188   int doSend(int aNodeId, bool lastFlag);
189 
getInterface()190   NdbQuery& getInterface()
191   { return m_interface; }
192 
193   /** Get next query in same transaction.*/
getNext() const194   NdbQueryImpl* getNext() const
195   { return m_next; }
196 
setNext(NdbQueryImpl * next)197   void setNext(NdbQueryImpl* next)
198   { m_next = next; }
199 
200   /** Get the (transaction independent) definition of this query. */
getQueryDef() const201   const NdbQueryDefImpl& getQueryDef() const
202   {
203     assert(m_queryDef);
204     return *m_queryDef;
205   }
206 
207   /** Process TCKEYCONF message. Return true if query is complete. */
208   bool execTCKEYCONF();
209 
210   /** Process SCAN_TABCONF w/ EndOfData which is a 'Close Scan Reply'. */
211   void execCLOSE_SCAN_REP(int errorCode, bool needClose);
212 
213   /** Determines if query has completed and may be garbage collected
214    *  A query is not considder complete until the client has
215    *  called the ::close() or ::release() method on it.
216    */
hasCompleted() const217   bool hasCompleted() const
218   { return (m_state == Closed);
219   }
220 
221   /**
222    * Mark this query as the first query or operation in a new transaction.
223    * This should only be called for queries where root operation is a lookup.
224    */
setStartIndicator()225   void setStartIndicator()
226   {
227     assert(!getQueryDef().isScanQuery());
228     m_startIndicator = true;
229   }
230 
231   /**
232    * Mark this query as the last query or operation in a transaction, after
233    * which the transaction should be committed. This should only be called
234    * for queries where root operation is a lookup.
235    */
setCommitIndicator()236   void setCommitIndicator()
237   {
238     assert(!getQueryDef().isScanQuery());
239     m_commitIndicator = true;
240   }
241 
242   /**
243    * Check if this is a pruned range scan. A range scan is pruned if the ranges
244    * are such that only a subset of the fragments need to be scanned for
245    * matching tuples.
246    *
247    * @param pruned This will be set to true if the operation is a pruned range
248    * scan.
249    * @return 0 if ok, -1 in case of error (call getNdbError() for details.)
250    */
251   int isPrunable(bool& pruned);
252 
253   /** Get the number of fragments to be read for the root operation.*/
getRootFragCount() const254   Uint32 getRootFragCount() const
255   { return m_rootFragCount; }
256 
getResultStreamAlloc()257   NdbBulkAllocator& getResultStreamAlloc()
258   { return m_resultStreamAlloc; }
259 
getTupleSetAlloc()260   NdbBulkAllocator& getTupleSetAlloc()
261   { return m_tupleSetAlloc; }
262 
getRowBufferAlloc()263   NdbBulkAllocator& getRowBufferAlloc()
264   { return m_rowBufferAlloc; }
265 
266 private:
267   /** Possible return values from NdbQueryImpl::awaitMoreResults.
268    * A subset of the integer values also matches those returned
269    * from PoolGuard::wait_scan().
270    */
271   enum FetchResult{
272     FetchResult_gotError = -4,  // There is an error avail in 'm_error.code'
273     FetchResult_sendFail = -3,
274     FetchResult_nodeFail = -2,
275     FetchResult_timeOut = -1,
276     FetchResult_ok = 0,
277     FetchResult_noMoreData = 1,
278     FetchResult_noMoreCache = 2
279   };
280 
281   /**
282    * Container of root fragments that the application is currently
283    * iterating over. 'Owned' by application thread and can be accesed
284    * without requiring a mutex lock.
285    * RootFragments are appended to a OrderedFragSet by ::prepareMoreResults()
286    *
287    */
288   class OrderedFragSet{
289   public:
290     // For calculating need for dynamically allocated memory.
291     static const Uint32 pointersPerFragment = 2;
292 
293     explicit OrderedFragSet();
294 
295     ~OrderedFragSet();
296 
297     /**
298      * Prepare internal datastructures.
299      * param[in] allocator For allocating arrays of pointers.
300      * param[in] ordering Possible scan ordering.
301      * param[in] capacity Max no of root fragments.
302      * @return 0 if ok, else errorcode
303      */
304     void prepare(NdbBulkAllocator& allocator,
305                  NdbQueryOptions::ScanOrdering ordering,
306                  int capacity,
307                  const NdbRecord* keyRecord,
308                  const NdbRecord* resultRecord);
309 
310     /**
311      * Add root fragments with completed ResultSets to this OrderedFragSet.
312      * The PollGuard mutex must locked, and under its protection
313      * completed root fragments are 'consumed' from rootFrags[] and
314      * added to OrderedFragSet where it become available for the
315      * application thread.
316      */
317     void prepareMoreResults(NdbRootFragment rootFrags[], Uint32 cnt);  // Need mutex lock
318 
319     /** Get the root fragment from which to read the next row.*/
320     NdbRootFragment* getCurrent() const;
321 
322     /**
323      * Re-organize the fragments after a row has been consumed. This is
324      * needed to remove fragments that has been emptied, and to re-sort
325      * fragments if doing a sorted scan.
326      */
327     void reorganize();
328 
329     /** Reset object to an empty state.*/
330     void clear();
331 
332     /**
333      * Get all fragments where more rows may be (pre-)fetched.
334      * (This method is not idempotent - the fragments are removed
335      * from the set.)
336      * @return Number of fragments (in &frags) from which more
337      * results should be requested.
338      */
339     Uint32 getFetchMore(NdbRootFragment** &rootFrags);
340 
341   private:
342 
343     /** No of fragments to read until '::finalBatchReceived()'.*/
344     int m_capacity;
345     /** Number of fragments in 'm_activeFrags'.*/
346     int m_activeFragCount;
347     /** Number of fragments in 'm_fetchMoreFrags'. */
348     int m_fetchMoreFragCount;
349     /**
350      * Number of fragments where the final batch has been received
351      * and consumed.
352      */
353     int m_finalFragCount;
354     /** Ordering of index scan result.*/
355     NdbQueryOptions::ScanOrdering m_ordering;
356     /** Needed for comparing records when ordering results.*/
357     const NdbRecord* m_keyRecord;
358     /** Needed for comparing records when ordering results.*/
359     const NdbRecord* m_resultRecord;
360     /**
361      * Fragments where some tuples in the current ResultSet has not
362      * yet been consumed.
363      */
364     NdbRootFragment** m_activeFrags;
365     /**
366      * Fragments from which we should request more ResultSets.
367      * Either due to the current batch has been consumed, or double buffering
368      * of result sets allows us to request another batch before the current
369      * has been consumed.
370      */
371     NdbRootFragment** m_fetchMoreFrags;
372 
373     /** Add a complete fragment that has been received.*/
374     void add(NdbRootFragment& frag);
375 
376     /** For sorting fragment reads according to index value of first record.
377      * Also f1<f2 if f2 has reached end of data and f1 has not.
378      * @return 1 if f1>f2, 0 if f1==f2, -1 if f1<f2.*/
379     int compare(const NdbRootFragment& frag1,
380                 const NdbRootFragment& frag2) const;
381 
382     /** For debugging purposes.*/
383     bool verifySortOrder() const;
384 
385     // No copying.
386     OrderedFragSet(const OrderedFragSet&);
387     OrderedFragSet& operator=(const OrderedFragSet&);
388   }; // class OrderedFragSet
389 
390   /** The interface that is visible to the application developer.*/
391   NdbQuery m_interface;
392 
393   enum {        // State of NdbQuery in API
394     Initial,    // Constructed object, assiciated with a defined query
395     Defined,    // Parameter values has been assigned
396     Prepared,   // KeyInfo & AttrInfo prepared for execution
397     Executing,  // Signal with exec. req. sent to TC
398     EndOfData,  // All results rows consumed
399     Closed,     // Query has been ::close()'ed
400     Failed,
401     Destructed
402   } m_state;
403 
404   enum {        // Assumed state of query cursor in TC block
405     Inactive,   // Execution not started at TC
406     Active
407   } m_tcState;
408 
409   /** Next query in same transaction.*/
410   NdbQueryImpl* m_next;
411   /** Definition of this query.*/
412   const NdbQueryDefImpl* m_queryDef;
413 
414   /** Possible error status of this query.*/
415   NdbError m_error;
416 
417   /**
418    * Possible error received from TC / datanodes.
419    * Only access w/ PollGuard mutex as it is set by receiver thread.
420    * Checked and moved into 'm_error' with ::hasReceivedError().
421    */
422   int m_errorReceived;   // BEWARE: protect with PollGuard mutex
423 
424   /** Transaction in which this query instance executes.*/
425   NdbTransaction& m_transaction;
426 
427   /** Scan queries creates their own sub transaction which they
428    *  execute within.
429    *  Has same transId, Ndb*, ++ as the 'real' transaction above.
430    */
431   NdbTransaction* m_scanTransaction;
432 
433   /** The operations constituting this query.*/
434   NdbQueryOperationImpl *m_operations;  // 'Array of ' OperationImpls
435   Uint32 m_countOperations;             // #elements in above array
436 
437   /** Current global cursor position. Refers the current NdbQueryOperation which
438    *  should be advanced to 'next' position for producing a new global set of results.
439    */
440   Uint32 m_globalCursor;
441 
442   /** Number of root fragments not yet completed within the current batch.
443    *  Only access w/ PollGuard mutex as it is also updated by receiver thread
444    */
445   Uint32 m_pendingFrags;  // BEWARE: protect with PollGuard mutex
446 
447   /** Number of fragments to be read by the root operation. (1 if root
448    * operation is a lookup)*/
449   Uint32 m_rootFragCount;
450 
451   /**
452    * This is an array with one element for each fragment that the root
453    * operation accesses (i.e. one for a lookup, all for a table scan).
454    * It keeps the state of the read operation on that fragment, and on
455    * any child operation instance derived from it.
456    */
457   NdbRootFragment* m_rootFrags;
458 
459   /** Root fragments that the application is currently iterating over. Only
460    * accessed by application thread.
461    */
462   OrderedFragSet m_applFrags;
463 
464   /** Number of root fragments for which confirmation for the final batch
465    * (with tcPtrI=RNIL) has been received. Observe that even if
466    * m_finalBatchFrags==m_rootFragCount, all tuples for the final batches may
467    * still not have been received (i.e. m_pendingFrags>0).
468    */
469   Uint32 m_finalBatchFrags; // BEWARE: protect with PollGuard mutex
470 
471   /** Number of IndexBounds set by API (index scans only) */
472   Uint32 m_num_bounds;
473 
474   /**
475    * Number of fields in the shortest bound (for an index scan root).
476    * Will be 0xffffffff if no bound has been set.
477    */
478   Uint32 m_shortestBound;
479 
480   /**
481    * Signal building section:
482    */
483   Uint32Buffer m_attrInfo;  // ATTRINFO: QueryTree + serialized parameters
484   Uint32Buffer m_keyInfo;   // KEYINFO:  Lookup key or scan bounds
485 
486   /** True if this query starts a new transaction. */
487   bool m_startIndicator;
488 
489   /** True if the transaction should be committed after executing this query.*/
490   bool m_commitIndicator;
491 
492   /** This field tells if the root operation is a prunable range scan. A range
493    * scan is pruned if the ranges are such that only a subset of the fragments
494    * need to be scanned for matching tuples. (Currently, pushed scans can only
495    * be pruned if is there is a single range that maps to a single fragment.
496    */
497   enum {
498     /** Call NdbQueryOperationDef::checkPrunable() to determine prunability.*/
499     Prune_Unknown,
500     Prune_Yes, // The root is a prunable range scan.
501     Prune_No   // The root is not a prunable range scan.
502   } m_prunability;
503 
504   /** If m_prunability==Prune_Yes, this is the hash value of the single
505    * fragment that should be scanned.*/
506   Uint32 m_pruneHashVal;
507 
508   /** Allocator for NdbQueryOperationImpl objects.*/
509   NdbBulkAllocator m_operationAlloc;
510 
511   /** Allocator for NdbResultStream::TupleSet objects.*/
512   NdbBulkAllocator m_tupleSetAlloc;
513 
514   /** Allocator for NdbResultStream objects.*/
515   NdbBulkAllocator m_resultStreamAlloc;
516 
517   /** Allocator for pointers.*/
518   NdbBulkAllocator m_pointerAlloc;
519 
520   /** Allocator for result row buffers.*/
521   NdbBulkAllocator m_rowBufferAlloc;
522 
523   // Only constructable from factory ::buildQuery();
524   explicit NdbQueryImpl(
525              NdbTransaction& trans,
526              const NdbQueryDefImpl& queryDef);
527 
528   ~NdbQueryImpl();
529 
530   /** Release resources after scan has returned last available result */
531   void postFetchRelease();
532 
533   /** Navigate to the next result from the root operation. */
534   NdbQuery::NextResultOutcome nextRootResult(bool fetchAllowed, bool forceSend);
535 
536   /** Send SCAN_NEXTREQ signal to fetch another batch from a scan query
537    * @return 0 if send succeeded, -1 otherwise.
538    */
539   int sendFetchMore(NdbRootFragment* rootFrags[], Uint32 cnt,
540                     bool forceSend);
541 
542   /** Wait for more scan results which already has been REQuested to arrive.
543    * @return 0 if some rows did arrive, a negative value if there are errors
544    * (in m_error.code),
545    * and 1 of there are no more rows to receive.
546    */
547   FetchResult awaitMoreResults(bool forceSend);
548 
549   /** Check if we have received an error from TC, or datanodes.
550    * @return 'true' if an error is pending, 'false' otherwise.
551    */
552   bool hasReceivedError();                                   // Need mutex lock
553 
554   void setFetchTerminated(int aErrorCode, bool needClose);   // Need mutex lock
555 
556   /** Close cursor on TC */
557   int closeTcCursor(bool forceSend);
558 
559   /** Send SCAN_NEXTREQ(close) signal to close cursor on TC and datanodes.
560    *  @return #signals sent, -1 if error.
561    */
562   int sendClose(int nodeId);
563 
getInterface() const564   const NdbQuery& getInterface() const
565   { return m_interface; }
566 
getRoot() const567   NdbQueryOperationImpl& getRoot() const
568   { return getQueryOperation(0U); }
569 
570   /** A complete batch has been received for a given root fragment
571    *  Update whatever required before the appl. is allowed to navigate
572    *  the result.
573    *  @return: 'true' if its time to resume appl. threads
574    */
575   bool handleBatchComplete(NdbRootFragment& rootFrag);
576 
getPointerAlloc()577   NdbBulkAllocator& getPointerAlloc()
578   { return m_pointerAlloc; }
579 
580 }; // class NdbQueryImpl
581 
582 
583 /** This class contains data members for NdbQueryOperation, such that these
584  *  do not need to exposed in NdbQueryOperation.hpp. This class may be
585  *  changed without forcing the customer to recompile his application.
586  */
587 class NdbQueryOperationImpl {
588 
589   /** For debugging.*/
590   friend NdbOut& operator<<(NdbOut& out, const NdbQueryOperationImpl&);
591 
592   friend class NdbQueryImpl;
593 
594 public:
595   Uint32 getNoOfParentOperations() const;
596   NdbQueryOperationImpl& getParentOperation(Uint32 i) const;
597   NdbQueryOperationImpl* getParentOperation() const;
598 
599   Uint32 getNoOfChildOperations() const;
600   NdbQueryOperationImpl& getChildOperation(Uint32 i) const;
601 
602   /** A shorthand for getting the root operation. */
getRoot() const603   NdbQueryOperationImpl& getRoot() const
604   { return m_queryImpl.getRoot(); }
605 
getQueryDef() const606   const NdbQueryDefImpl& getQueryDef() const
607   { return m_queryImpl.getQueryDef(); }
608 
getQueryOperationDef() const609   const NdbQueryOperationDefImpl& getQueryOperationDef() const
610   { return m_operationDef; }
611 
612   // Get the entire query object which this operation is part of
getQuery() const613   NdbQueryImpl& getQuery() const
614   { return m_queryImpl; }
615 
616   NdbRecAttr* getValue(const char* anAttrName, char* resultBuffer);
617   NdbRecAttr* getValue(Uint32 anAttrId, char* resultBuffer);
618   NdbRecAttr* getValue(const NdbColumnImpl&, char* resultBuffer);
619 
620   int setResultRowBuf (const NdbRecord *rec,
621                        char* resBuffer,
622                        const unsigned char* result_mask);
623 
624   int setResultRowRef (const NdbRecord* rec,
625                        const char* & bufRef,
626                        const unsigned char* result_mask);
627 
628   NdbQuery::NextResultOutcome firstResult();
629 
630   NdbQuery::NextResultOutcome nextResult(bool fetchAllowed, bool forceSend);
631 
632   bool isRowNULL() const;    // Row associated with Operation is NULL value?
633 
634   bool isRowChanged() const; // Prev ::nextResult() on NdbQuery retrieved a new
635                              // value for this NdbQueryOperation
636 
637   /** Process result data for this operation. Return true if batch complete.*/
638   bool execTRANSID_AI(const Uint32* ptr, Uint32 len);
639 
640   /** Process absence of result data for this operation. (Only used when the
641    * root operation is a lookup.)
642    * @return true if query complete.*/
643   bool execTCKEYREF(const NdbApiSignal* aSignal);
644 
645   /** Called once per complete (within batch) fragment when a SCAN_TABCONF
646    * signal is received.
647    * @param tcPtrI not in use.
648    * @param rowCount Number of rows for this fragment, including all rows from
649    * descendant lookup operations.
650    * @param receiver The receiver object that shall process the results.*/
651   bool execSCAN_TABCONF(Uint32 tcPtrI, Uint32 rowCount, Uint32 nodeMask,
652                         NdbReceiver* receiver);
653 
getInterface() const654   const NdbQueryOperation& getInterface() const
655   { return m_interface; }
getInterface()656   NdbQueryOperation& getInterface()
657   { return m_interface; }
658 
659   /** Define result ordering for ordered index scan. It is an error to call
660    * this method on an operation that is not a scan, or to call it if an
661    * ordering was already set on the operation defintion by calling
662    * NdbQueryOperationDef::setOrdering().
663    * @param ordering The desired ordering of results.
664    * @return 0 if ok, -1 in case of error (call getNdbError() for details.)
665    */
666   int setOrdering(NdbQueryOptions::ScanOrdering ordering);
667 
getOrdering() const668   NdbQueryOptions::ScanOrdering getOrdering() const
669   { return m_ordering; }
670 
671   /**
672    * Set the number of fragments to be scanned in parallel. This only applies
673    * to table scans and non-sorted scans of ordered indexes. This method is
674    * only implemented for then root scan operation.
675    * @return 0 if ok, -1 in case of error (call getNdbError() for details.)
676    */
677   int setParallelism(Uint32 parallelism);
678 
679   /**
680    * Set the number of fragments to be scanned in parallel to the maximum
681    * possible value. This is the default for the root scan operation.
682    * @return 0 if ok, -1 in case of error (call getNdbError() for details.)
683    */
684   int setMaxParallelism();
685 
686   /**
687    * Let the system dynamically choose the number of fragments to scan in
688    * parallel. The system will try to choose a value that gives optimal
689    * performance. This is the default for all scans but the root scan. This
690    * method only implemented for non-root scan operations.
691    * @return 0 if ok, -1 in case of error (call getNdbError() for details.)
692    */
693   int setAdaptiveParallelism();
694 
695   /** Set the batch size (max rows per batch) for this operation. This
696    * only applies to scan operations, as lookup operations always will
697    * have the same batch size as its parent operation, or 1 if it is the
698    * root operation.
699    * @param batchSize Batch size (in number of rows). A value of 0 means
700    * use the default batch size.
701    * @return 0 if ok, -1 in case of error (call getNdbError() for details.)
702    */
703   int setBatchSize(Uint32 batchSize);
704 
705   /**
706    * Set the NdbInterpretedCode needed for defining a scan filter for
707    * this operation.
708    * It is an error to call this method on a lookup operation.
709    * @param code The interpreted code. This object is copied internally,
710    * meaning that 'code' may be destroyed as soon as this method returns.
711    * @return 0 if ok, -1 in case of error (call getNdbError() for details.)
712    */
713   int setInterpretedCode(const NdbInterpretedCode& code);
714   bool hasInterpretedCode() const;
715 
716   /** Verify magic number.*/
checkMagicNumber() const717   bool checkMagicNumber() const
718   { return m_magic == MAGIC; }
719 
720   /** Get the maximal number of rows that may be returned in a single
721    *  SCANREQ to the SPJ block.
722    */
getMaxBatchRows() const723   Uint32 getMaxBatchRows() const
724   { return m_maxBatchRows; }
725 
726   /** Get size of row as required to buffer it. */
727   Uint32 getRowSize() const;
728 
getNdbRecord() const729   const NdbRecord* getNdbRecord() const
730   { return m_ndbRecord; }
731 
732 private:
733 
734   STATIC_CONST (MAGIC = 0xfade1234);
735 
736   /** Interface for the application developer.*/
737   NdbQueryOperation m_interface;
738   /** For verifying pointers to this class.*/
739   const Uint32 m_magic;
740   /** NdbQuery to which this operation belongs. */
741   NdbQueryImpl& m_queryImpl;
742   /** The (transaction independent ) definition from which this instance
743    * was created.*/
744   const NdbQueryOperationDefImpl& m_operationDef;
745 
746   /* MAYBE: replace m_children with navigation via m_operationDef.getChildOperation().*/
747   /** Parent of this operation.*/
748   NdbQueryOperationImpl* m_parent;
749   /** Children of this operation.*/
750   Vector<NdbQueryOperationImpl*> m_children;
751 
752   /** Max rows (per resultStream) in a scan batch.*/
753   Uint32 m_maxBatchRows;
754 
755   /** Buffer for parameters in serialized format */
756   Uint32Buffer m_params;
757 
758   /** User specified buffer for final storage of result.*/
759   char* m_resultBuffer;
760   /** User specified pointer to application pointer that should be
761    * set to point to the current row inside a receiver buffer
762    * @see NdbQueryOperationImpl::setResultRowRef */
763   const char** m_resultRef;
764   /** True if this operation gave no result for the current row.*/
765   bool m_isRowNull;
766 
767   /** Result record & optional bitmask to disable read of selected cols.*/
768   const NdbRecord* m_ndbRecord;
769   const unsigned char* m_read_mask;
770 
771   /** Head & tail of NdbRecAttr list defined by this operation.
772     * Used for old-style result retrieval (using getValue()).*/
773   NdbRecAttr* m_firstRecAttr;
774   NdbRecAttr* m_lastRecAttr;
775 
776   /** Ordering of scan results (only applies to ordered index scans.)*/
777   NdbQueryOptions::ScanOrdering m_ordering;
778 
779   /** A scan filter is mapped to an interpeter code program, which is stored
780    * here. (This field is NULL if no scan filter has been defined.)*/
781   NdbInterpretedCode* m_interpretedCode;
782 
783   /** True if this operation reads from any disk column. */
784   bool m_diskInUserProjection;
785 
786   /** Number of scan fragments to read in parallel.
787    */
788   Uint32 m_parallelism;
789 
790   /** Size of each result row (in bytes).*/
791   mutable Uint32 m_rowSize;
792 
793   explicit NdbQueryOperationImpl(NdbQueryImpl& queryImpl,
794                                  const NdbQueryOperationDefImpl& def);
795   ~NdbQueryOperationImpl();
796 
797   /** Copy NdbRecAttr and/or NdbRecord results from stream into appl. buffers */
798   void fetchRow(NdbResultStream& resultStream);
799 
800   /** Set result for this operation and all its descendand child
801    *  operations to NULL.
802    */
803   void nullifyResult();
804 
805   /** Release resources after scan has returned last available result */
806   void postFetchRelease();
807 
808   /** Count number of descendant operations (excluding the operation itself) */
809   Int32 getNoOfDescendantOperations() const;
810 
811   /**
812    * Count number of leaf operations below/including self
813    */
814   Uint32 getNoOfLeafOperations() const;
815 
816   /** Serialize parameter values.
817    *  @return possible error code.*/
818   int serializeParams(const NdbQueryParamValue* paramValues);
819 
820   int serializeProject(Uint32Buffer& attrInfo);
821 
822   Uint32 calculateBatchedRows(const NdbQueryOperationImpl* closestScan);
823   void setBatchedRows(Uint32 batchedRows);
824 
825   /** Prepare ATTRINFO for execution. (Add execution params++)
826    *  @return possible error code.*/
827   int prepareAttrInfo(Uint32Buffer& attrInfo);
828 
829   /**
830    * Expand keys and bounds for the root operation into the KEYINFO section.
831    * @param keyInfo Actuall KEYINFO section the key / bounds are
832    *                put into
833    * @param actualParam Instance values for NdbParamOperands.
834    * Returns: 0 if OK, or possible an errorcode.
835    */
836   int prepareKeyInfo(Uint32Buffer& keyInfo,
837                      const NdbQueryParamValue* actualParam);
838 
839   int prepareLookupKeyInfo(
840                      Uint32Buffer& keyInfo,
841                      const NdbQueryOperandImpl* const keys[],
842                      const NdbQueryParamValue* actualParam);
843 
844   int prepareIndexKeyInfo(
845                      Uint32Buffer& keyInfo,
846                      const NdbQueryOperationDefImpl::IndexBound* bounds,
847                      const NdbQueryParamValue* actualParam);
848 
849   /** Return I-value (for putting in object map) for a receiver pointing back
850    * to this object. TCKEYCONF is processed by first looking up an
851    * NdbReceiver instance in the object map, and then following
852    * NdbReceiver::m_query_operation_impl here.*/
853   Uint32 getIdOfReceiver() const;
854 
855   /**
856    * If the operation has a scan filter, append the corresponding
857    * interpreter code to a buffer.
858    * @param attrInfo The buffer to which the code should be appended.
859    * @return possible error code */
860   int prepareInterpretedCode(Uint32Buffer& attrInfo) const;
861 
862   /** Returns true if this operation reads from any disk column. */
diskInUserProjection() const863   bool diskInUserProjection() const
864   { return m_diskInUserProjection; }
865 
866 }; // class NdbQueryOperationImpl
867 
868 
869 #endif
870