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