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