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 St, Fifth Floor, Boston, MA 02110-1301  USA
23 */
24 
25 
26 #ifndef NdbQueryBuilderImpl_H
27 #define NdbQueryBuilderImpl_H
28 
29 /* Query-related error codes. */
30 #define QRY_REQ_ARG_IS_NULL 4800
31 #define QRY_TOO_FEW_KEY_VALUES 4801
32 #define QRY_TOO_MANY_KEY_VALUES 4802
33 #define QRY_OPERAND_HAS_WRONG_TYPE 4803
34 #define QRY_CHAR_OPERAND_TRUNCATED 4804
35 #define QRY_NUM_OPERAND_RANGE 4805
36 #define QRY_MULTIPLE_PARENTS 4806
37 #define QRY_UNKONWN_PARENT 4807
38 #define QRY_UNKNOWN_COLUMN 4808
39 #define QRY_UNRELATED_INDEX 4809
40 #define QRY_WRONG_INDEX_TYPE 4810
41 #define QRY_OPERAND_ALREADY_BOUND 4811
42 #define QRY_DEFINITION_TOO_LARGE 4812
43 #define QRY_SEQUENTIAL_SCAN_SORTED 4813
44 #define QRY_RESULT_ROW_ALREADY_DEFINED 4814
45 #define QRY_HAS_ZERO_OPERATIONS 4815
46 #define QRY_IN_ERROR_STATE 4816
47 #define QRY_ILLEGAL_STATE 4817
48 #define QRY_WRONG_OPERATION_TYPE 4820
49 #define QRY_SCAN_ORDER_ALREADY_SET 4821
50 #define QRY_PARAMETER_HAS_WRONG_TYPE 4822
51 #define QRY_CHAR_PARAMETER_TRUNCATED 4823
52 #define QRY_MULTIPLE_SCAN_SORTED 4824
53 #define QRY_BATCH_SIZE_TOO_SMALL 4825
54 
55 #ifdef __cplusplus
56 #include <Vector.hpp>
57 #include <Bitmask.hpp>
58 #include "NdbQueryBuilder.hpp"
59 #include "NdbIndexScanOperation.hpp"
60 #include "ndb_limits.h"
61 
62 // Forward declared
63 class NdbTableImpl;
64 class NdbIndexImpl;
65 class NdbColumnImpl;
66 class NdbQueryBuilderImpl;
67 class NdbQueryDefImpl;
68 class NdbQueryOperationDefImpl;
69 class NdbQueryParamValue;
70 class NdbParamOperandImpl;
71 class NdbConstOperandImpl;
72 class NdbLinkedOperandImpl;
73 
74 // For debuggging.
75 //#define TRACE_SERIALIZATION
76 
77 /** A buffer for holding serialized data.
78  *
79  *  Data is normaly appended to the end of this buffer by several variants
80  *  of ::append(). A chunk of memory may also be allocated (at end of buffer)
81  *  with ::alloc(). The buffer has a small local storage likely to be sufficent
82  *  for most buffer usage. If required it will allocate a buffer extension to
83  *  satisfy larger buffer requests.
84  *
85  * NOTE: When buffer grows, it contents may be relocated ta another memory area.
86  *       Pointers returned to ::alloc'ed objects or ::addr() request are therefore
87  *       not valid after another ::append() or ::alloc() has been performed.
88  *       If pointer persistency is required, use ::getSize() to store the current
89  *       end of buffer before the persistent object is allocated or appended.
90  *       You may then later use 'size' as a handle to ::addr() to get the address.
91  *
92  * NOTE: If memory allocation fails during append / alloc, a 'memoryExhausted' state
93  *       is set. Further allocation or append will then fail or be ignored. Before
94  *       using the contents in the Uint32Buffer, always check ::isMemoryExhausted()
95  *       to validate the contents of your buffer.
96  */
97 class Uint32Buffer{
98 public:
99 
100 //#define TEST_Uint32Buffer
101 
102 #if defined(TEST_Uint32Buffer)
103   STATIC_CONST(initSize = 1);  // Small size to force test of buffer expand.
104 #else
105   STATIC_CONST(initSize = 32); // Initial buffer size, extend on demand but probably sufficent
106 #endif
107 
Uint32Buffer()108   explicit Uint32Buffer():
109     m_array(m_local),
110     m_avail(initSize),
111     m_size(0),
112     m_memoryExhausted(false),
113     m_bytesLeft(0)
114   {}
115 
~Uint32Buffer()116   ~Uint32Buffer() {
117     if (unlikely(m_array != m_local)) {
118       delete[] m_array;
119     }
120   }
121 
122   /**
123    *  Explicit release of buffer to shrink memory footprint.
124    */
releaseExtend()125   void releaseExtend() {
126     if (unlikely(m_array != m_local)) {
127       delete[] m_array;
128     }
129     m_array = NULL;
130     m_size = 0;
131   }
132 
133   /**
134    * Allocate a buffer extension at end of this buffer.
135    * NOTE: Return NULL if allocation fails and set
136    *       isMemoryExhausted. This will also cause further
137    *       alloc() / append() to be skipped.
138    */
alloc(Uint32 count)139   Uint32* alloc(Uint32 count) {
140     Uint32 reqSize = m_size+count;
141     if(unlikely(reqSize >= m_avail)) {
142       if (unlikely(m_memoryExhausted)) {
143         return NULL;
144       }
145 #if defined(TEST_Uint32Buffer)
146       Uint32 newSize = reqSize; // -> Always expand on next alloc
147 #else
148       Uint32 newSize = reqSize*2;
149 #endif
150 //    ndbout << "Uint32Buffer::alloc() Extend buffer from: " << m_avail
151 //           << ", to: " << newSize << endl;
152       Uint32* newBuf = new Uint32[newSize];
153       if (likely(newBuf!=NULL)) {
154         assert(newBuf);
155         memcpy (newBuf, m_array, m_size*sizeof(Uint32));
156         if (m_array != m_local) {
157           delete[] m_array;
158         }
159         m_array = newBuf;
160         m_avail = static_cast<Uint32>(newSize);
161       } else {
162         m_size = m_avail;
163         m_memoryExhausted = true;
164         return NULL;
165       }
166     }
167     Uint32* extend = &m_array[m_size];
168     m_size += static_cast<Uint32>(count);
169     return extend;
170   }
171 
172   /** Put the idx'th element already allocated.
173    */
put(Uint32 idx,Uint32 value)174   void put(Uint32 idx, Uint32 value) {
175     assert(idx < m_size);
176     m_array[idx] = value;
177   }
178 
179   /** append 'src' word to end of this buffer
180    */
append(const Uint32 src)181   void append(const Uint32 src) {
182     m_bytesLeft = 0;
183     if (likely(m_size < m_avail)) {
184       m_array[m_size++] = src;
185     } else {
186       Uint32* dst = alloc(1);
187       if (likely(dst!=NULL))
188         *dst = src;
189     }
190   }
191 
192   /** append 'src' buffer to end of this buffer
193    */
append(const Uint32Buffer & src)194   void append(const Uint32Buffer& src) {
195     assert (!src.isMemoryExhausted());
196     m_bytesLeft = 0;
197     Uint32 len = src.getSize();
198     if (likely(len > 0)) {
199       Uint32* dst = alloc(len);
200       if (likely(dst!=NULL)) {
201         memcpy(dst, src.addr(), len*sizeof(Uint32));
202       }
203     }
204   }
205 
206   /** append 'src' *bytes* to end of this buffer
207    *  Zero pad possibly odd bytes in last Uint32 word
208    */
appendBytes(const void * src,Uint32 len)209   void appendBytes(const void* src, Uint32 len) {
210     if (likely(len > 0)) {
211       Uint32 wordCount =
212         static_cast<Uint32>((len + sizeof(Uint32)-1 - m_bytesLeft)
213                             / sizeof(Uint32));
214       Uint32* dst = alloc(wordCount);
215       if (likely(dst!=NULL)) {
216         // Copy src
217         Uint8* const start = reinterpret_cast<Uint8*>(dst) - m_bytesLeft;
218         memcpy(start, src, len);
219         m_bytesLeft = (m_bytesLeft - len) % sizeof(Uint32);
220         // Make sure that any trailing bytes in the last word are zero.
221         bzero(start + len, m_bytesLeft);
222       }
223     }
224   }
225 
226   /** Skip remaining bytes in m_array[m_size-1], so that a subsequent
227    * appendBytes() starts at a word boundary.*/
skipRestOfWord()228   void skipRestOfWord()
229   { m_bytesLeft = 0; }
230 
addr(Uint32 idx=0)231   Uint32* addr(Uint32 idx=0) {
232     return (likely(!m_memoryExhausted && m_size>idx)) ?&m_array[idx] :NULL;
233   }
addr(Uint32 idx=0) const234   const Uint32* addr(Uint32 idx=0) const {
235     return (likely(!m_memoryExhausted && m_size>idx)) ?&m_array[idx] :NULL;
236   }
237 
238   /** Get the idx'th element. Make sure there is space for 'count' elements.*/
get(Uint32 idx) const239   Uint32 get(Uint32 idx) const {
240     assert(idx < m_size);
241     return m_array[idx];
242   }
243 
244   /** Check for possible memory alloc failure during build. */
isMemoryExhausted() const245   bool isMemoryExhausted() const {
246     return m_memoryExhausted;
247   }
248 
getSize() const249   Uint32 getSize() const {
250     return m_size;
251   }
252 
253 private:
254   /** Should not be copied, nor assigned.*/
255   Uint32Buffer(Uint32Buffer&);
256   Uint32Buffer& operator=(Uint32Buffer&);
257 
258 private:
259   Uint32  m_local[initSize]; // Initial static bufferspace
260   Uint32* m_array;           // Refers m_local initially, or extended large buffer
261   Uint32  m_avail;           // Available buffer space
262   Uint32  m_size;            // Actuall size <= m_avail
263   bool m_memoryExhausted;
264   /** Number of remaining bytes (0-3) in m_array[m_size-1].*/
265   Uint32 m_bytesLeft;
266 };
267 
268 
269 class NdbQueryOptionsImpl
270 {
271   friend class NdbQueryOptions;
272   friend class NdbQueryOperationDefImpl;
273 
274 public:
NdbQueryOptionsImpl()275   explicit NdbQueryOptionsImpl()
276   : m_matchType(NdbQueryOptions::MatchAll),
277     m_scanOrder(NdbQueryOptions::ScanOrdering_void),
278     m_parent(NULL),
279     m_interpretedCode(NULL)
280   {};
281   NdbQueryOptionsImpl(const NdbQueryOptionsImpl&);
282   ~NdbQueryOptionsImpl();
283 
284 private:
285   NdbQueryOptions::MatchType     m_matchType;
286   NdbQueryOptions::ScanOrdering  m_scanOrder;
287   NdbQueryOperationDefImpl*      m_parent;
288   const NdbInterpretedCode*      m_interpretedCode;
289 
290   /**
291    * Assign NdbInterpretedCode by taking a deep copy of 'src'
292    * @return possible error code.
293    */
294   int copyInterpretedCode(const NdbInterpretedCode& src);
295 
296   NdbQueryOptionsImpl&operator=(const NdbQueryOptionsImpl&);  // Not impl.
297 };
298 
299 
300 ////////////////////////////////////////////////
301 // Implementation of NdbQueryOperation interface
302 ////////////////////////////////////////////////
303 
304 class NdbQueryOperationDefImpl
305 {
306   friend class NdbQueryOperationDef;
307   friend class NdbQueryOperationImpl;
308   friend class NdbQueryImpl;
309 
310 public:
311 
312   struct IndexBound {     // Limiting 'bound ' definition for indexScan
313     NdbQueryOperandImpl* low[MAX_ATTRIBUTES_IN_INDEX];
314     NdbQueryOperandImpl* high[MAX_ATTRIBUTES_IN_INDEX];
315     Uint32 lowKeys, highKeys;
316     bool lowIncl, highIncl;
317   };
318 
319   /* Currently only a single parent is supported */
getNoOfParentOperations() const320   Uint32 getNoOfParentOperations() const
321   { return (m_parent) ? 1 : 0; }
322 
getParentOperation(Uint32 i) const323   NdbQueryOperationDefImpl& getParentOperation(Uint32 i) const
324   { assert(i==0 && m_parent!=NULL);
325     return *m_parent;
326   }
327 
getParentOperation() const328   NdbQueryOperationDefImpl* getParentOperation() const
329   { return m_parent;
330   }
331 
getNoOfChildOperations() const332   Uint32 getNoOfChildOperations() const
333   { return m_children.size(); }
334 
getChildOperation(Uint32 i) const335   NdbQueryOperationDefImpl& getChildOperation(Uint32 i) const
336   { return *m_children[i]; }
337 
getTable() const338   const NdbTableImpl& getTable() const
339   { return m_table; }
340 
getName() const341   const char* getName() const
342   { return m_ident; }
343 
getMatchType() const344   enum NdbQueryOptions::MatchType getMatchType() const
345   { return m_options.m_matchType; }
346 
getOrdering() const347   enum NdbQueryOptions::ScanOrdering getOrdering() const
348   { return m_options.m_scanOrder; }
349 
getInterpretedCode() const350   const NdbInterpretedCode* getInterpretedCode() const
351   { return m_options.m_interpretedCode; }
352 
assignQueryOperationId(Uint32 & nodeId)353   Uint32 assignQueryOperationId(Uint32& nodeId)
354   { if (getType()==NdbQueryOperationDef::UniqueIndexAccess) nodeId++;
355     m_id = nodeId++;
356     return m_id;
357   }
358 
359   // Establish a linked parent <-> child relationship with this operation
360   int linkWithParent(NdbQueryOperationDefImpl* parentOp);
361 
362   /**
363    * Register a linked reference to a column from operation
364    * @param[in] column Column to refer.
365    * @param[out] error Possible error code.
366    * @return position in list of refered columns available from
367    * this (parent) operation. Child ops later refer linked
368    * columns by its position in this list.
369    */
370   Uint32 addColumnRef(const NdbColumnImpl* column, int& error);
371 
372   /**
373    * Register a param operand which is refered by this operation.
374    * Param values are supplied pr. operation when code is serialized.
375    * @param[in] param Parameter to add.
376    * @return Possible error code.
377    */
378   int addParamRef(const NdbParamOperandImpl* param);
379 
getNoOfParameters() const380   Uint32 getNoOfParameters() const
381   { return m_params.size(); }
382 
getParameter(Uint32 ix) const383   const NdbParamOperandImpl& getParameter(Uint32 ix) const
384   { return *m_params[ix]; }
385 
getIndex() const386   virtual const NdbIndexImpl* getIndex() const
387   { return NULL; }
388 
getKeyOperands() const389   virtual const NdbQueryOperandImpl* const* getKeyOperands() const
390   { return NULL; }
391 
getBounds() const392   virtual const IndexBound* getBounds() const
393   { return NULL; }
394 
395   // Return 'true' is query type is a multi-row scan
396   virtual bool isScanOperation() const = 0;
397 
398   virtual const NdbQueryOperationDef& getInterface() const = 0;
399 
400   /** Make a serialized representation of this operation, corresponding to
401    * the struct QueryNode type.
402    * @return Possible error code.
403    */
404   virtual int serializeOperation(Uint32Buffer& serializedTree) = 0;
405 
406   /** Find the projection that should be sent to the SPJ block. This should
407    * contain the attributes needed to instantiate all child operations.
408    */
getSPJProjection() const409   const Vector<const NdbColumnImpl*>& getSPJProjection() const {
410     return m_spjProjection;
411   }
412 
checkPrunable(const Uint32Buffer & keyInfo,Uint32 shortestBound,bool & isPruned,Uint32 & hashValue) const413   virtual int checkPrunable(const Uint32Buffer& keyInfo,
414                             Uint32  shortestBound,
415                             bool&   isPruned,
416 			    Uint32& hashValue) const {
417     isPruned = false;
418     return 0;
419   }
420 
421   virtual ~NdbQueryOperationDefImpl();
422 
423 protected:
424   explicit NdbQueryOperationDefImpl (const NdbTableImpl& table,
425                                      const NdbQueryOptionsImpl& options,
426                                      const char* ident,
427                                      Uint32 ix,
428                                      int& error);
429 public:
430   // Get the ordinal position of this operation within the query def.
getQueryOperationIx() const431   Uint32 getQueryOperationIx() const
432   { return m_ix; }
433 
434   // Get id of node as known inside queryTree
getQueryOperationId() const435   Uint32 getQueryOperationId() const
436   { return m_id; }
437 
438   // Get type of query operation
439   virtual NdbQueryOperationDef::Type getType() const = 0;
440 
441   /** Print query tree graph to trace file (using recursion).
442    * @param depth Number of ancestor nodes that this node has.
443    * @param hasMoreSiblingsMask The n'th bit should be set if the n'th ancestor
444    * (counted from the root) has more sibling nodes.
445    */
446   void printTree(
447            Uint32 depth,
448            Bitmask<(NDB_SPJ_MAX_TREE_NODES+31)/32> hasMoreSiblingsMask) const;
449 
450 protected:
451   // QueryTree building:
452   // Append list of parent nodes to serialized code
453   Uint32 appendParentList(Uint32Buffer& serializedDef) const;
454 
455   // Append list of columns required by SPJ to instantiate child operations.
456   Uint32 appendChildProjection(Uint32Buffer& serializedDef) const;
457 
458 protected:
459   /** True if enclosing query has been prepared.*/
460   bool m_isPrepared;
461 
462   /**
463    * True if the projection for instantiating child operations contains any
464    * disk columns.
465    */
466   bool m_diskInChildProjection;
467 
468 private:
469   bool isChildOf(const NdbQueryOperationDefImpl* parentOp) const;
470 
471   /**
472    * Register a linked child refering specified operation
473    * @param[in] child Child operation to add.
474    * @return Possible error code.
475    */
476   int addChild(NdbQueryOperationDefImpl* child);
477 
478   // Remove a linked child refering specified operation
479   void removeChild(const NdbQueryOperationDefImpl*);
480 
481 private:
482   const NdbTableImpl& m_table;
483   const char* const m_ident; // Optional name specified by aplication
484   const Uint32 m_ix;         // Index of this operation within operation array
485   Uint32       m_id;         // Operation id when materialized into queryTree.
486                              // If op has index, index id is 'm_id-1'.
487 
488   // Optional (or default) options specified when building query:
489   // - Scan order which may specify ascending or descending scan order
490   // - Match type used for hinting on optimal inner-, outer-, semijoin exec.
491   const NdbQueryOptionsImpl m_options;
492 
493   // parent pointer & child ptr. vector contains dependencies
494   // as defined with linkedValues
495   NdbQueryOperationDefImpl* m_parent;
496   Vector<NdbQueryOperationDefImpl*> m_children;
497 
498   // Params required by this operation
499   Vector<const NdbParamOperandImpl*> m_params;
500 
501   // Column from this operation required by its child operations
502   Vector<const NdbColumnImpl*> m_spjProjection;
503 }; // class NdbQueryOperationDefImpl
504 
505 
506 class NdbQueryScanOperationDefImpl :
507   public NdbQueryOperationDefImpl
508 {
509 public:
510   explicit NdbQueryScanOperationDefImpl (
511                            const NdbTableImpl& table,
512                            const NdbQueryOptionsImpl& options,
513                            const char* ident,
514                            Uint32      ix,
515                            int& error);
516 
isScanOperation() const517   virtual bool isScanOperation() const
518   { return true; }
519 
520 protected:
521   int serialize(Uint32Buffer& serializedDef,
522                 const NdbTableImpl& tableOrIndex);
523 
524   // Append pattern for creating complete range bounds to serialized code
appendBoundPattern(Uint32Buffer & serializedDef) const525   virtual Uint32 appendBoundPattern(Uint32Buffer& serializedDef) const
526   { return 0; }
527 
appendPrunePattern(Uint32Buffer & serializedDef) const528   virtual Uint32 appendPrunePattern(Uint32Buffer& serializedDef) const
529   { return 0; }
530 
531 }; // class NdbQueryScanOperationDefImpl
532 
533 
534 class NdbQueryIndexScanOperationDefImpl : public NdbQueryScanOperationDefImpl
535 {
536   friend class NdbQueryBuilder;  // Allow privat access from builder interface
537 
538 public:
getIndex() const539   virtual const NdbIndexImpl* getIndex() const
540   { return &m_index; }
541 
542   virtual int serializeOperation(Uint32Buffer& serializedDef);
543 
getInterface() const544   virtual const NdbQueryIndexScanOperationDef& getInterface() const
545   { return m_interface; }
546 
getType() const547   virtual NdbQueryOperationDef::Type getType() const
548   { return NdbQueryOperationDef::OrderedIndexScan; }
549 
550   virtual int checkPrunable(const Uint32Buffer& keyInfo,
551                             Uint32  shortestBound,
552                             bool&   isPruned,
553                             Uint32& hashValue) const;
554 
getBounds() const555   virtual const IndexBound* getBounds() const
556   { return &m_bound; }
557 
558 protected:
559   // Append pattern for creating complete range bounds to serialized code
560   virtual Uint32 appendBoundPattern(Uint32Buffer& serializedDef) const;
561 
562   virtual Uint32 appendPrunePattern(Uint32Buffer& serializedDef) const;
563 
564 private:
565 
566   explicit NdbQueryIndexScanOperationDefImpl (
567                            const NdbIndexImpl& index,
568                            const NdbTableImpl& table,
569                            const NdbQueryIndexBound* bound,
570                            const NdbQueryOptionsImpl& options,
571                            const char* ident,
572                            Uint32      ix,
573                            int& error);
574 
575   // Append pattern for creating a single bound value to serialized code
576   Uint32 appendBoundValue( Uint32Buffer& serializedDef,
577                            NdbIndexScanOperation::BoundType type,
578                            const NdbQueryOperandImpl* value,
579                            int& paramCnt) const;
580 
581 private:
582   NdbQueryIndexScanOperationDef m_interface;
583   const NdbIndexImpl& m_index;
584 
585   /** True if there is a set of bounds.*/
586   IndexBound m_bound;
587 }; // class NdbQueryIndexScanOperationDefImpl
588 
589 
590 class NdbQueryDefImpl
591 {
592   friend class NdbQueryDef;
593 
594 public:
595   explicit NdbQueryDefImpl(const Vector<NdbQueryOperationDefImpl*>& operations,
596                            const Vector<NdbQueryOperandImpl*>& operands,
597                            int& error);
598   ~NdbQueryDefImpl();
599 
600   // Entire query is a scan iff root operation is scan.
601   // May change in the future as we implement more complicated SPJ operations.
isScanQuery() const602   bool isScanQuery() const
603   { return m_operations[0]->isScanOperation(); }
604 
605   NdbQueryDef::QueryType getQueryType() const;
606 
getNoOfOperations() const607   Uint32 getNoOfOperations() const
608   { return m_operations.size(); }
609 
610   // Get a specific NdbQueryOperationDef by ident specified
611   // when the NdbQueryOperationDef was created.
getQueryOperation(Uint32 index) const612   const NdbQueryOperationDefImpl& getQueryOperation(Uint32 index) const
613   { return *m_operations[index]; }
614 
615   const NdbQueryOperationDefImpl* getQueryOperation(const char* ident) const;
616 
getInterface() const617   const NdbQueryDef& getInterface() const
618   { return m_interface; }
619 
620   /** Get serialized representation of query definition.*/
getSerialized()621   Uint32Buffer& getSerialized()
622   { return m_serializedDef; }
623 
624   /** Get serialized representation of query definition.*/
getSerialized() const625   const Uint32Buffer& getSerialized() const
626   { return m_serializedDef; }
627 
628 private:
629   NdbQueryDef m_interface;
630 
631   Vector<NdbQueryOperationDefImpl*> m_operations;
632   Vector<NdbQueryOperandImpl*> m_operands;
633   Uint32Buffer m_serializedDef;
634 }; // class NdbQueryDefImpl
635 
636 
637 class NdbQueryBuilderImpl
638 {
639   friend class NdbQueryBuilder;
640 
641 public:
642   ~NdbQueryBuilderImpl();
643   explicit NdbQueryBuilderImpl();
644 
645   const NdbQueryDefImpl* prepare();
646 
647   const NdbError& getNdbError() const;
648 
649   void setErrorCode(int aErrorCode);
650 
651 private:
hasError() const652   bool hasError() const
653   { return m_hasError; }
654 
655   /**
656    * Add an operand to m_operands. Set an error code if operand
657    * is null or if adding it to m_operands fails.
658    * @param[in] operand to add (may be NULL).
659    * @return Operand interface (or NULL if there was an error.)
660    */
661   NdbQueryOperand* addOperand(NdbQueryOperandImpl* operand);
662 
663   /**
664    * Take ownership of specified object: From now on it is the
665    * responsibility of this NdbQueryBuilderImpl to manage the
666    * lifetime of the object. If takeOwnership() fails, the
667    * specified object is deleted before it returns.
668    * @param[in] operand to take ownership for (may be NULL).
669    * @return 0 if ok, else there has been an 'Err_MemoryAlloc'
670    */
671   int takeOwnership(NdbQueryOperandImpl*);
672   int takeOwnership(NdbQueryOperationDefImpl*);
673 
674   bool contains(const NdbQueryOperationDefImpl*);
675 
676   NdbQueryBuilder m_interface;
677   NdbError m_error;
678 
679   Vector<NdbQueryOperationDefImpl*> m_operations;
680   Vector<NdbQueryOperandImpl*> m_operands;
681   Uint32 m_paramCnt;
682   /** True if there was an error that prevents further use of this object.*/
683   bool m_hasError;
684 }; // class NdbQueryBuilderImpl
685 
686 
687 //////////////////////////////////////////////
688 // Implementation of NdbQueryOperand interface
689 //////////////////////////////////////////////
690 
691 // Baseclass for the QueryOperand implementation
692 class NdbQueryOperandImpl
693 {
694   friend class NdbQueryBuilderImpl;
695 public:
696 
697   /** The type of an operand. This corresponds to the set of subclasses
698    * of NdbQueryOperandImpl.
699    */
700   enum Kind {
701     Linked,
702     Param,
703     Const
704   };
705 
getColumn() const706   const NdbColumnImpl* getColumn() const
707   { return m_column; }
708 
bindOperand(const NdbColumnImpl & column,NdbQueryOperationDefImpl & operation)709   virtual int bindOperand(const NdbColumnImpl& column,
710                           NdbQueryOperationDefImpl& operation)
711   { if (m_column  && m_column != &column)
712       // Already bounded to a different column
713       return QRY_OPERAND_ALREADY_BOUND;
714     m_column = &column;
715     return 0;
716   }
717 
getKind() const718   Kind getKind() const
719   { return m_kind; }
720 
721   virtual NdbQueryOperand& getInterface() = 0;
722 
723 protected:
724   friend NdbQueryBuilderImpl::~NdbQueryBuilderImpl();
725   friend NdbQueryDefImpl::~NdbQueryDefImpl();
726 
~NdbQueryOperandImpl()727   virtual ~NdbQueryOperandImpl(){};
728 
NdbQueryOperandImpl(Kind kind)729   NdbQueryOperandImpl(Kind kind)
730     : m_column(0),
731       m_kind(kind)
732   {}
733 
734 protected:
735   const NdbColumnImpl* m_column;       // Initial NULL, assigned w/ bindOperand()
736 
737   /** This is used to tell the type of an NdbQueryOperand. This allow safe
738    * downcasting to a subclass.
739    */
740   const Kind m_kind;
741 }; // class NdbQueryOperandImpl
742 
743 
744 class NdbLinkedOperandImpl : public NdbQueryOperandImpl
745 {
746   friend class NdbQueryBuilder;  // Allow privat access from builder interface
747 
748 public:
getParentOperation() const749   const NdbQueryOperationDefImpl& getParentOperation() const
750   { return m_parentOperation; }
751 
752   // 'LinkedSrc' is index into parent op's spj-projection list where
753   // the refered column value is available
getLinkedColumnIx() const754   Uint32 getLinkedColumnIx() const
755   { return m_parentColumnIx; }
756 
getParentColumn() const757   const NdbColumnImpl& getParentColumn() const
758   { return *m_parentOperation.getSPJProjection()[m_parentColumnIx]; }
759 
getInterface()760   virtual NdbQueryOperand& getInterface()
761   { return m_interface; }
762 
763   virtual int bindOperand(const NdbColumnImpl& column,
764                           NdbQueryOperationDefImpl& operation);
765 
766 private:
NdbLinkedOperandImpl(NdbQueryOperationDefImpl & parent,Uint32 columnIx)767   NdbLinkedOperandImpl (NdbQueryOperationDefImpl& parent,
768                         Uint32 columnIx)
769    : NdbQueryOperandImpl(Linked),
770      m_interface(*this),
771      m_parentOperation(parent),
772      m_parentColumnIx(columnIx)
773   {}
774 
775   NdbLinkedOperand m_interface;
776   NdbQueryOperationDefImpl& m_parentOperation;
777   const Uint32 m_parentColumnIx;
778 }; // class NdbLinkedOperandImpl
779 
780 
781 class NdbParamOperandImpl : public NdbQueryOperandImpl
782 {
783   friend class NdbQueryBuilder;  // Allow privat access from builder interface
784 
785 public:
getName() const786   const char* getName() const
787   { return m_name; }
788 
getParamIx() const789   Uint32 getParamIx() const
790   { return m_paramIx; }
791 
getInterface()792   virtual NdbQueryOperand& getInterface()
793   { return m_interface; }
794 
795   virtual int bindOperand(const NdbColumnImpl& column,
796                           NdbQueryOperationDefImpl& operation);
797 
798 private:
NdbParamOperandImpl(const char * name,Uint32 paramIx)799   NdbParamOperandImpl (const char* name, Uint32 paramIx)
800    : NdbQueryOperandImpl(Param),
801      m_interface(*this),
802      m_name(name),
803      m_paramIx(paramIx)
804   {}
805 
806   NdbParamOperand m_interface;
807   const char* const m_name;     // Optional parameter name or NULL
808   const Uint32 m_paramIx;
809 }; // class NdbParamOperandImpl
810 
811 
812 class NdbConstOperandImpl : public NdbQueryOperandImpl
813 {
814   friend class NdbQueryBuilder;  // Allow privat access from builder interface
815 public:
getSizeInBytes() const816   Uint32 getSizeInBytes() const
817   { return m_converted.len; }
getAddr() const818   const void* getAddr() const
819   { return likely(m_converted.buffer==NULL) ? &m_converted.val : m_converted.buffer; }
820 
getInterface()821   virtual NdbQueryOperand& getInterface()
822   { return m_interface; }
823 
824   virtual int bindOperand(const NdbColumnImpl& column,
825                           NdbQueryOperationDefImpl& operation);
826 
827 protected:
NdbConstOperandImpl()828   NdbConstOperandImpl ()
829     : NdbQueryOperandImpl(Const),
830       m_converted(),
831       m_interface(*this)
832   {}
833 
834   #define UNDEFINED_CONVERSION	\
835   { return QRY_OPERAND_HAS_WRONG_TYPE; }
836 
837   virtual int convertUint8()  UNDEFINED_CONVERSION;
838   virtual int convertInt8()   UNDEFINED_CONVERSION;
839   virtual int convertUint16() UNDEFINED_CONVERSION;
840   virtual int convertInt16()  UNDEFINED_CONVERSION;
841   virtual int convertUint24() UNDEFINED_CONVERSION;
842   virtual int convertInt24()  UNDEFINED_CONVERSION;
843   virtual int convertUint32() UNDEFINED_CONVERSION;
844   virtual int convertInt32()  UNDEFINED_CONVERSION;
845   virtual int convertUint64() UNDEFINED_CONVERSION;
846   virtual int convertInt64()  UNDEFINED_CONVERSION;
847   virtual int convertFloat()  UNDEFINED_CONVERSION;
848   virtual int convertDouble() UNDEFINED_CONVERSION
849 
850   virtual int convertUDec()   UNDEFINED_CONVERSION;
851   virtual int convertDec()    UNDEFINED_CONVERSION;
852 
853   virtual int convertBit()    UNDEFINED_CONVERSION;
854   virtual int convertChar()   UNDEFINED_CONVERSION;
855   virtual int convertVChar()  UNDEFINED_CONVERSION;
856   virtual int convertLVChar() UNDEFINED_CONVERSION;
857   virtual int convertBin()    UNDEFINED_CONVERSION;
858   virtual int convertVBin()   UNDEFINED_CONVERSION;
859   virtual int convertLVBin()  UNDEFINED_CONVERSION;
860 
861   virtual int convertDate()   UNDEFINED_CONVERSION;
862   virtual int convertDatetime() UNDEFINED_CONVERSION;
863   virtual int convertTime()   UNDEFINED_CONVERSION;
864   virtual int convertYear()   UNDEFINED_CONVERSION;
865   virtual int convertTimestamp() UNDEFINED_CONVERSION;
866 
867   virtual int convert2ColumnType();
868 
869   /** Values converted to datatype format as expected by bound column
870     * (available through ::getColumn())
871     */
872   class ConvertedValue {
873   public:
ConvertedValue()874     ConvertedValue()  : len(0), buffer(NULL) {};
~ConvertedValue()875     ~ConvertedValue() {
876       if (buffer) delete[] ((char*)buffer);
877     };
878 
getCharBuffer(Uint32 size)879     char* getCharBuffer(Uint32 size) {
880       char* dst = val.shortChar;
881       if (unlikely(size > sizeof(val.shortChar))) {
882         dst = new char[size];
883         buffer = dst;
884       }
885       len = size;
886       return dst;
887     }
888 
889     STATIC_CONST(maxShortChar = 32);
890 
891     union
892     {
893       Uint8     uint8;
894       Int8      int8;
895       Uint16    uint16;
896       Int16     int16;
897       Uint32    uint32;
898       Int32     int32;
899       Uint64    uint64;
900       Int64     int64;
901 
902       double    dbl;
903       float     flt;
904 
905       char      shortChar[maxShortChar];
906     } val;
907 
908     Uint32 len;
909     void*  buffer;  // Optional; storage for converted value
910   } m_converted;
911 
912 private:
913   NdbConstOperand m_interface;
914 }; // class NdbConstOperandImpl
915 
916 
917 #endif /* __cplusplus */
918 #endif
919