1 /*
2    Copyright (c) 2011, 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 #include <ndb_global.h>
26 #include <NdbDictionary.hpp>
27 #include "NdbIndexScanOperation.hpp"
28 #include "NdbQueryBuilder.hpp"
29 #include "NdbQueryBuilderImpl.hpp"
30 #include <Vector.hpp>
31 #include "signaldata/QueryTree.hpp"
32 
33 #include "NdbDictionaryImpl.hpp"
34 #include <NdbRecord.hpp>
35 #include "AttributeHeader.hpp"
36 #include "NdbOut.hpp"
37 #include <NdbInterpretedCode.hpp>
38 
39 /**
40  * Implementation of all QueryBuilder objects are hidden from
41  * both the API interface and other internals in the NDBAPI using the
42  * pimpl idiom.
43  *
44  * The object hierarch visible through the interface has its 'Impl'
45  * counterparts inside this module. Some classes are
46  * even subclassed further as part of the implementation.
47  * (Particular the ConstOperant in order to implement multiple datatypes)
48  *
49  * In order to avoid allocating both an interface object and its particular
50  * Impl object, all 'final' Impl objects 'has a' interface object
51  * which is accessible through the virtual method ::getInterface.
52  *
53  * ::getImpl() methods has been defined for convenient access
54  * to all available Impl classes.
55  *
56  */
57 
58 // For debugging purposes. Enable to print query tree graph to ndbout.
59 static const bool doPrintQueryTree = false;
60 
61 /* Various error codes that are not specific to NdbQuery. */
62 static const int Err_MemoryAlloc = 4000;
63 static const int Err_FunctionNotImplemented = 4003;
64 static const int Err_UnknownColumn = 4004;
65 static const int Err_FinaliseNotCalled = 4519;
66 
67 static void
setErrorCode(NdbQueryBuilderImpl * qb,int aErrorCode)68 setErrorCode(NdbQueryBuilderImpl* qb, int aErrorCode)
69 { qb->setErrorCode(aErrorCode);
70 }
71 
72 static void
setErrorCode(NdbQueryBuilder * qb,int aErrorCode)73 setErrorCode(NdbQueryBuilder* qb, int aErrorCode)
74 { qb->getImpl().setErrorCode(aErrorCode);
75 }
76 
77 
78 //////////////////////////////////////////////////////////////////
79 // Convenient macro for returning specific errorcodes if
80 // 'cond' does not evaluate to true.
81 //////////////////////////////////////////////////////////////////
82 #define returnErrIf(cond,err)		\
83   if (unlikely((cond)))			\
84   { ::setErrorCode(this,err);		\
85     return NULL;			\
86   }
87 
88 
89 //////////////////////////////////////////////
90 // Implementation of NdbQueryOperand interface
91 //
92 // The common baseclass 'class NdbQueryOperandImpl',
93 // and its 'const', 'linked' and 'param' subclasses are
94 // defined in "NdbQueryBuilderImpl.hpp"
95 // The 'const' operand subclass is a pure virtual baseclass
96 // which has different type specific subclasses defined below:
97 //////////////////////////////////////////////////////////////
98 
99 //////////////////////////////////////////////////
100 // Implements different const datatypes by further
101 // subclassing of the baseclass NdbConstOperandImpl.
102 //////////////////////////////////////////////////
103 class NdbInt64ConstOperandImpl : public NdbConstOperandImpl
104 {
105 public:
NdbInt64ConstOperandImpl(Int64 value)106   explicit NdbInt64ConstOperandImpl (Int64 value) :
107     NdbConstOperandImpl(),
108     m_value(value) {}
109 
110 private:
111   int convertInt8();
112   int convertUint8();
113   int convertInt16();
114   int convertUint16();
115   int convertInt24();
116   int convertUint24();
117   int convertInt32();
118   int convertUint32();
119   int convertInt64();
120   int convertUint64();
121 
122   const Int64 m_value;
123 };
124 
125 class NdbDoubleConstOperandImpl : public NdbConstOperandImpl
126 {
127 public:
NdbDoubleConstOperandImpl(double value)128   explicit NdbDoubleConstOperandImpl (double value) :
129     NdbConstOperandImpl(),
130     m_value(value) {}
131 
132 private:
133   int convertDouble();
134   int convertFloat();
135 private:
136   const double m_value;
137 };
138 
139 class NdbCharConstOperandImpl : public NdbConstOperandImpl
140 {
141 public:
NdbCharConstOperandImpl(const char * value)142   explicit NdbCharConstOperandImpl (const char* value) :
143     NdbConstOperandImpl(), m_value(value) {}
144 
145 private:
146   int convertChar();
147   int convertVChar();
148 //int convertLVChar();
149 private:
150   const char* const m_value;
151 };
152 
153 class NdbGenericConstOperandImpl : public NdbConstOperandImpl
154 {
155 public:
NdbGenericConstOperandImpl(const void * value,Uint32 len)156   explicit NdbGenericConstOperandImpl (const void* value,
157                                        Uint32 len)
158   : NdbConstOperandImpl(),
159     m_value(value),
160     m_len(len)
161   {}
162 
163 private:
164   int convert2ColumnType();
165 
166   const void* const m_value;
167   const Uint32 m_len;
168 };
169 
170 ////////////////////////////////////////////////
171 // Implementation of NdbQueryOperation interface
172 ////////////////////////////////////////////////
173 
174 // Common Baseclass 'class NdbQueryOperationDefImpl' is
175 // defined in "NdbQueryBuilderImpl.hpp"
176 
177 class NdbQueryLookupOperationDefImpl : public NdbQueryOperationDefImpl
178 {
179   friend class NdbQueryBuilder;  // Allow privat access from builder interface
180 
181 public:
getKeyOperands() const182   virtual const NdbQueryOperandImpl* const* getKeyOperands() const
183   { return m_keys; }
184 
185 protected:
186 
187   explicit NdbQueryLookupOperationDefImpl (
188                            const NdbTableImpl& table,
189                            const NdbQueryOperand* const keys[],
190                            const NdbQueryOptionsImpl& options,
191                            const char* ident,
192                            Uint32      opNo,
193                            Uint32      internalOpNo,
194                            int& error);
195 
getInterface() const196   virtual const NdbQueryLookupOperationDef& getInterface() const
197   { return m_interface; }
198 
199   // Append pattern for creating lookup key to serialized code
200   Uint32 appendKeyPattern(Uint32Buffer& serializedDef) const;
201 
isScanOperation() const202   virtual bool isScanOperation() const
203   { return false; }
204 
205 protected:
206   NdbQueryLookupOperationDef m_interface;
207   NdbQueryOperandImpl* m_keys[MAX_ATTRIBUTES_IN_INDEX+1];
208 
209 }; // class NdbQueryLookupOperationDefImpl
210 
211 class NdbQueryPKLookupOperationDefImpl : public NdbQueryLookupOperationDefImpl
212 {
213   friend class NdbQueryBuilder;  // Allow privat access from builder interface
214 
215 public:
216   virtual int serializeOperation(Uint32Buffer& serializedDef);
217 
218 private:
219 
NdbQueryPKLookupOperationDefImpl(const NdbTableImpl & table,const NdbQueryOperand * const keys[],const NdbQueryOptionsImpl & options,const char * ident,Uint32 opNo,Uint32 internalOpNo,int & error)220   explicit NdbQueryPKLookupOperationDefImpl (
221                            const NdbTableImpl& table,
222                            const NdbQueryOperand* const keys[],
223                            const NdbQueryOptionsImpl& options,
224                            const char* ident,
225                            Uint32      opNo,
226                            Uint32      internalOpNo,
227                            int& error)
228     : NdbQueryLookupOperationDefImpl(table, keys, options, ident, opNo,
229                                      internalOpNo, error)
230   {}
231 
getType() const232   virtual NdbQueryOperationDef::Type getType() const
233   { return NdbQueryOperationDef::PrimaryKeyAccess; }
234 
235 }; // class NdbQueryPKLookupOperationDefImpl
236 
237 
238 class NdbQueryIndexOperationDefImpl : public NdbQueryLookupOperationDefImpl
239 {
240   friend class NdbQueryBuilder;  // Allow privat access from builder interface
241 
242 public:
getIndex() const243   virtual const NdbIndexImpl* getIndex() const
244   { return &m_index; }
245 
246   virtual int serializeOperation(Uint32Buffer& serializedDef);
247 
248 private:
249 
NdbQueryIndexOperationDefImpl(const NdbIndexImpl & index,const NdbTableImpl & table,const NdbQueryOperand * const keys[],const NdbQueryOptionsImpl & options,const char * ident,Uint32 opNo,Uint32 internalOpNo,int & error)250   explicit NdbQueryIndexOperationDefImpl (
251                            const NdbIndexImpl& index,
252                            const NdbTableImpl& table,
253                            const NdbQueryOperand* const keys[],
254                            const NdbQueryOptionsImpl& options,
255                            const char* ident,
256                            Uint32      opNo,
257                            Uint32      internalOpNo,
258                            int& error)
259     // Add 1 to 'id' since index lookup is serialized as two operations.
260     : NdbQueryLookupOperationDefImpl(table, keys, options, ident, opNo,
261                                      internalOpNo+1, error),
262     m_index(index)
263   {}
264 
getType() const265   virtual NdbQueryOperationDef::Type getType() const
266   { return NdbQueryOperationDef::UniqueIndexAccess; }
267 
268 private:
269   const NdbIndexImpl& m_index;
270 
271 }; // class NdbQueryIndexOperationDefImpl
272 
273 
274 class NdbQueryTableScanOperationDefImpl : public NdbQueryScanOperationDefImpl
275 {
276   friend class NdbQueryBuilder;  // Allow privat access from builder interface
277 
278 public:
279   virtual int serializeOperation(Uint32Buffer& serializedDef);
280 
getInterface() const281   virtual const NdbQueryTableScanOperationDef& getInterface() const
282   { return m_interface; }
283 
getType() const284   virtual NdbQueryOperationDef::Type getType() const
285   { return NdbQueryOperationDef::TableScan; }
286 
287 private:
288 
NdbQueryTableScanOperationDefImpl(const NdbTableImpl & table,const NdbQueryOptionsImpl & options,const char * ident,Uint32 opNo,Uint32 internalOpNo,int & error)289   explicit NdbQueryTableScanOperationDefImpl (
290                            const NdbTableImpl& table,
291                            const NdbQueryOptionsImpl& options,
292                            const char* ident,
293                            Uint32      opNo,
294                            Uint32      internalOpNo,
295                            int& error)
296     : NdbQueryScanOperationDefImpl(table, options, ident, opNo,
297                                    internalOpNo, error),
298       m_interface(*this)
299   {}
300 
301   NdbQueryTableScanOperationDef m_interface;
302 
303 }; // class NdbQueryTableScanOperationDefImpl
304 
305 
306 
307 
308 ///////////////////////////////////////////////////
309 /////// End 'Impl' class declarations /////////////
310 ///////////////////////////////////////////////////
311 
NdbQueryDef(NdbQueryDefImpl & impl)312 NdbQueryDef::NdbQueryDef(NdbQueryDefImpl& impl) : m_impl(impl)
313 {}
~NdbQueryDef()314 NdbQueryDef::~NdbQueryDef()
315 {}
316 
317 Uint32
getNoOfOperations() const318 NdbQueryDef::getNoOfOperations() const
319 { return m_impl.getNoOfOperations();
320 }
321 
322 const NdbQueryOperationDef*
getQueryOperation(Uint32 index) const323 NdbQueryDef::getQueryOperation(Uint32 index) const
324 { return &m_impl.getQueryOperation(index).getInterface();
325 }
326 
327 const NdbQueryOperationDef*
getQueryOperation(const char * ident) const328 NdbQueryDef::getQueryOperation(const char* ident) const
329 { const NdbQueryOperationDefImpl *opDef = m_impl.getQueryOperation(ident);
330   return (opDef!=NULL) ? &opDef->getInterface() : NULL;
331 }
332 
333 bool
isScanQuery() const334 NdbQueryDef::isScanQuery() const
335 { return m_impl.isScanQuery();
336 }
337 
338 NdbQueryDef::QueryType
getQueryType() const339 NdbQueryDef::getQueryType() const
340 { return m_impl.getQueryType();
341 }
342 
343 NdbQueryDefImpl&
getImpl() const344 NdbQueryDef::getImpl() const{
345   return m_impl;
346 }
347 
348 void
destroy() const349 NdbQueryDef::destroy() const
350 {
351   delete &getImpl();
352 }
353 
354 void
print() const355 NdbQueryDef::print() const
356 {
357   m_impl.getQueryOperation(0U)
358     .printTree(0, NdbQueryOperationDefImpl::SiblingMask());
359 }
360 
361 /*************************************************************************
362  * Glue layer between NdbQueryOperand interface and its Impl'ementation.
363  ************************************************************************/
364 
NdbQueryOperand(NdbQueryOperandImpl & impl)365 NdbQueryOperand::NdbQueryOperand(NdbQueryOperandImpl& impl) : m_impl(impl)
366 {}
NdbConstOperand(NdbQueryOperandImpl & impl)367 NdbConstOperand::NdbConstOperand(NdbQueryOperandImpl& impl) : NdbQueryOperand(impl)
368 {}
NdbParamOperand(NdbQueryOperandImpl & impl)369 NdbParamOperand::NdbParamOperand(NdbQueryOperandImpl& impl) : NdbQueryOperand(impl)
370 {}
NdbLinkedOperand(NdbQueryOperandImpl & impl)371 NdbLinkedOperand::NdbLinkedOperand(NdbQueryOperandImpl& impl) : NdbQueryOperand(impl)
372 {}
373 
374 // D'tors
~NdbQueryOperand()375 NdbQueryOperand::~NdbQueryOperand()
376 {}
~NdbConstOperand()377 NdbConstOperand::~NdbConstOperand()
378 {}
~NdbParamOperand()379 NdbParamOperand::~NdbParamOperand()
380 {}
~NdbLinkedOperand()381 NdbLinkedOperand::~NdbLinkedOperand()
382 {}
383 
384 /**
385  * Get'ers for NdbQueryOperand...Impl object.
386  * Functions overridden to supply 'impl' casted to the correct '...OperandImpl' type
387  * for each available interface class.
388  */
389 inline NdbQueryOperandImpl&
getImpl() const390 NdbQueryOperand::getImpl() const
391 { return m_impl;
392 }
393 inline static
getImpl(const NdbQueryOperand & op)394 NdbQueryOperandImpl& getImpl(const NdbQueryOperand& op)
395 { return op.getImpl();
396 }
397 inline static
getImpl(const NdbConstOperand & op)398 NdbConstOperandImpl& getImpl(const NdbConstOperand& op)
399 { return static_cast<NdbConstOperandImpl&>(op.getImpl());
400 }
401 inline static
getImpl(const NdbParamOperand & op)402 NdbParamOperandImpl& getImpl(const NdbParamOperand& op)
403 { return static_cast<NdbParamOperandImpl&>(op.getImpl());
404 }
405 inline static
getImpl(const NdbLinkedOperand & op)406 NdbLinkedOperandImpl& getImpl(const NdbLinkedOperand& op)
407 { return static_cast<NdbLinkedOperandImpl&>(op.getImpl());
408 }
409 
410 /**
411  * BEWARE: Return 'NULL' Until the operand has been bound to an operation.
412  */
413 const NdbDictionary::Column*
getColumn() const414 NdbQueryOperand::getColumn() const
415 {
416   return ::getImpl(*this).getColumn();
417 }
418 
419 const char*
getName() const420 NdbParamOperand::getName() const
421 {
422   return ::getImpl(*this).getName();
423 }
424 
425 Uint32
getEnum() const426 NdbParamOperand::getEnum() const
427 {
428   return ::getImpl(*this).getParamIx();
429 }
430 
431 /****************************************************************************
432  * Implementation of NdbQueryOptions.
433  * Because of the simplicity of this class, the implementation has *not*
434  * been split into methods in the Impl class with a glue layer to the
435  * outside interface.
436  ****************************************************************************/
437 static NdbQueryOptionsImpl defaultOptions;
438 
NdbQueryOptions()439 NdbQueryOptions::NdbQueryOptions()
440 : m_pimpl(&defaultOptions)
441 {}
442 
~NdbQueryOptions()443 NdbQueryOptions::~NdbQueryOptions()
444 {
445   if (m_pimpl!=&defaultOptions)
446     delete m_pimpl;
447 }
448 
449 const NdbQueryOptionsImpl&
getImpl() const450 NdbQueryOptions::getImpl() const
451 {
452   return *m_pimpl;
453 }
454 
455 int
setOrdering(ScanOrdering ordering)456 NdbQueryOptions::setOrdering(ScanOrdering ordering)
457 {
458   if (m_pimpl==&defaultOptions)
459   {
460     m_pimpl = new NdbQueryOptionsImpl;
461     if (unlikely(m_pimpl==0))
462     {
463       return Err_MemoryAlloc;
464     }
465   }
466   m_pimpl->m_scanOrder = ordering;
467   return 0;
468 }
469 
470 int
setMatchType(MatchType matchType)471 NdbQueryOptions::setMatchType(MatchType matchType)
472 {
473   if (m_pimpl==&defaultOptions)
474   {
475     m_pimpl = new NdbQueryOptionsImpl;
476     if (unlikely(m_pimpl==0))
477     {
478       return Err_MemoryAlloc;
479     }
480   }
481   m_pimpl->m_matchType = matchType;
482   return 0;
483 }
484 
485 int
setParent(const NdbQueryOperationDef * parent)486 NdbQueryOptions::setParent(const NdbQueryOperationDef* parent)
487 {
488   if (m_pimpl==&defaultOptions)
489   {
490     m_pimpl = new NdbQueryOptionsImpl;
491     if (unlikely(m_pimpl==0))
492     {
493       return Err_MemoryAlloc;
494     }
495   }
496   m_pimpl->m_parent = &parent->getImpl();
497   return 0;
498 }
499 
500 int
setInterpretedCode(const NdbInterpretedCode & code)501 NdbQueryOptions::setInterpretedCode(const NdbInterpretedCode& code)
502 {
503   if (m_pimpl==&defaultOptions)
504   {
505     m_pimpl = new NdbQueryOptionsImpl;
506     if (unlikely(m_pimpl==0))
507     {
508       return Err_MemoryAlloc;
509     }
510   }
511   return m_pimpl->copyInterpretedCode(code);
512 }
513 
514 
~NdbQueryOptionsImpl()515 NdbQueryOptionsImpl::~NdbQueryOptionsImpl()
516 {
517   delete m_interpretedCode;
518 }
519 
NdbQueryOptionsImpl(const NdbQueryOptionsImpl & src)520 NdbQueryOptionsImpl::NdbQueryOptionsImpl(const NdbQueryOptionsImpl& src)
521  : m_matchType(src.m_matchType),
522    m_scanOrder(src.m_scanOrder),
523    m_parent(src.m_parent),
524    m_interpretedCode(NULL)
525 {
526   if (src.m_interpretedCode)
527   {
528     copyInterpretedCode(*src.m_interpretedCode);
529   }
530 }
531 
532 /*
533  * Make a deep copy, such that 'src' can be destroyed when this method
534  * returns.
535  */
536 int
copyInterpretedCode(const NdbInterpretedCode & src)537 NdbQueryOptionsImpl::copyInterpretedCode(const NdbInterpretedCode& src)
538 {
539   /* Check the program's finalised */
540   if (unlikely(!(src.m_flags & NdbInterpretedCode::Finalised)))
541   {
542     return Err_FinaliseNotCalled;  // NdbInterpretedCode::finalise() not called.
543   }
544   if (src.m_instructions_length == 0)
545   {
546     return 0;
547   }
548 
549   NdbInterpretedCode* interpretedCode = new NdbInterpretedCode();
550   if (unlikely(interpretedCode==NULL))
551   {
552     return Err_MemoryAlloc;
553   }
554 
555   const int error = interpretedCode->copy(src);
556   if (unlikely(error))
557   {
558     delete interpretedCode;
559     return error;
560   }
561 
562   /* Replace existing NdbInterpretedCode */
563   if (m_interpretedCode)
564     delete m_interpretedCode;
565 
566   m_interpretedCode = interpretedCode;
567   return 0;
568 }
569 
570 
571 /****************************************************************************
572  * Glue layer between NdbQueryOperationDef interface and its Impl'ementation.
573  ****************************************************************************/
NdbQueryOperationDef(NdbQueryOperationDefImpl & impl)574 NdbQueryOperationDef::NdbQueryOperationDef(NdbQueryOperationDefImpl& impl) : m_impl(impl)
575 {}
NdbQueryLookupOperationDef(NdbQueryOperationDefImpl & impl)576 NdbQueryLookupOperationDef::NdbQueryLookupOperationDef(NdbQueryOperationDefImpl& impl) : NdbQueryOperationDef(impl)
577 {}
NdbQueryScanOperationDef(NdbQueryOperationDefImpl & impl)578 NdbQueryScanOperationDef::NdbQueryScanOperationDef(NdbQueryOperationDefImpl& impl) : NdbQueryOperationDef(impl)
579 {}
NdbQueryTableScanOperationDef(NdbQueryOperationDefImpl & impl)580 NdbQueryTableScanOperationDef::NdbQueryTableScanOperationDef(NdbQueryOperationDefImpl& impl) : NdbQueryScanOperationDef(impl)
581 {}
NdbQueryIndexScanOperationDef(NdbQueryOperationDefImpl & impl)582 NdbQueryIndexScanOperationDef::NdbQueryIndexScanOperationDef(NdbQueryOperationDefImpl& impl) : NdbQueryScanOperationDef(impl)
583 {}
584 
585 
586 // D'tors
~NdbQueryOperationDef()587 NdbQueryOperationDef::~NdbQueryOperationDef()
588 {}
~NdbQueryLookupOperationDef()589 NdbQueryLookupOperationDef::~NdbQueryLookupOperationDef()
590 {}
~NdbQueryScanOperationDef()591 NdbQueryScanOperationDef::~NdbQueryScanOperationDef()
592 {}
~NdbQueryTableScanOperationDef()593 NdbQueryTableScanOperationDef::~NdbQueryTableScanOperationDef()
594 {}
~NdbQueryIndexScanOperationDef()595 NdbQueryIndexScanOperationDef::~NdbQueryIndexScanOperationDef()
596 {}
597 
~NdbQueryOperationDefImpl()598 NdbQueryOperationDefImpl::~NdbQueryOperationDefImpl()
599 {
600   // Unlink any parent and child refering this object
601   if (m_parent != NULL)
602   {
603     m_parent->removeChild(this);
604   }
605   for (Uint32 i = 0; i<m_children.size(); i++)
606   {
607     assert(m_children[i]->m_parent == this);
608     m_children[i]->m_parent = NULL;
609   }
610 }
611 
612 /**
613  * Get'ers for QueryOperation...DefImpl object.
614  * Functions overridden to supply 'impl' casted to the correct '...DefImpl' type
615  * for each available interface class.
616  */
617 NdbQueryOperationDefImpl&
getImpl() const618 NdbQueryOperationDef::getImpl() const
619 { return m_impl;
620 }
621 inline static
getImpl(const NdbQueryOperationDef & op)622 NdbQueryOperationDefImpl& getImpl(const NdbQueryOperationDef& op)
623 { return op.getImpl();
624 }
625 inline static
getImpl(const NdbQueryLookupOperationDef & op)626 NdbQueryLookupOperationDefImpl& getImpl(const NdbQueryLookupOperationDef& op)
627 { return static_cast<NdbQueryLookupOperationDefImpl&>(op.getImpl());
628 }
629 inline static
getImpl(const NdbQueryTableScanOperationDef & op)630 NdbQueryTableScanOperationDefImpl& getImpl(const NdbQueryTableScanOperationDef& op)
631 { return static_cast<NdbQueryTableScanOperationDefImpl&>(op.getImpl());
632 }
633 inline static
getImpl(const NdbQueryIndexScanOperationDef & op)634 NdbQueryIndexScanOperationDefImpl& getImpl(const NdbQueryIndexScanOperationDef& op)
635 { return static_cast<NdbQueryIndexScanOperationDefImpl&>(op.getImpl());
636 }
637 
638 
639 Uint32
getOpNo() const640 NdbQueryOperationDef::getOpNo() const
641 {
642   return ::getImpl(*this).getOpNo();
643 }
644 
645 Uint32
getNoOfParentOperations() const646 NdbQueryOperationDef::getNoOfParentOperations() const
647 {
648   return ::getImpl(*this).getNoOfParentOperations();
649 }
650 
651 const NdbQueryOperationDef*
getParentOperation(Uint32 i) const652 NdbQueryOperationDef::getParentOperation(Uint32 i) const
653 {
654   return &::getImpl(*this).getParentOperation(i).getInterface();
655 }
656 
657 Uint32
getNoOfChildOperations() const658 NdbQueryOperationDef::getNoOfChildOperations() const
659 {
660   return ::getImpl(*this).getNoOfChildOperations();
661 }
662 
663 const NdbQueryOperationDef*
getChildOperation(Uint32 i) const664 NdbQueryOperationDef::getChildOperation(Uint32 i) const
665 {
666   return &::getImpl(*this).getChildOperation(i).getInterface();
667 }
668 
669 const char*
getTypeName(Type type)670 NdbQueryOperationDef::getTypeName(Type type)
671 {
672   switch(type)
673   {
674   case PrimaryKeyAccess:
675     return "PrimaryKeyAccess";
676   case UniqueIndexAccess:
677     return "UniqueIndexAccess";
678   case TableScan:
679     return "TableScan";
680   case OrderedIndexScan:
681     return "OrderedIndexScan";
682   default:
683     return "<Invalid NdbQueryOperationDef::Type value>";
684   }
685 }
686 
687 
688 NdbQueryOperationDef::Type
getType() const689 NdbQueryOperationDef::getType() const
690 {
691   return ::getImpl(*this).getType();
692 }
693 
694 const NdbDictionary::Table*
getTable() const695 NdbQueryOperationDef::getTable() const
696 {
697   return &::getImpl(*this).getTable();
698 }
699 
700 const NdbDictionary::Index*
getIndex() const701 NdbQueryOperationDef::getIndex() const
702 {
703   return ::getImpl(*this).getIndex();
704 }
705 
706 /*******************************************
707  * Implementation of NdbQueryBuilder factory
708  ******************************************/
709 // Static method.
create()710 NdbQueryBuilder* NdbQueryBuilder::create()
711 {
712   NdbQueryBuilderImpl* const impl = new NdbQueryBuilderImpl();
713   if (likely (impl != NULL))
714   {
715     if((!ndb_join_pushdown(ndbGetOwnVersion())))
716     {
717       /* The SPJ code is present in releases where the SPJ feature is
718        * not yet enabled.
719        */
720       impl->setErrorCode(Err_FunctionNotImplemented);
721     }
722     return &impl->m_interface;
723   }
724   else
725   {
726     return NULL;
727   }
728 }
729 
destroy()730 void NdbQueryBuilder::destroy()
731 {
732   delete &m_impl;
733 }
734 
NdbQueryBuilder(NdbQueryBuilderImpl & impl)735 NdbQueryBuilder::NdbQueryBuilder(NdbQueryBuilderImpl& impl)
736 : m_impl(impl)
737 {}
738 
~NdbQueryBuilder()739 NdbQueryBuilder::~NdbQueryBuilder()
740 {}
741 
742 inline NdbQueryBuilderImpl&
getImpl() const743 NdbQueryBuilder::getImpl() const
744 { return m_impl;
745 }
746 
747 const NdbError&
getNdbError() const748 NdbQueryBuilder::getNdbError() const
749 {
750   return m_impl.getNdbError();
751 }
752 
753 //////////////////////////////////////////////////
754 // Implements different const datatypes by further
755 // subclassing of NdbConstOperand.
756 /////////////////////////////////////////////////
757 NdbConstOperand*
constValue(const char * value)758 NdbQueryBuilder::constValue(const char* value)
759 {
760   returnErrIf(value==0,QRY_REQ_ARG_IS_NULL);
761   return static_cast<NdbConstOperand*>
762     (m_impl.addOperand(new NdbCharConstOperandImpl(value)));
763 }
764 
765 NdbConstOperand*
constValue(const void * value,Uint32 len)766 NdbQueryBuilder::constValue(const void* value, Uint32 len)
767 {
768   returnErrIf(value == 0, QRY_REQ_ARG_IS_NULL);
769   return static_cast<NdbConstOperand*>
770     (m_impl.addOperand(new NdbGenericConstOperandImpl(value,len)));
771 }
772 
773 NdbConstOperand*
constValue(Int32 value)774 NdbQueryBuilder::constValue(Int32 value)
775 {
776   return static_cast<NdbConstOperand*>
777     (m_impl.addOperand(new NdbInt64ConstOperandImpl(value)));
778 }
779 
780 NdbConstOperand*
constValue(Uint32 value)781 NdbQueryBuilder::constValue(Uint32 value)
782 {
783   return static_cast<NdbConstOperand*>
784     (m_impl.addOperand(new NdbInt64ConstOperandImpl(value)));
785 }
786 
787 NdbConstOperand*
constValue(Int64 value)788 NdbQueryBuilder::constValue(Int64 value)
789 {
790   return static_cast<NdbConstOperand*>
791     (m_impl.addOperand(new NdbInt64ConstOperandImpl(value)));
792 }
793 
794 NdbConstOperand*
constValue(Uint64 value)795 NdbQueryBuilder::constValue(Uint64 value)
796 {
797   return static_cast<NdbConstOperand*>
798     (m_impl.addOperand(new NdbInt64ConstOperandImpl(value)));
799 }
800 
801 NdbConstOperand*
constValue(double value)802 NdbQueryBuilder::constValue(double value)
803 {
804   return static_cast<NdbConstOperand*>
805     (m_impl.addOperand(new NdbDoubleConstOperandImpl(value)));
806 }
807 
808 NdbParamOperand*
paramValue(const char * name)809 NdbQueryBuilder::paramValue(const char* name)
810 {
811   return static_cast<NdbParamOperand*>
812     (m_impl.addOperand(new NdbParamOperandImpl(name,getImpl().m_paramCnt++)));
813 }
814 
815 NdbLinkedOperand*
linkedValue(const NdbQueryOperationDef * parent,const char * attr)816 NdbQueryBuilder::linkedValue(const NdbQueryOperationDef* parent, const char* attr)
817 {
818   // Required non-NULL arguments
819   returnErrIf(parent==0 || attr==0, QRY_REQ_ARG_IS_NULL);
820   NdbQueryOperationDefImpl& parentImpl = parent->getImpl();
821 
822   // Parent should be a OperationDef contained in this query builder context
823   returnErrIf(!m_impl.contains(&parentImpl), QRY_UNKNOWN_PARENT);
824 
825   // 'attr' should refer a column from the underlying table in parent:
826   const NdbColumnImpl* column = parentImpl.getTable().getColumn(attr);
827   returnErrIf(column==0, Err_UnknownColumn); // Unknown column
828 
829   // Locate refered parrent column in parent operations SPJ projection list;
830   // Add if not already present
831   int error = 0;
832   Uint32 colIx = parentImpl.addColumnRef(column, error);
833   if (unlikely(error != 0))
834   {
835     m_impl.setErrorCode(error);
836     return NULL;
837   }
838 
839   return static_cast<NdbLinkedOperand*>
840     (m_impl.addOperand(new NdbLinkedOperandImpl(parentImpl,colIx)));
841 }
842 
843 // Check if there is at least one linked operand.
hasLinkedOperand(const NdbQueryOperand * const keys[])844 static bool hasLinkedOperand(const NdbQueryOperand* const keys[])
845 {
846   int i = 0;
847   while (keys[i] != NULL)
848   {
849     if (keys[i]->getImpl().getKind() == NdbQueryOperandImpl::Linked)
850     {
851       return true;
852     }
853     i++;
854   }
855   return false;
856 }
857 
858 const NdbQueryLookupOperationDef*
readTuple(const NdbDictionary::Table * table,const NdbQueryOperand * const keys[],const NdbQueryOptions * options,const char * ident)859 NdbQueryBuilder::readTuple(const NdbDictionary::Table* table,    // Primary key lookup
860                            const NdbQueryOperand* const keys[],  // Terminated by NULL element
861                            const NdbQueryOptions* options,
862                            const char* ident)
863 {
864   int i;
865   if (m_impl.hasError())
866     return NULL;
867 
868   returnErrIf(table==0 || keys==0, QRY_REQ_ARG_IS_NULL);
869   // All operations but the first one must depend on some other operation.
870   returnErrIf(m_impl.m_operations.size() > 0 && !hasLinkedOperand(keys),
871               QRY_UNKNOWN_PARENT);
872 
873   const NdbTableImpl& tableImpl = NdbTableImpl::getImpl(*table);
874 
875   // All column values being part of primary key should be specified:
876   int keyfields = table->getNoOfPrimaryKeys();
877   int colcount = table->getNoOfColumns();
878 
879   // Check: keys[] are specified for all fields in PK
880   for (i=0; i<keyfields; ++i)
881   {
882     // A 'Key' value is undefined
883     returnErrIf(keys[i]==NULL, QRY_TOO_FEW_KEY_VALUES);
884   }
885   // Check for propper NULL termination of keys[] spec
886   returnErrIf(keys[keyfields]!=NULL, QRY_TOO_MANY_KEY_VALUES);
887 
888   int error = 0;
889   NdbQueryPKLookupOperationDefImpl* op =
890     new NdbQueryPKLookupOperationDefImpl(tableImpl,
891                                        keys,
892                                        options ? options->getImpl() : defaultOptions,
893                                        ident,
894                                        m_impl.m_operations.size(),
895                                        m_impl.getNextInternalOpNo(),
896                                        error);
897 
898   returnErrIf(m_impl.takeOwnership(op)!=0, Err_MemoryAlloc);
899   returnErrIf(error!=0, error); // C'tor returned error, bailout
900 
901   Uint32 keyindex = 0;
902   for (i=0; i<colcount; ++i)
903   {
904     const NdbColumnImpl *col = tableImpl.getColumn(i);
905     if (col->getPrimaryKey())
906     {
907       assert (keyindex==col->m_keyInfoPos);
908       int error = op->m_keys[col->m_keyInfoPos]->bindOperand(*col,*op);
909       returnErrIf(error!=0, error);
910 
911       keyindex++;
912       if (keyindex >= static_cast<Uint32>(keyfields))
913         break;  // Seen all PK fields
914     }
915   }
916 
917   return &op->m_interface;
918 }
919 
920 
921 const NdbQueryLookupOperationDef*
readTuple(const NdbDictionary::Index * index,const NdbDictionary::Table * table,const NdbQueryOperand * const keys[],const NdbQueryOptions * options,const char * ident)922 NdbQueryBuilder::readTuple(const NdbDictionary::Index* index,    // Unique key lookup w/ index
923                            const NdbDictionary::Table* table,    // Primary key lookup
924                            const NdbQueryOperand* const keys[],  // Terminated by NULL element
925                            const NdbQueryOptions* options,
926                            const char* ident)
927 {
928   int i;
929 
930   if (m_impl.hasError())
931     return NULL;
932 
933   returnErrIf(table==0 || index==0 || keys==0, QRY_REQ_ARG_IS_NULL);
934   // All operations but the first one must depend on some other operation.
935   returnErrIf(m_impl.m_operations.size() > 0 && !hasLinkedOperand(keys),
936               QRY_UNKNOWN_PARENT);
937 
938   const NdbIndexImpl& indexImpl = NdbIndexImpl::getImpl(*index);
939   const NdbTableImpl& tableImpl = NdbTableImpl::getImpl(*table);
940 
941   // TODO: Restrict to only table_version_major() mismatch?
942   returnErrIf(indexImpl.m_table_id
943               != static_cast<Uint32>(table->getObjectId()) ||
944               indexImpl.m_table_version
945               != static_cast<Uint32>(table->getObjectVersion()),
946               QRY_UNRELATED_INDEX);
947 
948   // Only 'UNIQUE' indexes may be used for lookup operations:
949   returnErrIf(index->getType()!=NdbDictionary::Index::UniqueHashIndex,
950               QRY_WRONG_INDEX_TYPE);
951 
952   // Check: keys[] are specified for all fields in 'index'
953   int inxfields = index->getNoOfColumns();
954   for (i=0; i<inxfields; ++i)
955   {
956     // A 'Key' value is undefined
957     returnErrIf(keys[i]==NULL, QRY_TOO_FEW_KEY_VALUES);
958   }
959   // Check for propper NULL termination of keys[] spec
960   returnErrIf(keys[inxfields]!=NULL, QRY_TOO_MANY_KEY_VALUES);
961 
962   int error = 0;
963   NdbQueryIndexOperationDefImpl* op =
964     new NdbQueryIndexOperationDefImpl(indexImpl, tableImpl,
965                                        keys,
966                                        options ? options->getImpl() : defaultOptions,
967                                        ident,
968                                        m_impl.m_operations.size(),
969                                        m_impl.getNextInternalOpNo(),
970                                        error);
971 
972   returnErrIf(m_impl.takeOwnership(op)!=0, Err_MemoryAlloc);
973   returnErrIf(error!=0, error); // C'tor returned error, bailout
974 
975   // Bind to Column and check type compatibility
976   for (i=0; i<inxfields; ++i)
977   {
978     const NdbColumnImpl& col = NdbColumnImpl::getImpl(*indexImpl.getColumn(i));
979     assert (col.getColumnNo() == i);
980 
981     error = keys[i]->getImpl().bindOperand(col,*op);
982     returnErrIf(error!=0, error);
983   }
984 
985   return &op->m_interface;
986 }
987 
988 
989 const NdbQueryTableScanOperationDef*
scanTable(const NdbDictionary::Table * table,const NdbQueryOptions * options,const char * ident)990 NdbQueryBuilder::scanTable(const NdbDictionary::Table* table,
991                            const NdbQueryOptions* options,
992                            const char* ident)
993 {
994   if (m_impl.hasError())
995     return NULL;
996   returnErrIf(table==0, QRY_REQ_ARG_IS_NULL);  // Required non-NULL arguments
997   /**
998    * A table scan does not depend on other operations, since there cannot be
999    * linked operands in a scan filter. Therefore, it must be the first
1000    * operation.
1001    */
1002   returnErrIf(m_impl.m_operations.size() > 0, QRY_UNKNOWN_PARENT);
1003 
1004   int error = 0;
1005   NdbQueryTableScanOperationDefImpl* op =
1006     new NdbQueryTableScanOperationDefImpl(NdbTableImpl::getImpl(*table),
1007                                           options ? options->getImpl() : defaultOptions,
1008                                           ident,
1009                                           m_impl.m_operations.size(),
1010                                           m_impl.getNextInternalOpNo(),
1011                                           error);
1012 
1013   returnErrIf(m_impl.takeOwnership(op)!=0, Err_MemoryAlloc);
1014   returnErrIf(error!=0, error); // C'tor returned error, bailout
1015 
1016   return &op->m_interface;
1017 }
1018 
1019 
1020 const NdbQueryIndexScanOperationDef*
scanIndex(const NdbDictionary::Index * index,const NdbDictionary::Table * table,const NdbQueryIndexBound * bound,const NdbQueryOptions * options,const char * ident)1021 NdbQueryBuilder::scanIndex(const NdbDictionary::Index* index,
1022 	                   const NdbDictionary::Table* table,
1023                            const NdbQueryIndexBound* bound,
1024                            const NdbQueryOptions* options,
1025                            const char* ident)
1026 {
1027   if (m_impl.hasError())
1028     return NULL;
1029   // Required non-NULL arguments
1030   returnErrIf(table==0 || index==0, QRY_REQ_ARG_IS_NULL);
1031 
1032   if (m_impl.m_operations.size() > 0)
1033   {
1034     // All operations but the first one must depend on some other operation.
1035     returnErrIf(bound == NULL ||
1036                 (!hasLinkedOperand(bound->m_low) &&
1037                  !hasLinkedOperand(bound->m_high)),
1038                 QRY_UNKNOWN_PARENT);
1039 
1040     // Scan with root lookup operation has not been implemented.
1041     returnErrIf(!m_impl.m_operations[0]->isScanOperation(),
1042                 QRY_WRONG_OPERATION_TYPE);
1043 
1044     if (options != NULL)
1045     {
1046       // A child scan should not be sorted.
1047       const NdbQueryOptions::ScanOrdering order =
1048         options->getImpl().getOrdering();
1049       returnErrIf(order == NdbQueryOptions::ScanOrdering_ascending ||
1050                   order == NdbQueryOptions::ScanOrdering_descending,
1051                   QRY_MULTIPLE_SCAN_SORTED);
1052     }
1053   }
1054 
1055   const NdbIndexImpl& indexImpl = NdbIndexImpl::getImpl(*index);
1056   const NdbTableImpl& tableImpl = NdbTableImpl::getImpl(*table);
1057 
1058   // TODO: Restrict to only table_version_major() mismatch?
1059   returnErrIf(indexImpl.m_table_id
1060               != static_cast<Uint32>(table->getObjectId()) ||
1061               indexImpl.m_table_version
1062               != static_cast<Uint32>(table->getObjectVersion()),
1063               QRY_UNRELATED_INDEX);
1064 
1065   // Only ordered indexes may be used in scan operations:
1066   returnErrIf(index->getType()!=NdbDictionary::Index::OrderedIndex,
1067               QRY_WRONG_INDEX_TYPE);
1068 
1069   int error = 0;
1070   NdbQueryIndexScanOperationDefImpl* op =
1071     new NdbQueryIndexScanOperationDefImpl(indexImpl, tableImpl,
1072                                           bound,
1073                                           options ? options->getImpl() : defaultOptions,
1074                                           ident,
1075                                           m_impl.m_operations.size(),
1076                                           m_impl.getNextInternalOpNo(),
1077                                           error);
1078 
1079   returnErrIf(m_impl.takeOwnership(op)!=0, Err_MemoryAlloc);
1080   returnErrIf(error!=0, error); // C'tor returned error, bailout
1081 
1082   returnErrIf(op->m_bound.lowKeys  > indexImpl.getNoOfColumns() ||
1083               op->m_bound.highKeys > indexImpl.getNoOfColumns(),
1084               QRY_TOO_MANY_KEY_VALUES);
1085 
1086   // Bind lowKeys, and if applicable, highKeys to the column being refered
1087   Uint32 i;
1088   for (i=0; i<op->m_bound.lowKeys; ++i)
1089   {
1090     const NdbColumnImpl& col = NdbColumnImpl::getImpl(*indexImpl.getColumn(i));
1091 
1092     const int error = (i<op->m_bound.highKeys && op->m_bound.high[i]!=op->m_bound.low[i])
1093        ? op->m_bound.low[i]->bindOperand(col,*op) || op->m_bound.high[i]->bindOperand(col,*op)
1094        : op->m_bound.low[i]->bindOperand(col,*op);
1095 
1096     returnErrIf(error!=0, error);
1097   }
1098 
1099   // Bind any remaining highKeys past '#lowKeys'
1100   for (; i<op->m_bound.highKeys; ++i)
1101   {
1102     const NdbColumnImpl& col = NdbColumnImpl::getImpl(*indexImpl.getColumn(i));
1103     error = op->m_bound.high[i]->bindOperand(col,*op);
1104     returnErrIf(error!=0, error);
1105   }
1106 
1107   return &op->m_interface;
1108 }
1109 
1110 const NdbQueryDef*
prepare()1111 NdbQueryBuilder::prepare()
1112 {
1113   const NdbQueryDefImpl* def = m_impl.prepare();
1114   return (def) ? &def->getInterface() : NULL;
1115 }
1116 
1117 ////////////////////////////////////////
1118 // The (hidden) Impl of NdbQueryBuilder
1119 ////////////////////////////////////////
1120 
NdbQueryBuilderImpl()1121 NdbQueryBuilderImpl::NdbQueryBuilderImpl()
1122 : m_interface(*this),
1123   m_error(),
1124   m_operations(0),
1125   m_operands(0),
1126   m_paramCnt(0),
1127   m_hasError(false)
1128 {}
1129 
~NdbQueryBuilderImpl()1130 NdbQueryBuilderImpl::~NdbQueryBuilderImpl()
1131 {
1132   // Delete all operand and operator in Vector's
1133   for (Uint32 i=0; i<m_operations.size(); ++i)
1134   {
1135     delete m_operations[i];
1136   }
1137   for (Uint32 i=0; i<m_operands.size(); ++i)
1138   {
1139     delete m_operands[i];
1140   }
1141 }
1142 
setErrorCode(int aErrorCode)1143 void NdbQueryBuilderImpl::setErrorCode(int aErrorCode)
1144 {
1145   assert(aErrorCode != 0);
1146   m_error.code = aErrorCode;
1147   m_hasError = true;
1148 }
1149 
1150 bool
contains(const NdbQueryOperationDefImpl * opDef)1151 NdbQueryBuilderImpl::contains(const NdbQueryOperationDefImpl* opDef)
1152 {
1153   for (Uint32 i=0; i<m_operations.size(); ++i)
1154   { if (m_operations[i] == opDef)
1155       return true;
1156   }
1157   return false;
1158 }
1159 
1160 
1161 const NdbQueryDefImpl*
prepare()1162 NdbQueryBuilderImpl::prepare()
1163 {
1164   if (hasError())
1165   {
1166     return NULL;
1167   }
1168   if (m_operations.size() == 0)
1169   {
1170     setErrorCode(QRY_HAS_ZERO_OPERATIONS);
1171     return NULL;
1172   }
1173 
1174   int error;
1175   NdbQueryDefImpl* def = new NdbQueryDefImpl(m_operations, m_operands, error);
1176   m_operations.clear();
1177   m_operands.clear();
1178   m_paramCnt = 0;
1179 
1180   returnErrIf(def==0, Err_MemoryAlloc);
1181   if(unlikely(error!=0)){
1182     delete def;
1183     setErrorCode(error);
1184     return NULL;
1185   }
1186 
1187   if (doPrintQueryTree)
1188   {
1189     ndbout << "Query tree:" << endl;
1190     def->getQueryOperation(0U)
1191       .printTree(0, NdbQueryOperationDefImpl::SiblingMask());
1192   }
1193 
1194   return def;
1195 }
1196 
1197 inline int
takeOwnership(NdbQueryOperandImpl * operand)1198 NdbQueryBuilderImpl::takeOwnership(NdbQueryOperandImpl* operand)
1199 {
1200   if (unlikely(operand == NULL))
1201   {
1202     return Err_MemoryAlloc;
1203   }
1204   else if (unlikely(m_operands.push_back(operand) != 0))
1205   {
1206     assert(errno == ENOMEM);
1207     delete operand;
1208     return Err_MemoryAlloc;
1209   }
1210   return 0;
1211 }
1212 
1213 inline int
takeOwnership(NdbQueryOperationDefImpl * operation)1214 NdbQueryBuilderImpl::takeOwnership(NdbQueryOperationDefImpl* operation)
1215 {
1216   if (unlikely(operation == NULL))
1217   {
1218     return Err_MemoryAlloc;
1219   }
1220   else if (unlikely(m_operations.push_back(operation) != 0))
1221   {
1222     assert(errno == ENOMEM);
1223     delete operation;
1224     return Err_MemoryAlloc;
1225   }
1226   return 0;
1227 }
1228 
1229 NdbQueryOperand*
addOperand(NdbQueryOperandImpl * operand)1230 NdbQueryBuilderImpl::addOperand(NdbQueryOperandImpl* operand)
1231 {
1232   returnErrIf(takeOwnership(operand)!=0, Err_MemoryAlloc);
1233   return &operand->getInterface();
1234 }
1235 
1236 ///////////////////////////////////
1237 // The (hidden) Impl of NdbQueryDef
1238 ///////////////////////////////////
1239 NdbQueryDefImpl::
NdbQueryDefImpl(const Vector<NdbQueryOperationDefImpl * > & operations,const Vector<NdbQueryOperandImpl * > & operands,int & error)1240 NdbQueryDefImpl(const Vector<NdbQueryOperationDefImpl*>& operations,
1241                 const Vector<NdbQueryOperandImpl*>& operands,
1242                 int& error)
1243  : m_interface(*this),
1244    m_operations(0),
1245    m_operands(0)
1246 {
1247   if (m_operations.assign(operations) || m_operands.assign(operands))
1248   {
1249     // Failed to allocate memory in Vector::assign().
1250     error = Err_MemoryAlloc;
1251     return;
1252   }
1253 
1254   /* Grab first word, such that serialization of operation 0 will start from
1255    * offset 1, leaving space for the length field to be updated later
1256    */
1257   m_serializedDef.append(0);
1258   for(Uint32 i = 0; i<m_operations.size(); i++){
1259     NdbQueryOperationDefImpl* op =  m_operations[i];
1260     error = op->serializeOperation(m_serializedDef);
1261     if(unlikely(error != 0)){
1262       return;
1263     }
1264   }
1265 
1266   // Set length and number of nodes in tree.
1267   Uint32 cntLen;
1268   QueryTree::setCntLen(cntLen,
1269 		       m_operations[m_operations.size()-1]->getInternalOpNo()+1,
1270 		       m_serializedDef.getSize());
1271   m_serializedDef.put(0,cntLen);
1272 
1273 #ifdef __TRACE_SERIALIZATION
1274   ndbout << "Serialized tree : ";
1275   for(Uint32 i = 0; i < m_serializedDef.getSize(); i++){
1276     char buf[12];
1277     sprintf(buf, "%.8x", m_serializedDef.get(i));
1278     ndbout << buf << " ";
1279   }
1280   ndbout << endl;
1281 #endif
1282 }
1283 
~NdbQueryDefImpl()1284 NdbQueryDefImpl::~NdbQueryDefImpl()
1285 {
1286   // Release all NdbQueryOperations
1287   for (Uint32 i=0; i<m_operations.size(); ++i)
1288   {
1289     delete m_operations[i];
1290   }
1291   for (Uint32 i=0; i<m_operands.size(); ++i)
1292   {
1293     delete m_operands[i];
1294   }
1295 }
1296 
1297 const NdbQueryOperationDefImpl*
getQueryOperation(const char * ident) const1298 NdbQueryDefImpl::getQueryOperation(const char* ident) const
1299 {
1300   if (ident==NULL)
1301     return NULL;
1302 
1303   Uint32 sz = m_operations.size();
1304   const NdbQueryOperationDefImpl* const* opDefs = m_operations.getBase();
1305   for(Uint32 i = 0; i<sz; i++, opDefs++){
1306     const char* opName = (*opDefs)->getName();
1307     if(opName!=NULL && strcmp(opName, ident) == 0)
1308       return *opDefs;
1309   }
1310   return NULL;
1311 }
1312 
1313 NdbQueryDef::QueryType
getQueryType() const1314 NdbQueryDefImpl::getQueryType() const
1315 {
1316   if (!m_operations[0]->isScanOperation())
1317     return NdbQueryDef::LookupQuery;
1318 
1319   for (Uint32 i=1; i<m_operations.size(); ++i)
1320   {
1321     if (m_operations[i]->isScanOperation())
1322       return NdbQueryDef::MultiScanQuery;
1323   }
1324   return NdbQueryDef::SingleScanQuery;
1325 }
1326 
1327 ////////////////////////////////////////////////////////////////
1328 // The (hidden) Impl of NdbQueryOperand (w/ various subclasses)
1329 ////////////////////////////////////////////////////////////////
1330 
1331 /* Implicit typeconversion between related datatypes: */
convertUint8()1332 int NdbInt64ConstOperandImpl::convertUint8()
1333 {
1334   if (unlikely(m_value < 0 || m_value > 0xFF))
1335     return QRY_NUM_OPERAND_RANGE;
1336   m_converted.val.uint8 = (Uint8)m_value;
1337   m_converted.len = static_cast<Uint32>(sizeof(m_converted.val.uint8));
1338   return 0;
1339 }
convertInt8()1340 int NdbInt64ConstOperandImpl::convertInt8()
1341 {
1342   if (unlikely(m_value < -0x80L || m_value > 0x7F))
1343     return QRY_NUM_OPERAND_RANGE;
1344   m_converted.val.int8 = (Int8)m_value;
1345   m_converted.len = static_cast<Uint32>(sizeof(m_converted.val.int8));
1346   return 0;
1347 }
convertUint16()1348 int NdbInt64ConstOperandImpl::convertUint16()
1349 {
1350   if (unlikely(m_value < 0 || m_value > 0xFFFF))
1351     return QRY_NUM_OPERAND_RANGE;
1352   m_converted.val.uint16 = (Uint16)m_value;
1353   m_converted.len = static_cast<Uint32>(sizeof(m_converted.val.uint16));
1354   return 0;
1355 }
convertInt16()1356 int NdbInt64ConstOperandImpl::convertInt16()
1357 {
1358   if (unlikely(m_value < -0x8000L || m_value > 0x7FFF))
1359     return QRY_NUM_OPERAND_RANGE;
1360   m_converted.val.int16 = (Int16)m_value;
1361   m_converted.len = static_cast<Uint32>(sizeof(m_converted.val.int16));
1362   return 0;
1363 }
convertUint24()1364 int NdbInt64ConstOperandImpl::convertUint24()
1365 {
1366   if (unlikely(m_value < 0 || m_value > 0xFFFFFF))
1367     return QRY_NUM_OPERAND_RANGE;
1368   m_converted.val.uint32 = (Uint32)m_value;
1369   m_converted.len = static_cast<Uint32>(sizeof(m_converted.val.uint32));
1370   return 0;
1371 }
convertInt24()1372 int NdbInt64ConstOperandImpl::convertInt24()
1373 {
1374   if (unlikely(m_value < -0x800000L || m_value > 0x7FFFFF))
1375     return QRY_NUM_OPERAND_RANGE;
1376   m_converted.val.int32 = (Int32)m_value;
1377   m_converted.len = static_cast<Uint32>(sizeof(m_converted.val.int32));
1378   return 0;
1379 }
convertUint32()1380 int NdbInt64ConstOperandImpl::convertUint32()
1381 {
1382   if (unlikely(m_value < 0 || m_value > 0xFFFFFFFF))
1383     return QRY_NUM_OPERAND_RANGE;
1384   m_converted.val.uint32 = (Uint32)m_value;
1385   m_converted.len = static_cast<Uint32>(sizeof(m_converted.val.uint32));
1386   return 0;
1387 }
convertInt32()1388 int NdbInt64ConstOperandImpl::convertInt32()
1389 {
1390   if (unlikely(m_value < -((Int64)0x80000000L) || m_value > 0x7FFFFFFF))
1391     return QRY_NUM_OPERAND_RANGE;
1392   m_converted.val.int32 = (Int32)m_value;
1393   m_converted.len = static_cast<Uint32>(sizeof(m_converted.val.int32));
1394   return 0;
1395 }
convertInt64()1396 int NdbInt64ConstOperandImpl::convertInt64()
1397 {
1398   m_converted.val.int64 = m_value;
1399   m_converted.len = static_cast<Uint32>(sizeof(m_converted.val.int64));
1400   return 0;
1401 }
convertUint64()1402 int NdbInt64ConstOperandImpl::convertUint64()
1403 {
1404   m_converted.val.uint64 = (Uint64)m_value;
1405   m_converted.len = static_cast<Uint32>(sizeof(m_converted.val.uint64));
1406   return 0;
1407 }
1408 
convertFloat()1409 int NdbDoubleConstOperandImpl::convertFloat()
1410 {
1411   m_converted.val.flt = (float)m_value;
1412   m_converted.len = static_cast<Uint32>(sizeof(m_converted.val.flt));
1413   return 0;
1414 }
convertDouble()1415 int NdbDoubleConstOperandImpl::convertDouble()
1416 {
1417   m_converted.val.dbl = m_value;
1418   m_converted.len = static_cast<Uint32>(sizeof(m_converted.val.dbl));
1419   return 0;
1420 }
1421 
convertChar()1422 int NdbCharConstOperandImpl::convertChar()
1423 {
1424   Uint32 len = m_column->getLength();
1425   Uint32 srclen = (m_value) ? static_cast<Uint32>(strlen(m_value)) : 0;
1426   if (unlikely(srclen > len)) {
1427     // TODO: Truncates: May silently remove trailing spaces:
1428     return QRY_CHAR_OPERAND_TRUNCATED;
1429     srclen = len;
1430   }
1431 
1432   char* dst = m_converted.getCharBuffer(len);
1433   if (unlikely(dst==NULL))
1434     return Err_MemoryAlloc;
1435 
1436   memcpy (dst, m_value, srclen);
1437   if (unlikely(srclen < len)) {
1438     memset (dst+srclen, ' ', len-srclen);
1439   }
1440   return 0;
1441 } //NdbCharConstOperandImpl::convertChar
1442 
1443 
convertVChar()1444 int NdbCharConstOperandImpl::convertVChar()
1445 {
1446   Uint32 maxlen = m_column->getLength();
1447   Uint32 len = (m_value) ? static_cast<Uint32>(strlen(m_value)) : 0;
1448   if (unlikely(len > maxlen)) {
1449     // TODO: Truncates: May silently remove trailing spaces:
1450     return QRY_CHAR_OPERAND_TRUNCATED;
1451     len = maxlen;
1452   }
1453 
1454   char* dst = m_converted.getCharBuffer(len);
1455   if (unlikely(dst==NULL))
1456     return Err_MemoryAlloc;
1457 
1458   memcpy (dst, m_value, len);
1459   return 0;
1460 } //NdbCharConstOperandImpl::convertVChar
1461 
1462 
1463 /**
1464  * GenericConst is 'raw data' with minimal type checking and conversion capability.
1465  */
1466 int
convert2ColumnType()1467 NdbGenericConstOperandImpl::convert2ColumnType()
1468 {
1469   Uint32 len = m_len;
1470   Uint32 maxSize = m_column->getSizeInBytes();
1471 
1472   char* dst = NULL;
1473 
1474   if (likely(m_column->m_arrayType == NDB_ARRAYTYPE_FIXED))
1475   {
1476     if (unlikely(len != maxSize))
1477       return QRY_OPERAND_HAS_WRONG_TYPE;
1478 
1479     dst = m_converted.getCharBuffer(len);
1480     if (unlikely(dst==NULL))
1481       return Err_MemoryAlloc;
1482   }
1483   else if (m_column->m_arrayType == NDB_ARRAYTYPE_SHORT_VAR)
1484   {
1485     if (unlikely(len+1 > maxSize))
1486       return QRY_CHAR_OPERAND_TRUNCATED;
1487 
1488     dst = m_converted.getCharBuffer(len+1);
1489     if (unlikely(dst==NULL))
1490       return Err_MemoryAlloc;
1491 
1492     *(Uint8*)dst++ = (Uint8)len;
1493   }
1494   else if (m_column->m_arrayType == NDB_ARRAYTYPE_MEDIUM_VAR)
1495   {
1496     if (unlikely(len+2 > maxSize))
1497       return QRY_CHAR_OPERAND_TRUNCATED;
1498 
1499     dst = m_converted.getCharBuffer(len+2);
1500     if (unlikely(dst==NULL))
1501       return Err_MemoryAlloc;
1502 
1503     *(Uint8*)dst++ = (Uint8)(len & 0xFF);
1504     *(Uint8*)dst++ = (Uint8)(len >> 8);
1505   }
1506   else
1507   {
1508     assert(0);
1509   }
1510 
1511   memcpy (dst, m_value, len);
1512   return 0;
1513 }  //NdbGenericConstOperandImpl::convert2ColumnType
1514 
1515 
1516 int
convert2ColumnType()1517 NdbConstOperandImpl::convert2ColumnType()
1518 {
1519   switch(m_column->getType()) {
1520     case NdbDictionary::Column::Tinyint:         return convertInt8();
1521     case NdbDictionary::Column::Tinyunsigned:    return convertUint8();
1522     case NdbDictionary::Column::Smallint:        return convertInt16();
1523     case NdbDictionary::Column::Smallunsigned:   return convertUint16();
1524     case NdbDictionary::Column::Mediumint:       return convertInt24();
1525     case NdbDictionary::Column::Mediumunsigned:  return convertUint24();
1526     case NdbDictionary::Column::Int:             return convertInt32();
1527     case NdbDictionary::Column::Unsigned:        return convertUint32();
1528     case NdbDictionary::Column::Bigint:          return convertInt64();
1529     case NdbDictionary::Column::Bigunsigned:     return convertUint64();
1530     case NdbDictionary::Column::Float:           return convertFloat();
1531     case NdbDictionary::Column::Double:          return convertDouble();
1532 
1533     case NdbDictionary::Column::Decimal:         return convertDec();
1534     case NdbDictionary::Column::Decimalunsigned: return convertUDec();
1535 
1536     case NdbDictionary::Column::Char:            return convertChar();
1537     case NdbDictionary::Column::Varchar:         return convertVChar();
1538     case NdbDictionary::Column::Longvarchar:     return convertLVChar();
1539     case NdbDictionary::Column::Binary:          return convertBin();
1540     case NdbDictionary::Column::Varbinary:       return convertVBin();
1541     case NdbDictionary::Column::Longvarbinary:   return convertLVBin();
1542     case NdbDictionary::Column::Bit:             return convertBit();
1543 
1544     case NdbDictionary::Column::Date:            return convertDate();
1545     case NdbDictionary::Column::Time:            return convertTime();
1546     case NdbDictionary::Column::Datetime:        return convertDatetime();
1547     case NdbDictionary::Column::Timestamp:       return convertTimestamp();
1548     case NdbDictionary::Column::Year:            return convertYear();
1549 
1550     // Type conversion intentionally not supported (yet)
1551     case NdbDictionary::Column::Olddecimal:
1552     case NdbDictionary::Column::Olddecimalunsigned:
1553     case NdbDictionary::Column::Blob:
1554     case NdbDictionary::Column::Text:
1555       // Fall through:
1556 
1557     default:
1558     case NdbDictionary::Column::Undefined:    return QRY_OPERAND_HAS_WRONG_TYPE;
1559   }
1560 
1561   return 0;
1562 } //NdbConstOperandImpl::convert2ColumnType
1563 
1564 
1565 int
bindOperand(const NdbColumnImpl & column,NdbQueryOperationDefImpl & operation)1566 NdbConstOperandImpl::bindOperand(
1567                            const NdbColumnImpl& column,
1568                            NdbQueryOperationDefImpl& operation)
1569 {
1570   const int error = NdbQueryOperandImpl::bindOperand(column,operation);
1571   if (unlikely(error))
1572     return error;
1573 
1574   return convert2ColumnType();
1575 }
1576 
1577 
1578 int
bindOperand(const NdbColumnImpl & column,NdbQueryOperationDefImpl & operation)1579 NdbLinkedOperandImpl::bindOperand(
1580                            const NdbColumnImpl& column,
1581                            NdbQueryOperationDefImpl& operation)
1582 {
1583   const NdbColumnImpl& parentColumn = getParentColumn();
1584 
1585   if (unlikely(column.m_type      != parentColumn.m_type ||
1586                column.m_precision != parentColumn.m_precision ||
1587                column.m_scale     != parentColumn.m_scale ||
1588                column.m_length    != parentColumn.m_length ||
1589                column.m_cs        != parentColumn.m_cs))
1590     return QRY_OPERAND_HAS_WRONG_TYPE;  // Incompatible datatypes
1591 
1592   if (unlikely(column.m_type == NdbDictionary::Column::Blob ||
1593                column.m_type == NdbDictionary::Column::Text))
1594     return QRY_OPERAND_HAS_WRONG_TYPE;  // BLOB/CLOB datatypes intentionally not supported
1595 
1596   // TODO: Allow and autoconvert compatible datatypes
1597 
1598   // Register parent/child operation relations
1599   const int error = operation.linkWithParent(&this->m_parentOperation);
1600   if (unlikely(error))
1601     return error;
1602 
1603   return NdbQueryOperandImpl::bindOperand(column,operation);
1604 }
1605 
1606 
1607 int
bindOperand(const NdbColumnImpl & column,NdbQueryOperationDefImpl & operation)1608 NdbParamOperandImpl::bindOperand(
1609                            const NdbColumnImpl& column,
1610                            NdbQueryOperationDefImpl& operation)
1611 {
1612   if (unlikely(column.m_type == NdbDictionary::Column::Blob ||
1613                column.m_type == NdbDictionary::Column::Text))
1614     return QRY_OPERAND_HAS_WRONG_TYPE;  // BLOB/CLOB datatypes intentionally not supported
1615 
1616   const int res = operation.addParamRef(this);
1617   if (unlikely(res != 0))
1618   {
1619     return res;
1620   }
1621   return NdbQueryOperandImpl::bindOperand(column,operation);
1622 }
1623 
1624 
1625 /////////////////////////////////////////////////////////////////
1626 // The (hidden) Impl of NdbQueryOperation (w/ various subclasses)
1627 ///////////////////////>/////////////////////////////////////////
1628 
NdbQueryLookupOperationDefImpl(const NdbTableImpl & table,const NdbQueryOperand * const keys[],const NdbQueryOptionsImpl & options,const char * ident,Uint32 opNo,Uint32 internalOpNo,int & error)1629 NdbQueryLookupOperationDefImpl::NdbQueryLookupOperationDefImpl (
1630                            const NdbTableImpl& table,
1631                            const NdbQueryOperand* const keys[],
1632                            const NdbQueryOptionsImpl& options,
1633                            const char* ident,
1634                            Uint32      opNo,
1635                            Uint32      internalOpNo,
1636                            int& error)
1637   : NdbQueryOperationDefImpl(table, options, ident, opNo,
1638                              internalOpNo, error),
1639    m_interface(*this)
1640 {
1641   int i;
1642   for (i=0; i<MAX_ATTRIBUTES_IN_INDEX; ++i)
1643   { if (keys[i] == NULL)
1644       break;
1645     m_keys[i] = &keys[i]->getImpl();
1646   }
1647   assert (i > 0);
1648   assert (keys[i] == NULL);
1649   m_keys[i] = NULL;
1650 }
1651 
NdbQueryIndexScanOperationDefImpl(const NdbIndexImpl & index,const NdbTableImpl & table,const NdbQueryIndexBound * bound,const NdbQueryOptionsImpl & options,const char * ident,Uint32 opNo,Uint32 internalOpNo,int & error)1652 NdbQueryIndexScanOperationDefImpl::NdbQueryIndexScanOperationDefImpl (
1653                            const NdbIndexImpl& index,
1654                            const NdbTableImpl& table,
1655                            const NdbQueryIndexBound* bound,
1656                            const NdbQueryOptionsImpl& options,
1657                            const char* ident,
1658                            Uint32      opNo,
1659                            Uint32      internalOpNo,
1660                            int& error)
1661   : NdbQueryScanOperationDefImpl(table, options, ident, opNo, internalOpNo,
1662                                  error),
1663   m_interface(*this),
1664   m_index(index),
1665   m_paramInPruneKey(false)
1666 {
1667   memset(&m_bound, 0, sizeof m_bound);
1668   if (bound!=NULL) {
1669 
1670     if (bound->m_low!=NULL) {
1671       int i;
1672       for (i=0; bound->m_low[i] != NULL; ++i)
1673       { assert (i<MAX_ATTRIBUTES_IN_INDEX);
1674         m_bound.low[i] = &bound->m_low[i]->getImpl();
1675       }
1676       m_bound.lowKeys = i;
1677     } else {
1678       m_bound.lowKeys = 0;
1679     }
1680 
1681     if (bound->m_high!=NULL) {
1682       int i;
1683       for (i=0; bound->m_high[i] != NULL; ++i)
1684       { assert (i<MAX_ATTRIBUTES_IN_INDEX);
1685         m_bound.high[i] = &bound->m_high[i]->getImpl();
1686       }
1687       m_bound.highKeys = i;
1688     } else {
1689       m_bound.highKeys = 0;
1690     }
1691 
1692     m_bound.lowIncl = bound->m_lowInclusive;
1693     m_bound.highIncl = bound->m_highInclusive;
1694   }
1695   else {
1696     m_bound.lowKeys = m_bound.highKeys = 0;
1697     m_bound.lowIncl = m_bound.highIncl = true;
1698   }
1699 }
1700 
1701 int
checkPrunable(const Uint32Buffer & keyInfo,Uint32 shortestBound,bool & isPruned,Uint32 & hashValue) const1702 NdbQueryIndexScanOperationDefImpl::checkPrunable(
1703                               const Uint32Buffer& keyInfo,
1704 			      Uint32  shortestBound,
1705                               bool&   isPruned,
1706                               Uint32& hashValue) const  // 'hashValue' only defined if 'isPruned'
1707 {
1708   /**
1709    * Determine if scan may be pruned to a single partition:
1710    */
1711   isPruned = false;
1712   const NdbRecord* const tableRecord = getTable().getDefaultRecord();
1713   const NdbRecord* const indexRecord = m_index.getDefaultRecord();
1714   /**
1715    * This is the prefix (in number of fields) of the index key that will contain
1716    * all the distribution key fields.
1717    */
1718   const Uint32 prefixLength = indexRecord->m_min_distkey_prefix_length;
1719 
1720   if (indexRecord->m_no_of_distribution_keys != tableRecord->m_no_of_distribution_keys)
1721   {
1722     return 0; // Index does not contain all fields in the distribution key.
1723   }
1724   else if (shortestBound < prefixLength)
1725   {
1726     // Bounds set on query instance are to short to contain full dist key.
1727     return 0;
1728   }
1729   // Bounds being part of query definitions should have been covered by 'shortestBound' above
1730   assert( (m_bound.lowKeys+m_bound.highKeys==0) ||
1731           (m_bound.lowKeys >= prefixLength && m_bound.highKeys >= prefixLength));
1732 
1733   /**
1734    * The scan will be prunable if all upper and lower bound pairs are equal
1735    * for the prefix containing the distribution key, and if all bounds
1736    * give the same hash value for the distribution key.
1737    */
1738   Uint32 keyPos = 0;
1739 
1740   // Loop over all bounds.
1741   Uint32 boundNo = 0;
1742   while (keyPos < keyInfo.getSize())
1743   {
1744     const Uint32 keyEnd = keyPos + (keyInfo.get(keyPos) >> 16);
1745     Ndb::Key_part_ptr distKey[NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY+1]
1746       = {{NULL, 0}};
1747 
1748     // Loop over the fields in each bound.
1749     Uint32 keyPartNo = 0;
1750     Uint32 distKeyPartNo = 0;
1751     while (keyPos < keyEnd)
1752     {
1753       const NdbIndexScanOperation::BoundType type =
1754         static_cast<NdbIndexScanOperation::BoundType>
1755         (keyInfo.get(keyPos) & 0xF);
1756       const AttributeHeader attHead1(keyInfo.get(keyPos+1));
1757       const Ndb::Key_part_ptr keyPart1 = { keyInfo.addr(keyPos+2),
1758                                            attHead1.getByteSize() };
1759 
1760       keyPos += 1+1+attHead1.getDataSize();  // Skip data read above.
1761 
1762       const NdbColumnImpl& column
1763         = NdbColumnImpl::getImpl(*m_index.getColumn(keyPartNo));
1764 
1765       switch (type)
1766       {
1767       case NdbIndexScanOperation::BoundEQ:
1768         break;
1769       case NdbIndexScanOperation::BoundGE:
1770       case NdbIndexScanOperation::BoundGT:
1771         /**
1772          * We have a one-sided limit for this field, which is part of
1773          * the prefix containing the distribution key. We thus cannot prune.
1774          */
1775         return 0;
1776       case NdbIndexScanOperation::BoundLE:
1777       case NdbIndexScanOperation::BoundLT:
1778         /**
1779          * If keyPart1 is a lower limit for this column, there may be an upper
1780          * limit also.
1781          */
1782         if (keyPos == keyEnd ||
1783             ((keyInfo.get(keyPos) & 0xF) != NdbIndexScanOperation::BoundGE &&
1784              (keyInfo.get(keyPos) & 0xF) != NdbIndexScanOperation::BoundGT))
1785         {
1786           /**
1787            * We have a one-sided limit for this field, which is part of
1788            * the prefix containing the distribution key. We thus cannot prune.
1789            */
1790           return 0;
1791         }
1792         else // There is an upper limit.
1793         {
1794           const AttributeHeader attHeadHigh(keyInfo.get(keyPos+1));
1795           const Ndb::Key_part_ptr highKeyPart = { keyInfo.addr(keyPos+2),
1796                                                   attHeadHigh.getByteSize() };
1797 
1798           keyPos += 1+1+attHeadHigh.getDataSize();  // Skip data read above.
1799 
1800           /**
1801            * We must compare key parts in the prefix that contains the
1802            * distribution key. Even if subseqent parts should be different,
1803            * all matching tuples must have the same (distribution) hash.
1804            *
1805            * For example, assume there is a ordered index on {a, dist_key, b}.
1806            * Then any tuple in the range {a=c1, <dist key=c2>, b=c3} to
1807            * {a=c1, dist_key=c2, b=c4} will have dist_key=c2.
1808            * Then consider a range where fields before the distribution key are
1809            * different, e.g. {a=c6, <dist key=c7>, b=c8} to
1810            * {a=c9, <dist key=c7>, b=c8} then matching tuples can have any value
1811            * for the distribution key as long as c6 <= a <= c9, so there can be
1812            * no pruning.
1813            */
1814           assert(column.m_keyInfoPos < tableRecord->noOfColumns);
1815           const NdbRecord::Attr& recAttr = tableRecord->columns[column.m_keyInfoPos];
1816           /**
1817            * Shinked varchars should already have been converted in
1818            * NdbQueryImpl::setBound(), so no need to deal with them here.
1819            * (See also bug#56853 and http://lists.mysql.com/commits/121387 .)
1820            */
1821           assert((recAttr.flags & NdbRecord::IsMysqldShrinkVarchar) == 0);
1822           const int res=
1823             (*recAttr.compare_function)(recAttr.charset_info,
1824                                         keyPart1.ptr, keyPart1.len,
1825                                         highKeyPart.ptr, highKeyPart.len);
1826           if (res!=0)
1827           {  // Not equal
1828             return 0;
1829           }
1830         } // if (keyPos == keyEnd ||
1831         break;
1832       default:
1833         assert(false);
1834       } // switch (type)
1835 
1836       // If this field is part of the distribution key:
1837       // Keep the key value for later use by Ndb::computeHash.
1838       if (getTable().m_columns[column.m_keyInfoPos]->m_distributionKey)
1839       {
1840         /* Find the proper place for this field in the distribution key.*/
1841         Ndb::Key_part_ptr* distKeyPtr = distKey;
1842         for (Uint32 i = 0; i < column.m_keyInfoPos; i++)
1843         {
1844           if (getTable().m_columns[i]->m_distributionKey)
1845           {
1846             distKeyPtr++;
1847           }
1848         }
1849 
1850         assert(distKeyPtr->len == 0 && distKeyPtr->ptr == NULL);
1851         *distKeyPtr = keyPart1;
1852         distKeyPartNo++;
1853       }
1854 
1855       keyPartNo++;
1856       if (keyPartNo == prefixLength)
1857       {
1858         /**
1859          * Skip key parts after the prefix containing the distribution key,
1860          * as these do not affect prunability.
1861          */
1862         keyPos = keyEnd;
1863       }
1864     } // while (keyPos < keyEnd)
1865 
1866     assert(distKeyPartNo == tableRecord->m_no_of_distribution_keys);
1867 
1868     // hi/low are equal and prunable bounds.
1869     Uint32 newHashValue = 0;
1870     const int error = Ndb::computeHash(&newHashValue, &getTable(), distKey,
1871                                        NULL, 0);
1872     if (unlikely(error))
1873       return error;
1874 
1875     if (boundNo == 0)
1876     {
1877       hashValue = newHashValue;
1878     }
1879     else if (hashValue != newHashValue)
1880     {
1881       /* This bound does not have the same hash value as the previous one.
1882        * So we make the pessimistic assumtion that it will not hash to the
1883        * same node. (See also comments in
1884        * NdbScanOperation::getPartValueFromInfo()).
1885        */
1886       return 0;
1887     }
1888 
1889     boundNo++;
1890   } // while (keyPos < keyInfo.getSize())
1891 
1892   isPruned = true;
1893   return 0;
1894 } // NdbQueryIndexScanOperationDefImpl::checkPrunable
1895 
1896 
NdbQueryOperationDefImpl(const NdbTableImpl & table,const NdbQueryOptionsImpl & options,const char * ident,Uint32 opNo,Uint32 internalOpNo,int & error)1897 NdbQueryOperationDefImpl::NdbQueryOperationDefImpl (
1898                                      const NdbTableImpl& table,
1899                                      const NdbQueryOptionsImpl& options,
1900                                      const char* ident,
1901                                      Uint32      opNo,
1902                                      Uint32      internalOpNo,
1903                                      int& error)
1904   :m_isPrepared(false),
1905    m_diskInChildProjection(false),
1906    m_table(table),
1907    m_ident(ident),
1908    m_opNo(opNo), m_internalOpNo(internalOpNo),
1909    m_options(options),
1910    m_parent(NULL),
1911    m_children(0),
1912    m_params(0),
1913    m_spjProjection(0)
1914 {
1915   if (unlikely(m_internalOpNo >= NDB_SPJ_MAX_TREE_NODES))
1916   {
1917     error = QRY_DEFINITION_TOO_LARGE;
1918     return;
1919   }
1920   if (m_options.m_parent != NULL)
1921   {
1922     m_parent = m_options.m_parent;
1923     const int res = m_parent->addChild(this);
1924     if (unlikely(res != 0))
1925     {
1926       error = res;
1927       return;
1928     }
1929   }  // else, ::linkWithParent() will assign 'm_parent'
1930 }
1931 
1932 
1933 int
addChild(NdbQueryOperationDefImpl * childOp)1934 NdbQueryOperationDefImpl::addChild(NdbQueryOperationDefImpl* childOp)
1935 {
1936   for (Uint32 i=0; i<m_children.size(); ++i)
1937   { if (m_children[i] == childOp)
1938       return 0;
1939   }
1940   if (likely(m_children.push_back(childOp) == 0))
1941   {
1942     return 0;
1943   }
1944   else
1945   {
1946     assert(errno == ENOMEM);
1947     return Err_MemoryAlloc;
1948   }
1949 }
1950 
1951 void
removeChild(const NdbQueryOperationDefImpl * childOp)1952 NdbQueryOperationDefImpl::removeChild(const NdbQueryOperationDefImpl* childOp)
1953 {
1954   for (unsigned i=0; i<m_children.size(); ++i)
1955   {
1956     if (m_children[i] == childOp)
1957     {
1958       m_children.erase(i);
1959       return;
1960     }
1961   }
1962 }
1963 
1964 bool
isChildOf(const NdbQueryOperationDefImpl * parentOp) const1965 NdbQueryOperationDefImpl::isChildOf(const NdbQueryOperationDefImpl* parentOp) const
1966 {
1967   if (m_parent != NULL)
1968   { if (this->m_parent == parentOp)
1969     {
1970 #ifndef NDEBUG
1971       // Assert that parentOp also refer 'this' as a child.
1972       for (Uint32 j=0; j<parentOp->getNoOfChildOperations(); j++)
1973       { if (&parentOp->getChildOperation(j) == this)
1974           return true;
1975       }
1976       assert(false);
1977 #endif
1978       return true;
1979     }
1980     else if (m_parent->isChildOf(parentOp))
1981     {
1982       return true;
1983     }
1984   }
1985   return false;
1986 }
1987 
1988 int
linkWithParent(NdbQueryOperationDefImpl * parentOp)1989 NdbQueryOperationDefImpl::linkWithParent(NdbQueryOperationDefImpl* parentOp)
1990 {
1991   if (this->isChildOf(parentOp))
1992   {
1993     // There should only be a single parent/child relationship registered.
1994     return 0;
1995   }
1996 
1997   if (m_parent != NULL)
1998   {
1999     /**
2000      * Multiple parental relationship not allowed.
2001      * It is likely that the conflict is due to one of the
2002      * parents actually being a grand parent.
2003      * This can be resolved if existing parent actually was a grandparent.
2004      * Then register new parentOp as the real parrent.
2005      */
2006     if (parentOp->isChildOf(m_parent))
2007     { // Remove existing grandparent linkage being replaced by parentOp.
2008       m_parent->removeChild(this);
2009       m_parent = NULL;
2010     }
2011     else
2012     { // This is a real multiparent error.
2013       return QRY_MULTIPLE_PARENTS;
2014     }
2015   }
2016   m_parent = parentOp;
2017   parentOp->addChild(this);
2018   return 0;
2019 }
2020 
2021 
2022 // Register a linked reference to a column available from this operation
2023 Uint32
addColumnRef(const NdbColumnImpl * column,int & error)2024 NdbQueryOperationDefImpl::addColumnRef(const NdbColumnImpl* column,
2025                                        int& error)
2026 {
2027   Uint32 spjRef;
2028   for (spjRef=0; spjRef<m_spjProjection.size(); ++spjRef)
2029   { if (m_spjProjection[spjRef] == column)
2030       return spjRef;
2031   }
2032 
2033   // Add column if not already available
2034   if (unlikely(m_spjProjection.push_back(column) != 0))
2035   {
2036     assert(errno == ENOMEM);
2037     error = Err_MemoryAlloc;
2038     return ~0;
2039   }
2040   if (column->getStorageType() == NDB_STORAGETYPE_DISK)
2041   {
2042     m_diskInChildProjection = true;
2043   }
2044   return spjRef;
2045 }
2046 
addParamRef(const NdbParamOperandImpl * param)2047 int NdbQueryOperationDefImpl::addParamRef(const NdbParamOperandImpl* param)
2048 {
2049   if (unlikely(m_params.push_back(param) != 0))
2050   {
2051     assert(errno == ENOMEM);
2052     return Err_MemoryAlloc;
2053   }
2054   return 0;
2055 }
2056 
2057 /** This class is used for serializing sequences of 16 bit integers,
2058  * where the first 16 bit integer specifies the length of the sequence.
2059  */
2060 class Uint16Sequence{
2061 public:
Uint16Sequence(Uint32Buffer & buffer,Uint32 size)2062   explicit Uint16Sequence(Uint32Buffer& buffer, Uint32 size):
2063     m_seq(NULL),
2064     m_size(size),
2065     m_pos(0),
2066     m_finished(false)
2067  {
2068     m_seq = buffer.alloc(1 + size/2);
2069     assert (size <= 0xFFFF);
2070     m_seq[0] = size;
2071   }
2072 
~Uint16Sequence()2073   ~Uint16Sequence()
2074   { assert(m_finished);
2075   }
2076 
2077   /** Add an item to the sequence.*/
append(Uint16 value)2078   void append(Uint16 value) {
2079     assert(m_pos < m_size);
2080     assert(m_seq);
2081     m_pos++;
2082     if ((m_pos & 1) == 1) {
2083       m_seq[m_pos/2] |= (value<<16);
2084     } else {
2085       m_seq[m_pos/2] = value;
2086     }
2087   }
2088 
2089 
2090   /** End the sequence and pad possibly unused Int16 word at end. */
finish()2091   void finish() {
2092     assert(m_pos == m_size);
2093     assert(!m_finished);
2094     m_finished = true;
2095     if (m_pos>0) {
2096       if ((m_pos & 1) == 0) {
2097 	m_seq[m_pos/2] |= (0xBABE<<16);
2098       }
2099     }
2100   }
2101 
2102 private:
2103   /** Should not be copied.*/
2104   Uint16Sequence(Uint16Sequence&);
2105   /** Should not be assigned.*/
2106   Uint16Sequence& operator=(Uint16Sequence&);
2107 
2108   Uint32*       m_seq;      // Preallocated buffer to append Uint16's into
2109   const Uint32  m_size;     // Uint16 words available in m_seq
2110   Uint32        m_pos;      // Current Uint16 word to fill in
2111   bool          m_finished; // Debug assert of correct call convention
2112 };
2113 
2114 
2115 Uint32
appendParentList(Uint32Buffer & serializedDef) const2116 NdbQueryOperationDefImpl::appendParentList(Uint32Buffer& serializedDef) const
2117 {
2118   if (getParentOperation() != NULL)
2119   {
2120     Uint16Sequence parentSeq(serializedDef, 1);
2121     assert (getParentOperation()->getInternalOpNo() < getInternalOpNo());
2122     parentSeq.append(getParentOperation()->getInternalOpNo());
2123     parentSeq.finish();
2124     return DABits::NI_HAS_PARENT;
2125   }
2126   return 0;
2127 } // NdbQueryOperationDefImpl::appendParentList
2128 
2129 
2130 /* Add the projection that should be send to the SPJ block such that
2131  * child operations can be instantiated.
2132  */
2133 Uint32
appendChildProjection(Uint32Buffer & serializedDef) const2134 NdbQueryOperationDefImpl::appendChildProjection(Uint32Buffer& serializedDef) const
2135 {
2136   Uint32 requestInfo = 0;
2137   if (m_spjProjection.size() > 0 || getNoOfChildOperations() > 0)
2138   {
2139     requestInfo |= DABits::NI_LINKED_ATTR;
2140     Uint16Sequence spjProjSeq(serializedDef, m_spjProjection.size());
2141     for (Uint32 i = 0; i<m_spjProjection.size(); i++)
2142     {
2143       spjProjSeq.append(m_spjProjection[i]->getColumnNo());
2144     }
2145     spjProjSeq.finish();
2146 
2147     if (m_diskInChildProjection)
2148     {
2149       requestInfo |= DABits::NI_LINKED_DISK;
2150     }
2151   }
2152   return requestInfo;
2153 } // NdbQueryOperationDefImpl::appendChildProjection
2154 
2155 /** Used by NdbQueryOperationDefImpl::printTree() to print the arrows
2156  * that connect the tree nodes.
2157  */
printMargin(Uint32 depth,NdbQueryOperationDefImpl::SiblingMask hasMoreSiblingsMask,bool header)2158 static void printMargin(Uint32 depth,
2159                         NdbQueryOperationDefImpl::SiblingMask
2160                         hasMoreSiblingsMask,
2161                         bool header)
2162 {
2163   if (depth > 0)
2164   {
2165     // Print vertical lines to the siblings of the ancestore nodes.
2166     for (Uint32 i = 0; i<depth-1; i++)
2167     {
2168       if (hasMoreSiblingsMask.get(i+1))
2169       {
2170         ndbout << "|  ";
2171       }
2172       else
2173       {
2174         ndbout << "   ";
2175       }
2176     }
2177     if (header)
2178     {
2179       ndbout << "+->";
2180     }
2181     else if (hasMoreSiblingsMask.get(depth))
2182     {
2183       ndbout << "|  ";
2184     }
2185     else
2186     {
2187       ndbout << "   ";
2188     }
2189   }
2190 }
2191 
2192 void
printTree(Uint32 depth,SiblingMask hasMoreSiblingsMask) const2193 NdbQueryOperationDefImpl::printTree(Uint32 depth,
2194                                     SiblingMask hasMoreSiblingsMask) const
2195 {
2196   // Print vertical line leading down to this node.
2197   SiblingMask firstLineMask = hasMoreSiblingsMask;
2198   firstLineMask.set(depth);
2199   printMargin(depth, firstLineMask, false);
2200   ndbout << endl;
2201   // Print +-> leading to this node.
2202   printMargin(depth, hasMoreSiblingsMask, true);
2203   ndbout << NdbQueryOperationDef::getTypeName(getType()) << endl;
2204   printMargin(depth, hasMoreSiblingsMask, false);
2205   // Print attributes.
2206   ndbout << " opNo: " << getOpNo()
2207          << " (internal: " << getInternalOpNo() << ")" << endl;
2208   printMargin(depth, hasMoreSiblingsMask, false);
2209   ndbout << " table: " << getTable().getName() << endl;
2210   if (getIndex() != NULL)
2211   {
2212     printMargin(depth, hasMoreSiblingsMask, false);
2213     ndbout << " index: " << getIndex()->getName() << endl;
2214   }
2215 
2216   for (int childNo = 0;
2217        childNo < static_cast<int>(getNoOfChildOperations());
2218        childNo++)
2219   {
2220     if (childNo == 0)
2221     {
2222       /* For each child but the last one, use a mask with an extra bit set to
2223        * indicate that there are more siblings.
2224        */
2225       hasMoreSiblingsMask.set(depth+1);
2226     }
2227     if (childNo == static_cast<int>(getNoOfChildOperations()) - 1)
2228     {
2229       // The last child has no more siblings.
2230       hasMoreSiblingsMask.clear(depth+1);
2231     }
2232     getChildOperation(childNo).printTree(depth+1, hasMoreSiblingsMask);
2233   }
2234 } // NdbQueryOperationDefImpl::printTree()
2235 
2236 
2237 Uint32
appendKeyPattern(Uint32Buffer & serializedDef) const2238 NdbQueryLookupOperationDefImpl::appendKeyPattern(Uint32Buffer& serializedDef) const
2239 {
2240   Uint32 appendedPattern = 0;
2241 
2242   /**
2243    * Key value for root operation is constructed when query is instantiated with
2244    * NdbQueryOperationImpl::prepareIndexKeyInfo()
2245    */
2246   if (getOpNo() == 0)
2247     return 0;
2248 
2249   if (m_keys[0]!=NULL)
2250   {
2251     Uint32 startPos = serializedDef.getSize();
2252     serializedDef.append(0);     // Grab first word for length field, updated at end
2253     int paramCnt = 0;
2254     int keyNo = 0;
2255     const NdbQueryOperandImpl* key = m_keys[0];
2256     do
2257     {
2258       switch(key->getKind()){
2259       case NdbQueryOperandImpl::Linked:
2260       {
2261         appendedPattern |= DABits::NI_KEY_LINKED;
2262         const NdbLinkedOperandImpl& linkedOp = *static_cast<const NdbLinkedOperandImpl*>(key);
2263         const NdbQueryOperationDefImpl* parent = getParentOperation();
2264         uint32 levels = 0;
2265         while (parent != &linkedOp.getParentOperation())
2266         {
2267           if (parent->getType() == NdbQueryOperationDef::UniqueIndexAccess)  // Represented with two nodes in QueryTree
2268             levels+=2;
2269           else
2270             levels+=1;
2271           parent = parent->getParentOperation();
2272           assert(parent != NULL);
2273         }
2274         if (levels > 0)
2275         {
2276           serializedDef.append(QueryPattern::parent(levels));
2277         }
2278         serializedDef.append(QueryPattern::col(linkedOp.getLinkedColumnIx()));
2279         break;
2280       }
2281       case NdbQueryOperandImpl::Const:
2282       {
2283         appendedPattern |= DABits::NI_KEY_CONSTS;
2284         const NdbConstOperandImpl& constOp = *static_cast<const NdbConstOperandImpl*>(key);
2285 
2286         // No of words needed for storing the constant data.
2287         const Uint32 wordCount =  AttributeHeader::getDataSize(constOp.getSizeInBytes());
2288         // Set type and length in words of key pattern field.
2289         serializedDef.append(QueryPattern::data(wordCount));
2290         serializedDef.appendBytes(constOp.getAddr(),constOp.getSizeInBytes());
2291         break;
2292       }
2293       case NdbQueryOperandImpl::Param:
2294       {
2295         appendedPattern |= DABits::NI_KEY_PARAMS;
2296         serializedDef.append(QueryPattern::param(paramCnt++));
2297         break;
2298       }
2299       default:
2300         assert(false);
2301       }
2302       key = m_keys[++keyNo];
2303     } while (key!=NULL);
2304 
2305     // Set total length of key pattern.
2306     Uint32 len = serializedDef.getSize() - startPos -1;
2307     serializedDef.put(startPos, (paramCnt << 16) | (len));
2308   }
2309 
2310   return appendedPattern;
2311 } // NdbQueryLookupOperationDefImpl::appendKeyPattern
2312 
2313 
2314 Uint32
appendPrunePattern(Uint32Buffer & serializedDef)2315 NdbQueryIndexScanOperationDefImpl::appendPrunePattern(Uint32Buffer& serializedDef)
2316 {
2317   Uint32 appendedPattern = 0;
2318 
2319   /**
2320    * Bound value for root operation is constructed when query is instantiated with
2321    * NdbQueryOperationImpl::prepareIndexKeyInfo()
2322    */
2323   if (getOpNo() == 0)
2324     return 0;
2325 
2326   if (m_bound.lowKeys>0 || m_bound.highKeys>0)
2327   {
2328     const NdbRecord* const tableRecord = getTable().getDefaultRecord();
2329     const NdbRecord* const indexRecord = m_index.getDefaultRecord();
2330 
2331     if (indexRecord->m_no_of_distribution_keys != tableRecord->m_no_of_distribution_keys)
2332     {
2333       return 0; // Index does not contain all fields in the distribution key.
2334     }
2335 
2336     /**
2337      * This is the prefix (in number of fields) of the index key that will contain
2338      * all the distribution key fields.
2339      */
2340     Uint32 distKeys = indexRecord->m_min_distkey_prefix_length;
2341     if (m_bound.lowKeys < distKeys || m_bound.highKeys < distKeys)
2342     {
2343       // Bounds set on query definition are to short to contain full dist key.
2344       return 0;
2345     }
2346 
2347     /* All low/high bounds should be defined equal within the 'distKey' */
2348     for (unsigned keyNo = 0; keyNo < distKeys; keyNo++)
2349     {
2350       if (m_bound.low[keyNo] != m_bound.high[keyNo])
2351         return 0;
2352     }
2353 
2354     {
2355       int paramCnt = 0;
2356       Uint32 startPos = serializedDef.getSize();
2357       serializedDef.append(0);     // Grab first word for length field, updated at end
2358 
2359       for (unsigned i = 0; i < indexRecord->distkey_index_length; i++)
2360       {
2361         const unsigned keyNo = indexRecord->distkey_indexes[i];
2362         assert(keyNo<indexRecord->noOfColumns);
2363         const NdbRecord::Attr& indexAttr = indexRecord->columns[keyNo];
2364         assert(indexAttr.flags & NdbRecord::IsDistributionKey);
2365         assert(indexAttr.index_attrId<m_bound.lowKeys);
2366         const NdbQueryOperandImpl* key = m_bound.low[indexAttr.index_attrId];
2367 
2368         switch(key->getKind())
2369         {
2370           case NdbQueryOperandImpl::Linked:
2371           {
2372             appendedPattern |= QN_ScanIndexNode::SI_PRUNE_LINKED;
2373             const NdbLinkedOperandImpl& linkedOp = *static_cast<const NdbLinkedOperandImpl*>(key);
2374             const NdbQueryOperationDefImpl* parent = getParentOperation();
2375             uint32 levels = 0;
2376             while (parent != &linkedOp.getParentOperation())
2377             {
2378               if (parent->getType() == NdbQueryOperationDef::UniqueIndexAccess)  // Represented with two nodes in QueryTree
2379                 levels+=2;
2380               else
2381                 levels+=1;
2382               parent = parent->getParentOperation();
2383               assert(parent != NULL);
2384             }
2385             if (levels > 0)
2386             {
2387               serializedDef.append(QueryPattern::parent(levels));
2388             }
2389             serializedDef.append(QueryPattern::col(linkedOp.getLinkedColumnIx()));
2390             break;
2391           }
2392           case NdbQueryOperandImpl::Const:
2393           {
2394 //          appendedPattern |= QN_ScanIndexNode::SI_PRUNE_CONST;
2395             const NdbConstOperandImpl& constOp = *static_cast<const NdbConstOperandImpl*>(key);
2396 
2397             // No of words needed for storing the constant data.
2398             const Uint32 wordCount =  AttributeHeader::getDataSize(constOp.getSizeInBytes());
2399             // Set type and length in words of key pattern field.
2400             serializedDef.append(QueryPattern::data(wordCount));
2401             serializedDef.appendBytes(constOp.getAddr(),
2402                                       constOp.getSizeInBytes());
2403             break;
2404           }
2405           case NdbQueryOperandImpl::Param:
2406             appendedPattern |= QN_ScanIndexNode::SI_PRUNE_PARAMS;
2407             m_paramInPruneKey = true;
2408             serializedDef.append(QueryPattern::param(paramCnt++));
2409             break;
2410           default:
2411             assert(false);
2412         }
2413       }
2414 
2415       // Set total length of bound pattern.
2416       Uint32 len = serializedDef.getSize() - startPos -1;
2417       serializedDef.put(startPos, (paramCnt << 16) | (len));
2418       appendedPattern |= QN_ScanIndexNode::SI_PRUNE_PATTERN;
2419     }
2420   }
2421   return appendedPattern;
2422 } // NdbQueryIndexScanOperationDefImpl::appendPrunePattern
2423 
2424 
2425 Uint32
appendBoundValue(Uint32Buffer & serializedDef,NdbIndexScanOperation::BoundType type,const NdbQueryOperandImpl * value,int & paramCnt) const2426 NdbQueryIndexScanOperationDefImpl::appendBoundValue(
2427                                  Uint32Buffer& serializedDef,
2428                                  NdbIndexScanOperation::BoundType type,
2429                                  const NdbQueryOperandImpl* value,
2430                                  int& paramCnt) const
2431 {
2432   Uint32 appendedPattern = 0;
2433 
2434   // Append BoundType as a constant value
2435   serializedDef.append(QueryPattern::data(1));
2436   serializedDef.append(type);
2437 
2438   switch(value->getKind())
2439   {
2440     case NdbQueryOperandImpl::Linked:
2441     {
2442       appendedPattern |= DABits::NI_KEY_LINKED;
2443       const NdbLinkedOperandImpl& linkedOp = *static_cast<const NdbLinkedOperandImpl*>(value);
2444       const NdbQueryOperationDefImpl* parent = getParentOperation();
2445       uint32 levels = 0;
2446       while (parent != &linkedOp.getParentOperation())
2447       {
2448         if (parent->getType() == NdbQueryOperationDef::UniqueIndexAccess)  // Represented with two nodes in QueryTree
2449           levels+=2;
2450         else
2451           levels+=1;
2452         parent = parent->getParentOperation();
2453         assert(parent != NULL);
2454       }
2455       if (levels > 0)
2456       {
2457         serializedDef.append(QueryPattern::parent(levels));
2458       }
2459 //    serializedDef.append(QueryPattern::col(linkedOp.getLinkedColumnIx()));
2460       serializedDef.append(QueryPattern::attrInfo(linkedOp.getLinkedColumnIx())); // col w/ AttributeHeader
2461       break;
2462     }
2463     case NdbQueryOperandImpl::Const:
2464     {
2465       appendedPattern |= DABits::NI_KEY_CONSTS;
2466       const NdbConstOperandImpl& constOp = *static_cast<const NdbConstOperandImpl*>(value);
2467 
2468       // Build the AttributeHeader for const value
2469       // (AttributeId is later filled in by SPJ in Dbspj::scanIndex_fixupBound())
2470       AttributeHeader ah(0, constOp.getSizeInBytes());
2471 
2472       // Constant is then appended as AttributeHeader + const-value
2473       serializedDef.append(QueryPattern::data(1+ah.getDataSize()));
2474       serializedDef.append(ah.m_value);
2475       serializedDef.appendBytes(constOp.getAddr(),constOp.getSizeInBytes());
2476       break;
2477     }
2478     case NdbQueryOperandImpl::Param:
2479     {
2480       appendedPattern |= DABits::NI_KEY_PARAMS;
2481 //    serializedDef.append(QueryPattern::param(paramCnt++));
2482       serializedDef.append(QueryPattern::paramHeader(paramCnt++));
2483       break;
2484     }
2485     default:
2486       assert(false);
2487   }
2488 
2489   return appendedPattern;
2490 } // NdbQueryIndexScanOperationDefImpl::appendBoundValue
2491 
2492 
2493 /**
2494  * Append the complete patterns for hi & low bound for an index range scan.
2495  * Each bound may consist of multiple values which in turn are
2496  * added with NdbQueryIndexScanOperationDefImpl::appendBoundPattern()
2497  */
2498 Uint32
appendBoundPattern(Uint32Buffer & serializedDef) const2499 NdbQueryIndexScanOperationDefImpl::appendBoundPattern(Uint32Buffer& serializedDef) const
2500 {
2501   Uint32 appendedPattern = 0;
2502 
2503   /**
2504    * Bound value for root operation is constructed when query is instantiated with
2505    * NdbQueryOperationImpl::prepareIndexKeyInfo()
2506    */
2507   if (getOpNo() == 0)
2508     return 0;
2509 
2510   if (m_bound.lowKeys>0 || m_bound.highKeys>0)
2511   {
2512     int paramCnt = 0;
2513     Uint32 startPos = serializedDef.getSize();
2514     serializedDef.append(0);     // Grab first word for length field, updated at end
2515 
2516     const uint key_count =
2517        (m_bound.lowKeys >= m_bound.highKeys) ? m_bound.lowKeys : m_bound.highKeys;
2518 
2519     for (uint keyNo=0; keyNo<key_count; ++keyNo)
2520     {
2521       NdbIndexScanOperation::BoundType bound_type;
2522 
2523       /* If upper and lower limits are equal, a single BoundEQ is sufficient */
2524       if (keyNo < m_bound.lowKeys  &&
2525           keyNo < m_bound.highKeys &&
2526           m_bound.low[keyNo] == m_bound.high[keyNo])
2527       {
2528         /* Inclusive if defined, or matching rows can include this value */
2529         bound_type= NdbIndexScanOperation::BoundEQ;
2530 
2531         appendedPattern |=
2532           appendBoundValue(serializedDef, bound_type, m_bound.low[keyNo], paramCnt);
2533 
2534       } else {
2535 
2536         /* If key is part of lower bound */
2537         if (keyNo < m_bound.lowKeys)
2538         {
2539           /* Inclusive if defined, or matching rows can include this value */
2540           bound_type= m_bound.lowIncl || keyNo+1 < m_bound.lowKeys ?
2541               NdbIndexScanOperation::BoundLE : NdbIndexScanOperation::BoundLT;
2542 
2543           appendedPattern |=
2544             appendBoundValue(serializedDef, bound_type, m_bound.low[keyNo], paramCnt);
2545         }
2546 
2547         /* If key is part of upper bound */
2548         if (keyNo < m_bound.highKeys)
2549         {
2550           /* Inclusive if defined, or matching rows can include this value */
2551           bound_type= m_bound.highIncl || keyNo+1 < m_bound.highKeys ?
2552               NdbIndexScanOperation::BoundGE : NdbIndexScanOperation::BoundGT;
2553 
2554           appendedPattern |=
2555             appendBoundValue(serializedDef, bound_type, m_bound.high[keyNo], paramCnt);
2556         }
2557       }
2558     } // for 'all bound values'
2559 
2560     // Set total length of bound pattern.
2561     Uint32 len = serializedDef.getSize() - startPos -1;
2562     serializedDef.put(startPos, (paramCnt << 16) | (len));
2563   }
2564 
2565   return appendedPattern;
2566 } // NdbQueryIndexScanOperationDefImpl::appendBoundPattern
2567 
2568 
2569 int
2570 NdbQueryPKLookupOperationDefImpl
serializeOperation(Uint32Buffer & serializedDef)2571 ::serializeOperation(Uint32Buffer& serializedDef)
2572 {
2573   assert (m_keys[0]!=NULL);
2574   // This method should only be invoked once.
2575   assert (!m_isPrepared);
2576   m_isPrepared = true;
2577 
2578   // Reserve memory for LookupNode, fill in contents later when
2579   // 'length' and 'requestInfo' has been calculated.
2580   Uint32 startPos = serializedDef.getSize();
2581   serializedDef.alloc(QN_LookupNode::NodeSize);
2582   Uint32 requestInfo = 0;
2583 
2584   /**
2585    * NOTE: Order of sections within the optional part is fixed as:
2586    *    Part1:  'NI_HAS_PARENT'
2587    *    Part2:  'NI_KEY_PARAMS, NI_KEY_LINKED, NI_KEY_CONST'
2588    *    PART3:  'NI_LINKED_ATTR ++
2589    */
2590 
2591   // Optional part1: Make list of parent nodes.
2592   requestInfo |= appendParentList (serializedDef);
2593 
2594   // Part2: Append m_keys[] values specifying lookup key.
2595   requestInfo |= appendKeyPattern(serializedDef);
2596 
2597   // Part3: Columns required by SPJ to instantiate further child operations.
2598   requestInfo |= appendChildProjection(serializedDef);
2599 
2600   // Fill in LookupNode contents (Already allocated, 'startPos' is our handle:
2601   QN_LookupNode* node = reinterpret_cast<QN_LookupNode*>(serializedDef.addr(startPos));
2602   if (unlikely(node==NULL)) {
2603     return Err_MemoryAlloc;
2604   }
2605   node->tableId = getTable().getObjectId();
2606   node->tableVersion = getTable().getObjectVersion();
2607   node->requestInfo = requestInfo;
2608   const Uint32 length = serializedDef.getSize() - startPos;
2609   if (unlikely(length > 0xFFFF)) {
2610     return QRY_DEFINITION_TOO_LARGE; //Query definition too large.
2611   } else {
2612     QueryNode::setOpLen(node->len, QueryNode::QN_LOOKUP, length);
2613   }
2614 
2615 #ifdef __TRACE_SERIALIZATION
2616   ndbout << "Serialized node " << getInternalOpNo() << " : ";
2617   for (Uint32 i = startPos; i < serializedDef.getSize(); i++) {
2618     char buf[12];
2619     sprintf(buf, "%.8x", serializedDef.get(i));
2620     ndbout << buf << " ";
2621   }
2622   ndbout << endl;
2623 #endif
2624 
2625   return 0;
2626 } // NdbQueryPKLookupOperationDefImpl::serializeOperation
2627 
2628 
2629 int
2630 NdbQueryIndexOperationDefImpl
serializeOperation(Uint32Buffer & serializedDef)2631 ::serializeOperation(Uint32Buffer& serializedDef)
2632 {
2633   assert (m_keys[0]!=NULL);
2634   // This method should only be invoked once.
2635   assert (!m_isPrepared);
2636   m_isPrepared = true;
2637 
2638   /**
2639    * Serialize unique index as a seperate lookupNode
2640    */
2641   {
2642     // Reserve memory for Index LookupNode, fill in contents later when
2643     // 'length' and 'requestInfo' has been calculated.
2644     Uint32 startPos = serializedDef.getSize();
2645     serializedDef.alloc(QN_LookupNode::NodeSize);
2646     Uint32 requestInfo = QN_LookupNode::L_UNIQUE_INDEX;
2647 
2648     // Optional part1: Make list of parent nodes.
2649     assert (getInternalOpNo() > 0);
2650     requestInfo |= appendParentList (serializedDef);
2651 
2652     // Part2: m_keys[] are the keys to be used for index
2653     requestInfo |= appendKeyPattern(serializedDef);
2654 
2655     /* Basetable is executed as child operation of index:
2656      * Add projection of (only) NDB$PK column which is hidden *after* last index column.
2657      */
2658     {
2659       requestInfo |= DABits::NI_LINKED_ATTR;
2660       Uint16Sequence spjProjSeq(serializedDef,1);
2661       spjProjSeq.append(getIndex()->getNoOfColumns());
2662       spjProjSeq.finish();
2663     }
2664 
2665     // Fill in LookupNode contents (Already allocated, 'startPos' is our handle:
2666     QN_LookupNode* node = reinterpret_cast<QN_LookupNode*>(serializedDef.addr(startPos));
2667     if (unlikely(node==NULL)) {
2668       return Err_MemoryAlloc;
2669     }
2670     node->tableId = getIndex()->getObjectId();
2671     node->tableVersion = getIndex()->getObjectVersion();
2672     node->requestInfo = requestInfo;
2673     const Uint32 length = serializedDef.getSize() - startPos;
2674     if (unlikely(length > 0xFFFF)) {
2675       return QRY_DEFINITION_TOO_LARGE; //Query definition too large.
2676     } else {
2677       QueryNode::setOpLen(node->len, QueryNode::QN_LOOKUP, length);
2678     }
2679 
2680 #ifdef __TRACE_SERIALIZATION
2681     ndbout << "Serialized index " << getInternalOpNo()-1 << " : ";
2682     for (Uint32 i = startPos; i < serializedDef.getSize(); i++){
2683       char buf[12];
2684       sprintf(buf, "%.8x", serializedDef.get(i));
2685       ndbout << buf << " ";
2686     }
2687     ndbout << endl;
2688 #endif
2689   } // End: Serialize unique index access
2690 
2691   // Reserve memory for LookupNode, fill in contents later when
2692   // 'length' and 'requestInfo' has been calculated.
2693   Uint32 startPos = serializedDef.getSize();
2694   serializedDef.alloc(QN_LookupNode::NodeSize);
2695   Uint32 requestInfo = 0;
2696 
2697   /**
2698    * NOTE: Order of sections within the optional part is fixed as:
2699    *    Part1:  'NI_HAS_PARENT'
2700    *    Part2:  'NI_KEY_PARAMS, NI_KEY_LINKED, NI_KEY_CONST'
2701    *    PART3:  'NI_LINKED_ATTR ++
2702    */
2703 
2704   // Optional part1: Append index as (single) parent op..
2705   { requestInfo |= DABits::NI_HAS_PARENT;
2706     Uint16Sequence parentSeq(serializedDef,1);
2707     parentSeq.append(getInternalOpNo()-1);
2708     parentSeq.finish();
2709   }
2710 
2711   // Part2: Append projected NDB$PK column as index -> table linkage
2712   {
2713     requestInfo |= DABits::NI_KEY_LINKED;
2714     serializedDef.append(1U); // Length: Key pattern contains only the single PK column
2715     serializedDef.append(QueryPattern::colPk(0));
2716   }
2717 
2718   // Part3: Columns required by SPJ to instantiate descendant child operations.
2719   requestInfo |= appendChildProjection(serializedDef);
2720 
2721   // Fill in LookupNode contents (Already allocated, 'startPos' is our handle:
2722   QN_LookupNode* node = reinterpret_cast<QN_LookupNode*>(serializedDef.addr(startPos));
2723   if (unlikely(node==NULL)) {
2724     return Err_MemoryAlloc;
2725   }
2726   node->tableId = getTable().getObjectId();
2727   node->tableVersion = getTable().getObjectVersion();
2728   node->requestInfo = requestInfo;
2729   const Uint32 length = serializedDef.getSize() - startPos;
2730   if (unlikely(length > 0xFFFF)) {
2731     return QRY_DEFINITION_TOO_LARGE; //Query definition too large.
2732   } else {
2733     QueryNode::setOpLen(node->len, QueryNode::QN_LOOKUP, length);
2734   }
2735 
2736 #ifdef __TRACE_SERIALIZATION
2737   ndbout << "Serialized node " << getInternalOpNo() << " : ";
2738   for (Uint32 i = startPos; i < serializedDef.getSize(); i++) {
2739     char buf[12];
2740     sprintf(buf, "%.8x", serializedDef.get(i));
2741     ndbout << buf << " ";
2742   }
2743   ndbout << endl;
2744 #endif
2745 
2746   return 0;
2747 } // NdbQueryIndexOperationDefImpl::serializeOperation
2748 
2749 
NdbQueryScanOperationDefImpl(const NdbTableImpl & table,const NdbQueryOptionsImpl & options,const char * ident,Uint32 opNo,Uint32 internalOpNo,int & error)2750 NdbQueryScanOperationDefImpl::NdbQueryScanOperationDefImpl (
2751                            const NdbTableImpl& table,
2752                            const NdbQueryOptionsImpl& options,
2753                            const char* ident,
2754                            Uint32      opNo,
2755                            Uint32      internalOpNo,
2756                            int& error)
2757   : NdbQueryOperationDefImpl(table, options, ident, opNo, internalOpNo, error)
2758 {}
2759 
2760 int
serialize(Uint32Buffer & serializedDef,const NdbTableImpl & tableOrIndex)2761 NdbQueryScanOperationDefImpl::serialize(Uint32Buffer& serializedDef,
2762                                         const NdbTableImpl& tableOrIndex)
2763 {
2764   bool isRoot = (getOpNo()==0);
2765 
2766   // This method should only be invoked once.
2767   assert (!m_isPrepared);
2768   m_isPrepared = true;
2769   // Reserve memory for ScanFragNode, fill in contents later when
2770   // 'length' and 'requestInfo' has been calculated.
2771   Uint32 startPos = serializedDef.getSize();
2772   assert (QN_ScanFragNode::NodeSize==QN_ScanIndexNode::NodeSize);
2773   serializedDef.alloc(QN_ScanFragNode::NodeSize);
2774   Uint32 requestInfo = 0;
2775 
2776   // Optional part1: Make list of parent nodes.
2777   requestInfo |= appendParentList (serializedDef);
2778 
2779   // Part2: Append pattern for building upper/lower bounds.
2780   requestInfo |= appendBoundPattern(serializedDef);
2781 
2782   // Part3: Columns required by SPJ to instantiate descendant child operations.
2783   requestInfo |= appendChildProjection(serializedDef);
2784 
2785   // Part4: Pattern to creating a prune key for range scan
2786   requestInfo |= appendPrunePattern(serializedDef);
2787 
2788   const Uint32 length = serializedDef.getSize() - startPos;
2789   if (unlikely(length > 0xFFFF))
2790   {
2791     return QRY_DEFINITION_TOO_LARGE; //Query definition too large.
2792   }
2793   // Fill in ScanFragNode/ScanIndexNode contents (Already allocated, 'startPos' is our handle:
2794   if (isRoot)
2795   {
2796     QN_ScanFragNode* node = reinterpret_cast<QN_ScanFragNode*>(serializedDef.addr(startPos));
2797     if (unlikely(node==NULL)) {
2798       return Err_MemoryAlloc;
2799     }
2800     node->tableId = tableOrIndex.getObjectId();
2801     node->tableVersion = tableOrIndex.getObjectVersion();
2802     node->requestInfo = requestInfo;
2803     QueryNode::setOpLen(node->len, QueryNode::QN_SCAN_FRAG, length);
2804   }
2805   else
2806   {
2807     QN_ScanIndexNode* node = reinterpret_cast<QN_ScanIndexNode*>(serializedDef.addr(startPos));
2808     if (unlikely(node==NULL)) {
2809       return Err_MemoryAlloc;
2810     }
2811     node->tableId = tableOrIndex.getObjectId();
2812     node->tableVersion = tableOrIndex.getObjectVersion();
2813     // Need NI_REPEAT_SCAN_RESULT if there are star-joined scans
2814     node->requestInfo = requestInfo | DABits::NI_REPEAT_SCAN_RESULT;
2815     QueryNode::setOpLen(node->len, QueryNode::QN_SCAN_INDEX, length);
2816   }
2817 
2818 #ifdef __TRACE_SERIALIZATION
2819   ndbout << "Serialized node " << getInternalOpNo() << " : ";
2820   for(Uint32 i = startPos; i < serializedDef.getSize(); i++){
2821     char buf[12];
2822     sprintf(buf, "%.8x", serializedDef.get(i));
2823     ndbout << buf << " ";
2824   }
2825   ndbout << endl;
2826 #endif
2827   return 0;
2828 } // NdbQueryScanOperationDefImpl::serialize
2829 
2830 
2831 int
2832 NdbQueryTableScanOperationDefImpl
serializeOperation(Uint32Buffer & serializedDef)2833 ::serializeOperation(Uint32Buffer& serializedDef)
2834 {
2835   return NdbQueryScanOperationDefImpl::serialize(serializedDef, getTable());
2836 } // NdbQueryTableScanOperationDefImpl::serializeOperation
2837 
2838 
2839 int
2840 NdbQueryIndexScanOperationDefImpl
serializeOperation(Uint32Buffer & serializedDef)2841 ::serializeOperation(Uint32Buffer& serializedDef)
2842 {
2843   return NdbQueryScanOperationDefImpl::serialize(serializedDef, *m_index.getIndexTable());
2844 } // NdbQueryIndexScanOperationDefImpl::serializeOperation
2845 
2846 
2847 // Instantiate Vector templates
2848 template class Vector<NdbQueryOperationDefImpl*>;
2849 template class Vector<NdbQueryOperandImpl*>;
2850 
2851 template class Vector<const NdbParamOperandImpl*>;
2852 template class Vector<const NdbColumnImpl*>;
2853 
2854 #if 0
2855 /**********************************************
2856  * Simple hack for module test & experimenting
2857  **********************************************/
2858 #include <stdio.h>
2859 #include <assert.h>
2860 
2861 int
2862 main(int argc, const char** argv)
2863 {
2864   printf("Hello, I am the unit test for NdbQueryBuilder\n");
2865 
2866   printf("sizeof(NdbQueryOperationDef): %d\n", sizeof(NdbQueryOperationDef));
2867   printf("sizeof(NdbQueryLookupOperationDef): %d\n", sizeof(NdbQueryLookupOperationDef));
2868 
2869   // Assert that interfaces *only* contain the pimpl pointer:
2870   assert (sizeof(NdbQueryOperationDef) == sizeof(NdbQueryOperationDefImpl*));
2871   assert (sizeof(NdbQueryLookupOperationDef) == sizeof(NdbQueryOperationDefImpl*));
2872   assert (sizeof(NdbQueryTableScanOperationDef) == sizeof(NdbQueryOperationDefImpl*));
2873   assert (sizeof(NdbQueryIndexScanOperationDef) == sizeof(NdbQueryOperationDefImpl*));
2874 
2875   assert (sizeof(NdbQueryOperand) == sizeof(NdbQueryOperandImpl*));
2876   assert (sizeof(NdbConstOperand) == sizeof(NdbQueryOperandImpl*));
2877   assert (sizeof(NdbParamOperand) == sizeof(NdbQueryOperandImpl*));
2878   assert (sizeof(NdbLinkedOperand) == sizeof(NdbQueryOperandImpl*));
2879 
2880   NdbQueryBuilder* const myBuilder= NdbQueryBuilder::create();
2881 
2882   const NdbDictionary::Table *manager = (NdbDictionary::Table*)0xDEADBEAF;
2883 //  const NdbDictionary::Index *ix = (NdbDictionary::Index*)0x11223344;
2884 
2885   const NdbQueryDef* q1 = 0;
2886   {
2887     NdbQueryBuilder* qb = myBuilder;
2888 
2889     const NdbQueryOperand* managerKey[] =  // Manager is indexed om {"dept_no", "emp_no"}
2890     {  qb->constValue("d005"),             // dept_no = "d005"
2891        qb->constValue(110567),             // emp_no  = 110567
2892        0
2893     };
2894 
2895     const NdbQueryLookupOperationDef *readManager = qb->readTuple(manager, managerKey);
2896 //  if (readManager == NULL) APIERROR(myNdb.getNdbError());
2897     assert (readManager);
2898 
2899     printf("readManager : %p\n", readManager);
2900     printf("Index : %p\n", readManager->getIndex());
2901     printf("Table : %p\n", readManager->getTable());
2902 
2903     q1 = qb->prepare();
2904 //  if (q1 == NULL) APIERROR(qb->getNdbError());
2905     assert (q1);
2906 
2907     // Some operations are intentionally disallowed through private declaration
2908 //  delete readManager;
2909 //  NdbQueryLookupOperationDef illegalAssign = *readManager;
2910 //  NdbQueryLookupOperationDef *illegalCopy1 = new NdbQueryLookupOperationDef(*readManager);
2911 //  NdbQueryLookupOperationDef illegalCopy2(*readManager);
2912   }
2913 }
2914 
2915 #endif
2916