1 /*
2    Copyright (c) 2003, 2020, 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 <ndb_math.h>
26 #include <NdbDictionary.hpp>
27 #include "NdbDictionaryImpl.hpp"
28 #include <NdbOut.hpp>
29 #include <signaldata/CreateHashMap.hpp>
30 #include <NdbBlob.hpp>
31 #include "decimal.h"
32 #include "m_ctype.h"
33 
34 /* NdbRecord static helper methods */
35 
36 NdbDictionary::RecordType
getRecordType(const NdbRecord * record)37 NdbDictionary::getRecordType(const NdbRecord* record)
38 {
39   return NdbDictionaryImpl::getRecordType(record);
40 }
41 
42 const char*
getRecordTableName(const NdbRecord * record)43 NdbDictionary::getRecordTableName(const NdbRecord* record)
44 {
45   return NdbDictionaryImpl::getRecordTableName(record);
46 }
47 
48 const char*
getRecordIndexName(const NdbRecord * record)49 NdbDictionary::getRecordIndexName(const NdbRecord* record)
50 {
51   return NdbDictionaryImpl::getRecordIndexName(record);
52 }
53 
54 bool
getFirstAttrId(const NdbRecord * record,Uint32 & firstAttrId)55 NdbDictionary::getFirstAttrId(const NdbRecord* record,
56                               Uint32& firstAttrId)
57 {
58   return NdbDictionaryImpl::getNextAttrIdFrom(record,
59                                               0,
60                                               firstAttrId);
61 }
62 
63 bool
getNextAttrId(const NdbRecord * record,Uint32 & attrId)64 NdbDictionary::getNextAttrId(const NdbRecord* record,
65                              Uint32& attrId)
66 {
67   return NdbDictionaryImpl::getNextAttrIdFrom(record,
68                                               attrId+1,
69                                               attrId);
70 }
71 
72 bool
getOffset(const NdbRecord * record,Uint32 attrId,Uint32 & offset)73 NdbDictionary::getOffset(const NdbRecord* record,
74                          Uint32 attrId,
75                          Uint32& offset)
76 {
77   return NdbDictionaryImpl::getOffset(record, attrId, offset);
78 }
79 
80 bool
getNullBitOffset(const NdbRecord * record,Uint32 attrId,Uint32 & nullbit_byte_offset,Uint32 & nullbit_bit_in_byte)81 NdbDictionary::getNullBitOffset(const NdbRecord* record,
82                                 Uint32 attrId,
83                                 Uint32& nullbit_byte_offset,
84                                 Uint32& nullbit_bit_in_byte)
85 {
86   return NdbDictionaryImpl::getNullBitOffset(record,
87                                              attrId,
88                                              nullbit_byte_offset,
89                                              nullbit_bit_in_byte);
90 }
91 
92 
93 const char*
getValuePtr(const NdbRecord * record,const char * row,Uint32 attrId)94 NdbDictionary::getValuePtr(const NdbRecord* record,
95             const char* row,
96             Uint32 attrId)
97 {
98   return NdbDictionaryImpl::getValuePtr(record, row, attrId);
99 }
100 
101 char*
getValuePtr(const NdbRecord * record,char * row,Uint32 attrId)102 NdbDictionary::getValuePtr(const NdbRecord* record,
103             char* row,
104             Uint32 attrId)
105 {
106   return NdbDictionaryImpl::getValuePtr(record, row, attrId);
107 }
108 
109 bool
isNull(const NdbRecord * record,const char * row,Uint32 attrId)110 NdbDictionary::isNull(const NdbRecord* record,
111        const char* row,
112        Uint32 attrId)
113 {
114   return NdbDictionaryImpl::isNull(record, row, attrId);
115 }
116 
117 int
setNull(const NdbRecord * record,char * row,Uint32 attrId,bool value)118 NdbDictionary::setNull(const NdbRecord* record,
119         char* row,
120         Uint32 attrId,
121         bool value)
122 {
123   return NdbDictionaryImpl::setNull(record, row, attrId, value);
124 }
125 
126 Uint32
getRecordRowLength(const NdbRecord * record)127 NdbDictionary::getRecordRowLength(const NdbRecord* record)
128 {
129   return NdbDictionaryImpl::getRecordRowLength(record);
130 }
131 
132 const unsigned char*
getEmptyBitmask()133 NdbDictionary::getEmptyBitmask()
134 {
135   return (const unsigned char*) NdbDictionaryImpl::m_emptyMask;
136 }
137 
138 /* --- */
139 
ObjectId()140 NdbDictionary::ObjectId::ObjectId()
141   : m_impl(* new NdbDictObjectImpl(NdbDictionary::Object::TypeUndefined))
142 {
143 }
144 
~ObjectId()145 NdbDictionary::ObjectId::~ObjectId()
146 {
147   NdbDictObjectImpl * tmp = &m_impl;
148   delete tmp;
149 }
150 
151 NdbDictionary::Object::Status
getObjectStatus() const152 NdbDictionary::ObjectId::getObjectStatus() const {
153   return m_impl.m_status;
154 }
155 
156 int
getObjectVersion() const157 NdbDictionary::ObjectId::getObjectVersion() const {
158   return m_impl.m_version;
159 }
160 
161 int
getObjectId() const162 NdbDictionary::ObjectId::getObjectId() const {
163   return m_impl.m_id;
164 }
165 
166 /*****************************************************************
167  * Column facade
168  */
Column(const char * name)169 NdbDictionary::Column::Column(const char * name)
170   : m_impl(* new NdbColumnImpl(* this))
171 {
172   setName(name);
173 }
174 
Column(const NdbDictionary::Column & org)175 NdbDictionary::Column::Column(const NdbDictionary::Column & org)
176   : m_impl(* new NdbColumnImpl(* this))
177 {
178   m_impl = org.m_impl;
179 }
180 
Column(NdbColumnImpl & impl)181 NdbDictionary::Column::Column(NdbColumnImpl& impl)
182   : m_impl(impl)
183 {
184 }
185 
~Column()186 NdbDictionary::Column::~Column(){
187   NdbColumnImpl * tmp = &m_impl;
188   if(this != tmp){
189     delete tmp;
190   }
191 }
192 
193 NdbDictionary::Column&
operator =(const NdbDictionary::Column & column)194 NdbDictionary::Column::operator=(const NdbDictionary::Column& column)
195 {
196   m_impl = column.m_impl;
197 
198   return *this;
199 }
200 
201 int
setName(const char * name)202 NdbDictionary::Column::setName(const char * name){
203   return !m_impl.m_name.assign(name);
204 }
205 
206 const char*
getName() const207 NdbDictionary::Column::getName() const {
208   return m_impl.m_name.c_str();
209 }
210 
211 void
setType(Type t)212 NdbDictionary::Column::setType(Type t){
213   m_impl.init(t);
214 }
215 
216 NdbDictionary::Column::Type
getType() const217 NdbDictionary::Column::getType() const {
218   return m_impl.m_type;
219 }
220 
221 void
setPrecision(int val)222 NdbDictionary::Column::setPrecision(int val){
223   m_impl.m_precision = val;
224 }
225 
226 int
getPrecision() const227 NdbDictionary::Column::getPrecision() const {
228   return m_impl.m_precision;
229 }
230 
231 void
setScale(int val)232 NdbDictionary::Column::setScale(int val){
233   m_impl.m_scale = val;
234 }
235 
236 int
getScale() const237 NdbDictionary::Column::getScale() const{
238   return m_impl.m_scale;
239 }
240 
241 void
setLength(int length)242 NdbDictionary::Column::setLength(int length){
243   m_impl.m_length = length;
244 }
245 
246 int
getLength() const247 NdbDictionary::Column::getLength() const{
248   return m_impl.m_length;
249 }
250 
251 void
setInlineSize(int size)252 NdbDictionary::Column::setInlineSize(int size)
253 {
254   m_impl.m_precision = size;
255 }
256 
257 void
setCharset(CHARSET_INFO * cs)258 NdbDictionary::Column::setCharset(CHARSET_INFO* cs)
259 {
260   m_impl.m_cs = cs;
261 }
262 
263 CHARSET_INFO*
getCharset() const264 NdbDictionary::Column::getCharset() const
265 {
266   return m_impl.m_cs;
267 }
268 
269 int
getCharsetNumber() const270 NdbDictionary::Column::getCharsetNumber() const
271 {
272   return m_impl.m_cs->number;
273 }
274 
275 int
getInlineSize() const276 NdbDictionary::Column::getInlineSize() const
277 {
278   return m_impl.m_precision;
279 }
280 
281 void
setPartSize(int size)282 NdbDictionary::Column::setPartSize(int size)
283 {
284   m_impl.m_scale = size;
285 }
286 
287 int
getPartSize() const288 NdbDictionary::Column::getPartSize() const
289 {
290   return m_impl.m_scale;
291 }
292 
293 void
setStripeSize(int size)294 NdbDictionary::Column::setStripeSize(int size)
295 {
296   m_impl.m_length = size;
297 }
298 
299 int
getStripeSize() const300 NdbDictionary::Column::getStripeSize() const
301 {
302   return m_impl.m_length;
303 }
304 
305 int
getSize() const306 NdbDictionary::Column::getSize() const{
307   return m_impl.m_attrSize;
308 }
309 
310 void
setNullable(bool val)311 NdbDictionary::Column::setNullable(bool val){
312   m_impl.m_nullable = val;
313 }
314 
315 bool
getNullable() const316 NdbDictionary::Column::getNullable() const {
317   return m_impl.m_nullable;
318 }
319 
320 void
setPrimaryKey(bool val)321 NdbDictionary::Column::setPrimaryKey(bool val){
322   m_impl.m_pk = val;
323 }
324 
325 bool
getPrimaryKey() const326 NdbDictionary::Column::getPrimaryKey() const {
327   return m_impl.m_pk;
328 }
329 
330 void
setPartitionKey(bool val)331 NdbDictionary::Column::setPartitionKey(bool val){
332   m_impl.m_distributionKey = val;
333 }
334 
335 bool
getPartitionKey() const336 NdbDictionary::Column::getPartitionKey() const{
337   return m_impl.m_distributionKey;
338 }
339 
340 const NdbDictionary::Table *
getBlobTable() const341 NdbDictionary::Column::getBlobTable() const {
342   NdbTableImpl * t = m_impl.m_blobTable;
343   if (t)
344     return t->m_facade;
345   return 0;
346 }
347 
348 void
setAutoIncrement(bool val)349 NdbDictionary::Column::setAutoIncrement(bool val){
350   m_impl.m_autoIncrement = val;
351 }
352 
353 bool
getAutoIncrement() const354 NdbDictionary::Column::getAutoIncrement() const {
355   return m_impl.m_autoIncrement;
356 }
357 
358 void
setAutoIncrementInitialValue(Uint64 val)359 NdbDictionary::Column::setAutoIncrementInitialValue(Uint64 val){
360   m_impl.m_autoIncrementInitialValue = val;
361 }
362 
363 int
getSizeInBytesForRecord() const364 NdbDictionary::Column::getSizeInBytesForRecord() const {
365   const bool isBlob= ((m_impl.m_type == Blob) || (m_impl.m_type == Text));
366   return isBlob ? sizeof(NdbBlob *) : getSizeInBytes();
367 }
368 
369 /*
370 * setDefaultValue() with only one const char * parameter is reserved
371 * for backward compatible api consideration, but is broken.
372 */
373 int
setDefaultValue(const char * defaultValue)374 NdbDictionary::Column::setDefaultValue(const char* defaultValue)
375 {
376   return -1;
377 }
378 
379 /*
380   The significant length of a column can't easily be calculated before
381   the column type is fully defined, so the length of the default value
382   is passed in as a parameter explicitly.
383 */
384 int
setDefaultValue(const void * defaultValue,unsigned int n)385 NdbDictionary::Column::setDefaultValue(const void* defaultValue, unsigned int n)
386 {
387   if (defaultValue == NULL)
388     return m_impl.m_defaultValue.assign(NULL, 0);
389 
390   return m_impl.m_defaultValue.assign(defaultValue, n);
391 }
392 
393 const void*
getDefaultValue(unsigned int * len) const394 NdbDictionary::Column::getDefaultValue(unsigned int* len) const
395 {
396   if (len)
397    *len = m_impl.m_defaultValue.length();
398 
399   return m_impl.m_defaultValue.get_data();
400 }
401 
402 int
getColumnNo() const403 NdbDictionary::Column::getColumnNo() const {
404   return m_impl.m_column_no;
405 }
406 
407 int
getAttrId() const408 NdbDictionary::Column::getAttrId() const {
409   return m_impl.m_attrId;
410 }
411 
412 bool
equal(const NdbDictionary::Column & col) const413 NdbDictionary::Column::equal(const NdbDictionary::Column & col) const {
414   return m_impl.equal(col.m_impl);
415 }
416 
417 int
getSizeInBytes() const418 NdbDictionary::Column::getSizeInBytes() const
419 {
420   return m_impl.m_attrSize * m_impl.m_arraySize;
421 }
422 
423 void
setArrayType(ArrayType type)424 NdbDictionary::Column::setArrayType(ArrayType type)
425 {
426   m_impl.m_arrayType = type;
427 }
428 
429 NdbDictionary::Column::ArrayType
getArrayType() const430 NdbDictionary::Column::getArrayType() const
431 {
432   return (ArrayType)m_impl.m_arrayType;
433 }
434 
435 void
setStorageType(StorageType type)436 NdbDictionary::Column::setStorageType(StorageType type)
437 {
438   m_impl.m_storageType = type;
439 }
440 
441 NdbDictionary::Column::StorageType
getStorageType() const442 NdbDictionary::Column::getStorageType() const
443 {
444   return (StorageType)m_impl.m_storageType;
445 }
446 
447 int
getBlobVersion() const448 NdbDictionary::Column::getBlobVersion() const
449 {
450   return m_impl.getBlobVersion();
451 }
452 
453 void
setBlobVersion(int blobVersion)454 NdbDictionary::Column::setBlobVersion(int blobVersion)
455 {
456   m_impl.setBlobVersion(blobVersion);
457 }
458 
459 void
setDynamic(bool val)460 NdbDictionary::Column::setDynamic(bool val){
461   m_impl.m_dynamic = val;
462 }
463 
464 bool
getDynamic() const465 NdbDictionary::Column::getDynamic() const {
466   return m_impl.m_dynamic;
467 }
468 
469 bool
getIndexSourced() const470 NdbDictionary::Column::getIndexSourced() const {
471   return m_impl.m_indexSourced;
472 }
473 
474 int
isBindable(const NdbDictionary::Column & col) const475 NdbDictionary::Column::isBindable(const NdbDictionary::Column & col) const
476 {
477   const NdbColumnImpl& parentColumn = col.m_impl;
478 
479   if (m_impl.m_type      != parentColumn.m_type ||
480       m_impl.m_precision != parentColumn.m_precision ||
481       m_impl.m_scale     != parentColumn.m_scale ||
482       m_impl.m_length    != parentColumn.m_length ||
483       m_impl.m_cs        != parentColumn.m_cs)
484     return -1;
485 
486   if (m_impl.m_type == NdbDictionary::Column::Blob ||
487       m_impl.m_type == NdbDictionary::Column::Text)
488     return -1;
489 
490   return 0; // ok
491 }
492 
493 /*****************************************************************
494  * Table facade
495  */
Table(const char * name)496 NdbDictionary::Table::Table(const char * name)
497   : m_impl(* new NdbTableImpl(* this))
498 {
499   setName(name);
500 }
501 
Table(const NdbDictionary::Table & org)502 NdbDictionary::Table::Table(const NdbDictionary::Table & org)
503   : Object(org), m_impl(* new NdbTableImpl(* this))
504 {
505   m_impl.assign(org.m_impl);
506 }
507 
Table(NdbTableImpl & impl)508 NdbDictionary::Table::Table(NdbTableImpl & impl)
509   : m_impl(impl)
510 {
511 }
512 
~Table()513 NdbDictionary::Table::~Table(){
514   NdbTableImpl * tmp = &m_impl;
515   if(this != tmp){
516     delete tmp;
517   }
518 }
519 
520 NdbDictionary::Table&
operator =(const NdbDictionary::Table & table)521 NdbDictionary::Table::operator=(const NdbDictionary::Table& table)
522 {
523   m_impl.assign(table.m_impl);
524 
525   m_impl.m_facade = this;
526   return *this;
527 }
528 
529 int
setName(const char * name)530 NdbDictionary::Table::setName(const char * name){
531   return m_impl.setName(name);
532 }
533 
534 const char *
getName() const535 NdbDictionary::Table::getName() const {
536   return m_impl.getName();
537 }
538 
539 const char *
getMysqlName() const540 NdbDictionary::Table::getMysqlName() const {
541   return m_impl.getMysqlName();
542 }
543 
544 int
getTableId() const545 NdbDictionary::Table::getTableId() const {
546   return m_impl.m_id;
547 }
548 
549 int
addColumn(const Column & c)550 NdbDictionary::Table::addColumn(const Column & c){
551   NdbColumnImpl* col = new NdbColumnImpl;
552   if (col ==  NULL)
553   {
554     errno = ENOMEM;
555     return -1;
556   }
557   (* col) = NdbColumnImpl::getImpl(c);
558   if (m_impl.m_columns.push_back(col))
559   {
560     return -1;
561   }
562   if (m_impl.buildColumnHash())
563   {
564     return -1;
565   }
566   col->m_column_no = m_impl.m_columns.size() - 1;
567   return 0;
568 }
569 
570 const NdbDictionary::Column*
getColumn(const char * name) const571 NdbDictionary::Table::getColumn(const char * name) const {
572   return m_impl.getColumn(name);
573 }
574 
575 const NdbDictionary::Column*
getColumn(const int attrId) const576 NdbDictionary::Table::getColumn(const int attrId) const {
577   return m_impl.getColumn(attrId);
578 }
579 
580 NdbDictionary::Column*
getColumn(const char * name)581 NdbDictionary::Table::getColumn(const char * name)
582 {
583   return m_impl.getColumn(name);
584 }
585 
586 NdbDictionary::Column*
getColumn(const int attrId)587 NdbDictionary::Table::getColumn(const int attrId)
588 {
589   return m_impl.getColumn(attrId);
590 }
591 
592 void
setLogging(bool val)593 NdbDictionary::Table::setLogging(bool val){
594   m_impl.m_logging = val;
595 }
596 
597 bool
getLogging() const598 NdbDictionary::Table::getLogging() const {
599   return m_impl.m_logging;
600 }
601 
602 void
setFragmentType(FragmentType ft)603 NdbDictionary::Table::setFragmentType(FragmentType ft){
604   m_impl.m_fragmentType = ft;
605 }
606 
607 NdbDictionary::Object::FragmentType
getFragmentType() const608 NdbDictionary::Table::getFragmentType() const {
609   return m_impl.m_fragmentType;
610 }
611 
612 void
setKValue(int kValue)613 NdbDictionary::Table::setKValue(int kValue){
614   m_impl.m_kvalue = kValue;
615 }
616 
617 int
getKValue() const618 NdbDictionary::Table::getKValue() const {
619   return m_impl.m_kvalue;
620 }
621 
622 void
setMinLoadFactor(int lf)623 NdbDictionary::Table::setMinLoadFactor(int lf){
624   m_impl.m_minLoadFactor = lf;
625 }
626 
627 int
getMinLoadFactor() const628 NdbDictionary::Table::getMinLoadFactor() const {
629   return m_impl.m_minLoadFactor;
630 }
631 
632 void
setMaxLoadFactor(int lf)633 NdbDictionary::Table::setMaxLoadFactor(int lf){
634   m_impl.m_maxLoadFactor = lf;
635 }
636 
637 int
getMaxLoadFactor() const638 NdbDictionary::Table::getMaxLoadFactor() const {
639   return m_impl.m_maxLoadFactor;
640 }
641 
642 int
getNoOfColumns() const643 NdbDictionary::Table::getNoOfColumns() const {
644   return m_impl.m_columns.size();
645 }
646 
647 int
getNoOfAutoIncrementColumns() const648 NdbDictionary::Table::getNoOfAutoIncrementColumns() const {
649   return m_impl.m_noOfAutoIncColumns;
650 }
651 
652 int
getNoOfPrimaryKeys() const653 NdbDictionary::Table::getNoOfPrimaryKeys() const {
654   return m_impl.m_noOfKeys;
655 }
656 
657 void
setMaxRows(Uint64 maxRows)658 NdbDictionary::Table::setMaxRows(Uint64 maxRows)
659 {
660   m_impl.m_max_rows = maxRows;
661 }
662 
663 Uint64
getMaxRows() const664 NdbDictionary::Table::getMaxRows() const
665 {
666   return m_impl.m_max_rows;
667 }
668 
669 void
setMinRows(Uint64 minRows)670 NdbDictionary::Table::setMinRows(Uint64 minRows)
671 {
672   m_impl.m_min_rows = minRows;
673 }
674 
675 Uint64
getMinRows() const676 NdbDictionary::Table::getMinRows() const
677 {
678   return m_impl.m_min_rows;
679 }
680 
681 void
setDefaultNoPartitionsFlag(Uint32 flag)682 NdbDictionary::Table::setDefaultNoPartitionsFlag(Uint32 flag)
683 {
684   m_impl.m_default_no_part_flag = flag;
685 }
686 
687 Uint32
getDefaultNoPartitionsFlag() const688 NdbDictionary::Table::getDefaultNoPartitionsFlag() const
689 {
690   return m_impl.m_default_no_part_flag;
691 }
692 
693 const char*
getPrimaryKey(int no) const694 NdbDictionary::Table::getPrimaryKey(int no) const {
695   int count = 0;
696   for (unsigned i = 0; i < m_impl.m_columns.size(); i++) {
697     if (m_impl.m_columns[i]->m_pk) {
698       if (count++ == no)
699         return m_impl.m_columns[i]->m_name.c_str();
700     }
701   }
702   return 0;
703 }
704 
705 const void*
getFrmData() const706 NdbDictionary::Table::getFrmData() const {
707   return m_impl.getFrmData();
708 }
709 
710 Uint32
getFrmLength() const711 NdbDictionary::Table::getFrmLength() const {
712   return m_impl.getFrmLength();
713 }
714 
715 enum NdbDictionary::Table::SingleUserMode
getSingleUserMode() const716 NdbDictionary::Table::getSingleUserMode() const
717 {
718   return (enum SingleUserMode)m_impl.m_single_user_mode;
719 }
720 
721 void
setSingleUserMode(enum NdbDictionary::Table::SingleUserMode mode)722 NdbDictionary::Table::setSingleUserMode(enum NdbDictionary::Table::SingleUserMode mode)
723 {
724   m_impl.m_single_user_mode = (Uint8)mode;
725 }
726 
727 void
setLinearFlag(Uint32 flag)728 NdbDictionary::Table::setLinearFlag(Uint32 flag)
729 {
730   m_impl.m_linear_flag = flag;
731 }
732 
733 bool
getLinearFlag() const734 NdbDictionary::Table::getLinearFlag() const
735 {
736   return m_impl.m_linear_flag;
737 }
738 
739 void
setFragmentCount(Uint32 count)740 NdbDictionary::Table::setFragmentCount(Uint32 count)
741 {
742   m_impl.setFragmentCount(count);
743 }
744 
745 Uint32
getFragmentCount() const746 NdbDictionary::Table::getFragmentCount() const
747 {
748   return m_impl.getFragmentCount();
749 }
750 
751 Uint32
getPartitionCount() const752 NdbDictionary::Table::getPartitionCount() const
753 {
754   return m_impl.getPartitionCount();
755 }
756 
757 void
setPartitionBalance(NdbDictionary::Object::PartitionBalance arg)758 NdbDictionary::Table::setPartitionBalance(NdbDictionary::Object::PartitionBalance arg)
759 {
760   m_impl.m_partitionBalance = arg;
761 }
762 
763 NdbDictionary::Object::PartitionBalance
getPartitionBalance() const764 NdbDictionary::Table::getPartitionBalance() const
765 {
766   return m_impl.m_partitionBalance;
767 }
768 
769 const char*
getPartitionBalanceString() const770 NdbDictionary::Table::getPartitionBalanceString() const
771 {
772   const char* name = getPartitionBalanceString(m_impl.m_partitionBalance);
773   if (name == NULL)
774     return "unknown";
775   return name;
776 }
777 
778 static
779 struct {
780   NdbDictionary::Object::PartitionBalance value;
781   const char * name;
782 } partitionBalanceNames[] = {
783   {NdbDictionary::Object::PartitionBalance_Specific,         "SPECIFIC"},
784   {NdbDictionary::Object::PartitionBalance_ForRPByLDM,       "FOR_RP_BY_LDM"},
785   {NdbDictionary::Object::PartitionBalance_ForRPByNode,      "FOR_RP_BY_NODE"},
786   {NdbDictionary::Object::PartitionBalance_ForRAByLDM,       "FOR_RA_BY_LDM"},
787   {NdbDictionary::Object::PartitionBalance_ForRAByNode,      "FOR_RA_BY_NODE"},
788   {NdbDictionary::Object::PartitionBalance_ForRAByLDMx2,     "FOR_RA_BY_LDM_X_2"},
789   {NdbDictionary::Object::PartitionBalance_ForRAByLDMx3,     "FOR_RA_BY_LDM_X_3"},
790   {NdbDictionary::Object::PartitionBalance_ForRAByLDMx4,     "FOR_RA_BY_LDM_X_4"},
791 };
792 
793 NdbDictionary::Object::PartitionBalance
getPartitionBalance(const char str[])794 NdbDictionary::Table::getPartitionBalance(const char str[])
795 {
796   for (unsigned i = 0; i < NDB_ARRAY_SIZE(partitionBalanceNames) ; i++)
797   {
798     if (strcmp(partitionBalanceNames[i].name, str) == 0)
799     {
800       return partitionBalanceNames[i].value;
801     }
802   }
803   return NdbDictionary::Object::PartitionBalance(0); /* No matching partition balance */
804 }
805 
806 const char*
getPartitionBalanceString(PartitionBalance partition_balance)807 NdbDictionary::Table::getPartitionBalanceString(PartitionBalance partition_balance)
808 {
809   for (unsigned i = 0; i < NDB_ARRAY_SIZE(partitionBalanceNames) ; i++)
810   {
811     if (partitionBalanceNames[i].value == partition_balance)
812     {
813       return partitionBalanceNames[i].name;
814     }
815   }
816   return NULL;
817 }
818 
819 int
setFrm(const void * data,Uint32 len)820 NdbDictionary::Table::setFrm(const void* data, Uint32 len){
821   return m_impl.setFrm(data, len);
822 }
823 
824 int
setExtraMetadata(Uint32 version,const void * data,Uint32 data_length)825 NdbDictionary::Table::setExtraMetadata(Uint32 version,
826                                        const void* data, Uint32 data_length)
827 {
828   return m_impl.setExtraMetadata(version, data, data_length);
829 }
830 
831 int
getExtraMetadata(Uint32 & version,void ** data,Uint32 * data_length) const832 NdbDictionary::Table::getExtraMetadata(Uint32& version,
833                                        void** data, Uint32* data_length) const
834 {
835   return m_impl.getExtraMetadata(version, data, data_length);
836 }
837 
838 const Uint32*
getFragmentData() const839 NdbDictionary::Table::getFragmentData() const {
840   return m_impl.getFragmentData();
841 }
842 
843 Uint32
getFragmentDataLen() const844 NdbDictionary::Table::getFragmentDataLen() const {
845   return m_impl.getFragmentDataLen();
846 }
847 
848 int
setFragmentData(const Uint32 * data,Uint32 cnt)849 NdbDictionary::Table::setFragmentData(const Uint32* data, Uint32 cnt)
850 {
851   return m_impl.setFragmentData(data, cnt);
852 }
853 
854 const Int32*
getRangeListData() const855 NdbDictionary::Table::getRangeListData() const {
856   return m_impl.getRangeListData();
857 }
858 
859 Uint32
getRangeListDataLen() const860 NdbDictionary::Table::getRangeListDataLen() const {
861   return m_impl.getRangeListDataLen();
862 }
863 
864 int
setRangeListData(const Int32 * data,Uint32 len)865 NdbDictionary::Table::setRangeListData(const Int32* data, Uint32 len)
866 {
867   return m_impl.setRangeListData(data, len);
868 }
869 
870 Uint32
getFragmentNodes(Uint32 fragmentId,Uint32 * nodeIdArrayPtr,Uint32 arraySize) const871 NdbDictionary::Table::getFragmentNodes(Uint32 fragmentId,
872                                        Uint32* nodeIdArrayPtr,
873                                        Uint32 arraySize) const
874 {
875   return m_impl.getFragmentNodes(fragmentId, nodeIdArrayPtr, arraySize);
876 }
877 
878 NdbDictionary::Object::Status
getObjectStatus() const879 NdbDictionary::Table::getObjectStatus() const {
880   return m_impl.m_status;
881 }
882 
883 void
setStatusInvalid() const884 NdbDictionary::Table::setStatusInvalid() const {
885   m_impl.m_status = NdbDictionary::Object::Invalid;
886 }
887 
888 int
getObjectVersion() const889 NdbDictionary::Table::getObjectVersion() const {
890   return m_impl.m_version;
891 }
892 
893 int
getObjectId() const894 NdbDictionary::Table::getObjectId() const {
895   return m_impl.m_id;
896 }
897 
898 bool
equal(const NdbDictionary::Table & col) const899 NdbDictionary::Table::equal(const NdbDictionary::Table & col) const {
900   return m_impl.equal(col.m_impl);
901 }
902 
903 int
getRowSizeInBytes() const904 NdbDictionary::Table::getRowSizeInBytes() const {
905   int sz = 0;
906   for(int i = 0; i<getNoOfColumns(); i++){
907     const NdbDictionary::Column * c = getColumn(i);
908     sz += (c->getSizeInBytes()+ 3) / 4;
909   }
910   return sz * 4;
911 }
912 
913 int
getReplicaCount() const914 NdbDictionary::Table::getReplicaCount() const {
915   return m_impl.m_replicaCount;
916 }
917 
918 bool
getTemporary() const919 NdbDictionary::Table::getTemporary() const {
920   return m_impl.m_temporary;
921 }
922 
923 void
setTemporary(bool val)924 NdbDictionary::Table::setTemporary(bool val) {
925   m_impl.m_temporary = val;
926 }
927 
928 int
createTableInDb(Ndb * pNdb,bool equalOk) const929 NdbDictionary::Table::createTableInDb(Ndb* pNdb, bool equalOk) const {
930   const NdbDictionary::Table * pTab =
931     pNdb->getDictionary()->getTable(getName());
932   if(pTab != 0 && equal(* pTab))
933     return 0;
934   if(pTab != 0 && !equal(* pTab))
935     return -1;
936   return pNdb->getDictionary()->createTable(* this);
937 }
938 
939 bool
getTablespace(Uint32 * id,Uint32 * version) const940 NdbDictionary::Table::getTablespace(Uint32 *id, Uint32 *version) const
941 {
942   if (m_impl.m_tablespace_id == RNIL)
943     return false;
944   if (id)
945     *id= m_impl.m_tablespace_id;
946   if (version)
947     *version= m_impl.m_version;
948   return true;
949 }
950 
951 const char *
getTablespaceName() const952 NdbDictionary::Table::getTablespaceName() const
953 {
954   return m_impl.m_tablespace_name.c_str();
955 }
956 
957 int
setTablespaceName(const char * name)958 NdbDictionary::Table::setTablespaceName(const char * name){
959   m_impl.m_tablespace_id = ~0;
960   m_impl.m_tablespace_version = ~0;
961   return !m_impl.m_tablespace_name.assign(name);
962 }
963 
964 int
setTablespace(const NdbDictionary::Tablespace & ts)965 NdbDictionary::Table::setTablespace(const NdbDictionary::Tablespace & ts){
966   m_impl.m_tablespace_id = NdbTablespaceImpl::getImpl(ts).m_id;
967   m_impl.m_tablespace_version = ts.getObjectVersion();
968   return !m_impl.m_tablespace_name.assign(ts.getName());
969 }
970 
971 bool
getHashMap(Uint32 * id,Uint32 * version) const972 NdbDictionary::Table::getHashMap(Uint32 *id, Uint32 *version) const
973 {
974   if (m_impl.m_hash_map_id == RNIL)
975     return false;
976   if (id)
977     *id= m_impl.m_hash_map_id;
978   if (version)
979     *version= m_impl.m_hash_map_version;
980   return true;
981 }
982 
983 int
setHashMap(const NdbDictionary::HashMap & hm)984 NdbDictionary::Table::setHashMap(const NdbDictionary::HashMap& hm)
985 {
986   m_impl.m_hash_map_id = hm.getObjectId();
987   m_impl.m_hash_map_version = hm.getObjectVersion();
988   return 0;
989 }
990 
991 void
setRowChecksumIndicator(bool val)992 NdbDictionary::Table::setRowChecksumIndicator(bool val){
993   m_impl.m_row_checksum = val;
994 }
995 
996 bool
getRowChecksumIndicator() const997 NdbDictionary::Table::getRowChecksumIndicator() const {
998   return m_impl.m_row_checksum;
999 }
1000 
1001 void
setRowGCIIndicator(bool val)1002 NdbDictionary::Table::setRowGCIIndicator(bool val){
1003   m_impl.m_row_gci = val;
1004 }
1005 
1006 bool
getRowGCIIndicator() const1007 NdbDictionary::Table::getRowGCIIndicator() const {
1008   return m_impl.m_row_gci;
1009 }
1010 
1011 void
setExtraRowGciBits(Uint32 val)1012 NdbDictionary::Table::setExtraRowGciBits(Uint32 val)
1013 {
1014   if (val <= 31)
1015   {
1016     m_impl.m_extra_row_gci_bits = val;
1017   }
1018 }
1019 
1020 Uint32
getExtraRowGciBits() const1021 NdbDictionary::Table::getExtraRowGciBits() const
1022 {
1023   return m_impl.m_extra_row_gci_bits;
1024 }
1025 
1026 void
setExtraRowAuthorBits(Uint32 val)1027 NdbDictionary::Table::setExtraRowAuthorBits(Uint32 val)
1028 {
1029   if (val <= 31)
1030   {
1031     m_impl.m_extra_row_author_bits = val;
1032   }
1033 }
1034 
1035 Uint32
getExtraRowAuthorBits() const1036 NdbDictionary::Table::getExtraRowAuthorBits() const
1037 {
1038   return m_impl.m_extra_row_author_bits;
1039 }
1040 
1041 void
setReadBackupFlag(bool val)1042 NdbDictionary::Table::setReadBackupFlag(bool val){
1043   m_impl.m_read_backup = val;
1044 }
1045 
1046 bool
getReadBackupFlag() const1047 NdbDictionary::Table::getReadBackupFlag() const {
1048   return m_impl.m_read_backup;
1049 }
1050 
1051 void
setForceVarPart(bool val)1052 NdbDictionary::Table::setForceVarPart(bool val){
1053   m_impl.m_force_var_part = val;
1054 }
1055 
1056 bool
getForceVarPart() const1057 NdbDictionary::Table::getForceVarPart() const {
1058   return m_impl.m_force_var_part;
1059 }
1060 
1061 bool
hasDefaultValues() const1062 NdbDictionary::Table::hasDefaultValues() const {
1063   return m_impl.m_has_default_values;
1064 }
1065 
1066 const NdbRecord*
getDefaultRecord() const1067 NdbDictionary::Table::getDefaultRecord() const {
1068   return m_impl.m_ndbrecord;
1069 }
1070 
1071 int
aggregate(NdbError & error)1072 NdbDictionary::Table::aggregate(NdbError& error)
1073 {
1074   return m_impl.aggregate(error);
1075 }
1076 
1077 int
validate(NdbError & error)1078 NdbDictionary::Table::validate(NdbError& error)
1079 {
1080   return m_impl.validate(error);
1081 }
1082 
1083 Uint32
getPartitionId(Uint32 hashValue) const1084 NdbDictionary::Table::getPartitionId(Uint32 hashValue) const
1085 {
1086   switch (m_impl.m_fragmentType){
1087   case NdbDictionary::Object::FragAllSmall:
1088   case NdbDictionary::Object::FragAllMedium:
1089   case NdbDictionary::Object::FragAllLarge:
1090   case NdbDictionary::Object::FragSingle:
1091   case NdbDictionary::Object::DistrKeyLin:
1092   {
1093     Uint32 fragmentId = hashValue & m_impl.m_hashValueMask;
1094     if(fragmentId < m_impl.m_hashpointerValue)
1095       fragmentId = hashValue & ((m_impl.m_hashValueMask << 1) + 1);
1096     return fragmentId;
1097   }
1098   case NdbDictionary::Object::DistrKeyHash:
1099   {
1100     Uint32 cnt = m_impl.m_fragmentCount;
1101     return hashValue % (cnt ? cnt : 1);
1102   }
1103   case NdbDictionary::Object::HashMapPartition:
1104   {
1105     Uint32 cnt = m_impl.m_hash_map.size();
1106     return m_impl.m_hash_map[hashValue % cnt];
1107   }
1108   default:
1109     return 0;
1110   }
1111 }
1112 
1113 void
assignObjId(const NdbDictionary::ObjectId & _objId)1114 NdbDictionary::Table::assignObjId(const NdbDictionary::ObjectId& _objId)
1115 {
1116   const NdbDictObjectImpl& objId = NdbDictObjectImpl::getImpl(_objId);
1117   m_impl.m_id = objId.m_id;
1118   m_impl.m_version = objId.m_version;
1119 }
1120 
1121 void
setStorageType(NdbDictionary::Column::StorageType type)1122 NdbDictionary::Table::setStorageType(NdbDictionary::Column::StorageType type)
1123 {
1124   m_impl.m_storageType = type;
1125 }
1126 
1127 NdbDictionary::Column::StorageType
getStorageType() const1128 NdbDictionary::Table::getStorageType() const
1129 {
1130   return (NdbDictionary::Column::StorageType)m_impl.m_storageType;
1131 }
1132 
1133 void
setFullyReplicated(bool val)1134 NdbDictionary::Table::setFullyReplicated(bool val)
1135 {
1136   m_impl.m_fully_replicated = val;
1137 }
1138 
1139 bool
getFullyReplicated() const1140 NdbDictionary::Table::getFullyReplicated() const
1141 {
1142   return m_impl.m_fully_replicated;
1143 }
1144 
1145 void
setRowChecksum(Uint32 val)1146 NdbDictionary::Table::setRowChecksum(Uint32 val)
1147 {
1148   m_impl.m_row_checksum = val;
1149 }
1150 
1151 Uint32
getRowChecksum()1152 NdbDictionary::Table::getRowChecksum()
1153 {
1154   return m_impl.m_row_checksum;
1155 }
1156 
1157 /*****************************************************************
1158  * Index facade
1159  */
1160 
Index(const char * name)1161 NdbDictionary::Index::Index(const char * name)
1162   : m_impl(* new NdbIndexImpl(* this))
1163 {
1164   setName(name);
1165 }
1166 
Index(NdbIndexImpl & impl)1167 NdbDictionary::Index::Index(NdbIndexImpl & impl)
1168   : m_impl(impl)
1169 {
1170 }
1171 
~Index()1172 NdbDictionary::Index::~Index(){
1173   NdbIndexImpl * tmp = &m_impl;
1174   if(this != tmp){
1175     delete tmp;
1176   }
1177 }
1178 
1179 int
setName(const char * name)1180 NdbDictionary::Index::setName(const char * name){
1181   return m_impl.setName(name);
1182 }
1183 
1184 const char *
getName() const1185 NdbDictionary::Index::getName() const {
1186   return m_impl.getName();
1187 }
1188 
1189 int
setTable(const char * table)1190 NdbDictionary::Index::setTable(const char * table){
1191   return m_impl.setTable(table);
1192 }
1193 
1194 const char *
getTable() const1195 NdbDictionary::Index::getTable() const {
1196   return m_impl.getTable();
1197 }
1198 
1199 unsigned
getNoOfColumns() const1200 NdbDictionary::Index::getNoOfColumns() const {
1201   return m_impl.m_columns.size();
1202 }
1203 
1204 int
getNoOfIndexColumns() const1205 NdbDictionary::Index::getNoOfIndexColumns() const {
1206   return m_impl.m_columns.size();
1207 }
1208 
1209 const NdbDictionary::Column *
getColumn(unsigned no) const1210 NdbDictionary::Index::getColumn(unsigned no) const {
1211   if(no < m_impl.m_columns.size())
1212     return m_impl.m_columns[no];
1213   return NULL;
1214 }
1215 
1216 const char *
getIndexColumn(int no) const1217 NdbDictionary::Index::getIndexColumn(int no) const {
1218   const NdbDictionary::Column* col = getColumn(no);
1219 
1220   if (col)
1221     return col->getName();
1222   else
1223     return NULL;
1224 }
1225 
1226 const NdbRecord*
getDefaultRecord() const1227 NdbDictionary::Index::getDefaultRecord() const {
1228   return m_impl.m_table->m_ndbrecord;
1229 }
1230 
1231 int
addColumn(const Column & c)1232 NdbDictionary::Index::addColumn(const Column & c){
1233   NdbColumnImpl* col = new NdbColumnImpl;
1234   if (col == NULL)
1235   {
1236     errno = ENOMEM;
1237     return -1;
1238   }
1239   (* col) = NdbColumnImpl::getImpl(c);
1240 
1241   col->m_indexSourced=true;
1242 
1243   /* Remove defaults from indexed columns */
1244   col->m_defaultValue.clear();
1245 
1246   if (m_impl.m_columns.push_back(col))
1247   {
1248     return -1;
1249   }
1250   return 0;
1251 }
1252 
1253 int
addColumnName(const char * name)1254 NdbDictionary::Index::addColumnName(const char * name){
1255   const Column c(name);
1256   return addColumn(c);
1257 }
1258 
1259 int
addIndexColumn(const char * name)1260 NdbDictionary::Index::addIndexColumn(const char * name){
1261   const Column c(name);
1262   return addColumn(c);
1263 }
1264 
1265 int
addColumnNames(unsigned noOfNames,const char ** names)1266 NdbDictionary::Index::addColumnNames(unsigned noOfNames, const char ** names){
1267   for(unsigned i = 0; i < noOfNames; i++) {
1268     const Column c(names[i]);
1269     if (addColumn(c))
1270     {
1271       return -1;
1272     }
1273   }
1274   return 0;
1275 }
1276 
1277 int
addIndexColumns(int noOfNames,const char ** names)1278 NdbDictionary::Index::addIndexColumns(int noOfNames, const char ** names){
1279   for(int i = 0; i < noOfNames; i++) {
1280     const Column c(names[i]);
1281     if (addColumn(c))
1282     {
1283       return -1;
1284     }
1285   }
1286   return 0;
1287 }
1288 
1289 void
setType(NdbDictionary::Index::Type t)1290 NdbDictionary::Index::setType(NdbDictionary::Index::Type t){
1291   m_impl.m_type = (NdbDictionary::Object::Type)t;
1292 }
1293 
1294 NdbDictionary::Index::Type
getType() const1295 NdbDictionary::Index::getType() const {
1296   return (NdbDictionary::Index::Type)m_impl.m_type;
1297 }
1298 
1299 void
setLogging(bool val)1300 NdbDictionary::Index::setLogging(bool val){
1301   m_impl.m_logging = val;
1302 }
1303 
1304 bool
getTemporary() const1305 NdbDictionary::Index::getTemporary() const {
1306   return m_impl.m_temporary;
1307 }
1308 
1309 void
setTemporary(bool val)1310 NdbDictionary::Index::setTemporary(bool val){
1311   m_impl.m_temporary = val;
1312 }
1313 
1314 bool
getLogging() const1315 NdbDictionary::Index::getLogging() const {
1316   return m_impl.m_logging;
1317 }
1318 
1319 NdbDictionary::Object::Status
getObjectStatus() const1320 NdbDictionary::Index::getObjectStatus() const {
1321   return m_impl.m_table->m_status;
1322 }
1323 
1324 int
getObjectVersion() const1325 NdbDictionary::Index::getObjectVersion() const {
1326   return m_impl.m_table->m_version;
1327 }
1328 
1329 int
getObjectId() const1330 NdbDictionary::Index::getObjectId() const {
1331   return m_impl.m_table->m_id;
1332 }
1333 
1334 /*****************************************************************
1335  * OptimizeTableHandle facade
1336  */
OptimizeTableHandle()1337 NdbDictionary::OptimizeTableHandle::OptimizeTableHandle()
1338   : m_impl(* new NdbOptimizeTableHandleImpl(* this))
1339 {}
1340 
OptimizeTableHandle(NdbOptimizeTableHandleImpl & impl)1341 NdbDictionary::OptimizeTableHandle::OptimizeTableHandle(NdbOptimizeTableHandleImpl & impl)
1342   : m_impl(impl)
1343 {}
1344 
~OptimizeTableHandle()1345 NdbDictionary::OptimizeTableHandle::~OptimizeTableHandle()
1346 {
1347   NdbOptimizeTableHandleImpl * tmp = &m_impl;
1348   if(this != tmp){
1349     delete tmp;
1350   }
1351 }
1352 
1353 int
next()1354 NdbDictionary::OptimizeTableHandle::next()
1355 {
1356   return m_impl.next();
1357 }
1358 
1359 int
close()1360 NdbDictionary::OptimizeTableHandle::close()
1361 {
1362   int result = m_impl.close();
1363   return result;
1364 }
1365 
1366 /*****************************************************************
1367  * OptimizeIndexHandle facade
1368  */
OptimizeIndexHandle()1369 NdbDictionary::OptimizeIndexHandle::OptimizeIndexHandle()
1370   : m_impl(* new NdbOptimizeIndexHandleImpl(* this))
1371 {}
1372 
OptimizeIndexHandle(NdbOptimizeIndexHandleImpl & impl)1373 NdbDictionary::OptimizeIndexHandle::OptimizeIndexHandle(NdbOptimizeIndexHandleImpl & impl)
1374   : m_impl(impl)
1375 {}
1376 
~OptimizeIndexHandle()1377 NdbDictionary::OptimizeIndexHandle::~OptimizeIndexHandle()
1378 {
1379   NdbOptimizeIndexHandleImpl * tmp = &m_impl;
1380   if(this != tmp){
1381     delete tmp;
1382   }
1383 }
1384 
1385 int
next()1386 NdbDictionary::OptimizeIndexHandle::next()
1387 {
1388   return m_impl.next();
1389 }
1390 
1391 int
close()1392 NdbDictionary::OptimizeIndexHandle::close()
1393 {
1394   int result = m_impl.close();
1395   return result;
1396 }
1397 
1398 /*****************************************************************
1399  * Event facade
1400  */
Event(const char * name)1401 NdbDictionary::Event::Event(const char * name)
1402   : m_impl(* new NdbEventImpl(* this))
1403 {
1404   setName(name);
1405 }
1406 
Event(const char * name,const Table & table)1407 NdbDictionary::Event::Event(const char * name, const Table& table)
1408   : m_impl(* new NdbEventImpl(* this))
1409 {
1410   setName(name);
1411   setTable(table);
1412 }
1413 
Event(NdbEventImpl & impl)1414 NdbDictionary::Event::Event(NdbEventImpl & impl)
1415   : m_impl(impl)
1416 {
1417 }
1418 
~Event()1419 NdbDictionary::Event::~Event()
1420 {
1421   NdbEventImpl * tmp = &m_impl;
1422   if(this != tmp){
1423     delete tmp;
1424   }
1425 }
1426 
1427 int
setName(const char * name)1428 NdbDictionary::Event::setName(const char * name)
1429 {
1430   return m_impl.setName(name);
1431 }
1432 
1433 const char *
getName() const1434 NdbDictionary::Event::getName() const
1435 {
1436   return m_impl.getName();
1437 }
1438 
1439 void
setTable(const Table & table)1440 NdbDictionary::Event::setTable(const Table& table)
1441 {
1442   m_impl.setTable(table);
1443 }
1444 
1445 int
setTable(const Table * table)1446 NdbDictionary::Event::setTable(const Table *table)
1447 {
1448   return m_impl.setTable(table);
1449 }
1450 
1451 const NdbDictionary::Table *
getTable() const1452 NdbDictionary::Event::getTable() const
1453 {
1454   return m_impl.getTable();
1455 }
1456 
1457 int
setTable(const char * table)1458 NdbDictionary::Event::setTable(const char * table)
1459 {
1460   return m_impl.setTable(table);
1461 }
1462 
1463 const char*
getTableName() const1464 NdbDictionary::Event::getTableName() const
1465 {
1466   return m_impl.getTableName();
1467 }
1468 
1469 void
addTableEvent(const TableEvent t)1470 NdbDictionary::Event::addTableEvent(const TableEvent t)
1471 {
1472   m_impl.addTableEvent(t);
1473 }
1474 
1475 bool
getTableEvent(const TableEvent t) const1476 NdbDictionary::Event::getTableEvent(const TableEvent t) const
1477 {
1478   return m_impl.getTableEvent(t);
1479 }
1480 
1481 void
setDurability(EventDurability d)1482 NdbDictionary::Event::setDurability(EventDurability d)
1483 {
1484   m_impl.setDurability(d);
1485 }
1486 
1487 NdbDictionary::Event::EventDurability
getDurability() const1488 NdbDictionary::Event::getDurability() const
1489 {
1490   return m_impl.getDurability();
1491 }
1492 
1493 void
setReport(EventReport r)1494 NdbDictionary::Event::setReport(EventReport r)
1495 {
1496   m_impl.setReport(r);
1497 }
1498 
1499 NdbDictionary::Event::EventReport
getReport() const1500 NdbDictionary::Event::getReport() const
1501 {
1502   return m_impl.getReport();
1503 }
1504 
1505 void
addColumn(const Column & c)1506 NdbDictionary::Event::addColumn(const Column & c){
1507   NdbColumnImpl* col = new NdbColumnImpl;
1508   (* col) = NdbColumnImpl::getImpl(c);
1509   m_impl.m_columns.push_back(col);
1510 }
1511 
1512 void
addEventColumn(unsigned attrId)1513 NdbDictionary::Event::addEventColumn(unsigned attrId)
1514 {
1515   m_impl.m_attrIds.push_back(attrId);
1516 }
1517 
1518 void
addEventColumn(const char * name)1519 NdbDictionary::Event::addEventColumn(const char * name)
1520 {
1521   const Column c(name);
1522   addColumn(c);
1523 }
1524 
1525 void
addEventColumns(int n,const char ** names)1526 NdbDictionary::Event::addEventColumns(int n, const char ** names)
1527 {
1528   for (int i = 0; i < n; i++)
1529     addEventColumn(names[i]);
1530 }
1531 
getNoOfEventColumns() const1532 int NdbDictionary::Event::getNoOfEventColumns() const
1533 {
1534   return m_impl.getNoOfEventColumns();
1535 }
1536 
1537 const NdbDictionary::Column *
getEventColumn(unsigned no) const1538 NdbDictionary::Event::getEventColumn(unsigned no) const
1539 {
1540   return m_impl.getEventColumn(no);
1541 }
1542 
mergeEvents(bool flag)1543 void NdbDictionary::Event::mergeEvents(bool flag)
1544 {
1545   m_impl.m_mergeEvents = flag;
1546 }
1547 
1548 NdbDictionary::Object::Status
getObjectStatus() const1549 NdbDictionary::Event::getObjectStatus() const
1550 {
1551   return m_impl.m_status;
1552 }
1553 
1554 int
getObjectVersion() const1555 NdbDictionary::Event::getObjectVersion() const
1556 {
1557   return m_impl.m_version;
1558 }
1559 
1560 int
getObjectId() const1561 NdbDictionary::Event::getObjectId() const {
1562   return m_impl.m_id;
1563 }
1564 
print()1565 void NdbDictionary::Event::print()
1566 {
1567   m_impl.print();
1568 }
1569 
1570 /*****************************************************************
1571  * Tablespace facade
1572  */
Tablespace()1573 NdbDictionary::Tablespace::Tablespace()
1574   : m_impl(* new NdbTablespaceImpl(* this))
1575 {
1576 }
1577 
Tablespace(NdbTablespaceImpl & impl)1578 NdbDictionary::Tablespace::Tablespace(NdbTablespaceImpl & impl)
1579   : m_impl(impl)
1580 {
1581 }
1582 
Tablespace(const NdbDictionary::Tablespace & org)1583 NdbDictionary::Tablespace::Tablespace(const NdbDictionary::Tablespace & org)
1584   : Object(org), m_impl(* new NdbTablespaceImpl(* this))
1585 {
1586   m_impl.assign(org.m_impl);
1587 }
1588 
~Tablespace()1589 NdbDictionary::Tablespace::~Tablespace(){
1590   NdbTablespaceImpl * tmp = &m_impl;
1591   if(this != tmp){
1592     delete tmp;
1593   }
1594 }
1595 
1596 void
setName(const char * name)1597 NdbDictionary::Tablespace::setName(const char * name){
1598   m_impl.m_name.assign(name);
1599 }
1600 
1601 const char *
getName() const1602 NdbDictionary::Tablespace::getName() const {
1603   return m_impl.m_name.c_str();
1604 }
1605 
1606 void
setAutoGrowSpecification(const NdbDictionary::AutoGrowSpecification & spec)1607 NdbDictionary::Tablespace::setAutoGrowSpecification
1608 (const NdbDictionary::AutoGrowSpecification& spec){
1609   m_impl.m_grow_spec = spec;
1610 }
1611 const NdbDictionary::AutoGrowSpecification&
getAutoGrowSpecification() const1612 NdbDictionary::Tablespace::getAutoGrowSpecification() const {
1613   return m_impl.m_grow_spec;
1614 }
1615 
1616 void
setExtentSize(Uint32 sz)1617 NdbDictionary::Tablespace::setExtentSize(Uint32 sz){
1618   m_impl.m_extent_size = sz;
1619 }
1620 
1621 Uint32
getExtentSize() const1622 NdbDictionary::Tablespace::getExtentSize() const {
1623   return m_impl.m_extent_size;
1624 }
1625 
1626 void
setDefaultLogfileGroup(const char * name)1627 NdbDictionary::Tablespace::setDefaultLogfileGroup(const char * name){
1628   m_impl.m_logfile_group_id = ~0;
1629   m_impl.m_logfile_group_version = ~0;
1630   m_impl.m_logfile_group_name.assign(name);
1631 }
1632 
1633 void
setDefaultLogfileGroup(const NdbDictionary::LogfileGroup & lg)1634 NdbDictionary::Tablespace::setDefaultLogfileGroup
1635 (const NdbDictionary::LogfileGroup & lg){
1636   m_impl.m_logfile_group_id = NdbLogfileGroupImpl::getImpl(lg).m_id;
1637   m_impl.m_logfile_group_version = lg.getObjectVersion();
1638   m_impl.m_logfile_group_name.assign(lg.getName());
1639 }
1640 
1641 const char *
getDefaultLogfileGroup() const1642 NdbDictionary::Tablespace::getDefaultLogfileGroup() const {
1643   return m_impl.m_logfile_group_name.c_str();
1644 }
1645 
1646 Uint32
getDefaultLogfileGroupId() const1647 NdbDictionary::Tablespace::getDefaultLogfileGroupId() const {
1648   return m_impl.m_logfile_group_id;
1649 }
1650 
1651 NdbDictionary::Object::Status
getObjectStatus() const1652 NdbDictionary::Tablespace::getObjectStatus() const {
1653   return m_impl.m_status;
1654 }
1655 
1656 int
getObjectVersion() const1657 NdbDictionary::Tablespace::getObjectVersion() const {
1658   return m_impl.m_version;
1659 }
1660 
1661 int
getObjectId() const1662 NdbDictionary::Tablespace::getObjectId() const {
1663   return m_impl.m_id;
1664 }
1665 
1666 /*****************************************************************
1667  * LogfileGroup facade
1668  */
LogfileGroup()1669 NdbDictionary::LogfileGroup::LogfileGroup()
1670   : m_impl(* new NdbLogfileGroupImpl(* this))
1671 {
1672 }
1673 
LogfileGroup(NdbLogfileGroupImpl & impl)1674 NdbDictionary::LogfileGroup::LogfileGroup(NdbLogfileGroupImpl & impl)
1675   : m_impl(impl)
1676 {
1677 }
1678 
LogfileGroup(const NdbDictionary::LogfileGroup & org)1679 NdbDictionary::LogfileGroup::LogfileGroup(const NdbDictionary::LogfileGroup & org)
1680   : Object(org), m_impl(* new NdbLogfileGroupImpl(* this))
1681 {
1682   m_impl.assign(org.m_impl);
1683 }
1684 
~LogfileGroup()1685 NdbDictionary::LogfileGroup::~LogfileGroup(){
1686   NdbLogfileGroupImpl * tmp = &m_impl;
1687   if(this != tmp){
1688     delete tmp;
1689   }
1690 }
1691 
1692 void
setName(const char * name)1693 NdbDictionary::LogfileGroup::setName(const char * name){
1694   m_impl.m_name.assign(name);
1695 }
1696 
1697 const char *
getName() const1698 NdbDictionary::LogfileGroup::getName() const {
1699   return m_impl.m_name.c_str();
1700 }
1701 
1702 void
setUndoBufferSize(Uint32 sz)1703 NdbDictionary::LogfileGroup::setUndoBufferSize(Uint32 sz){
1704   m_impl.m_undo_buffer_size = sz;
1705 }
1706 
1707 Uint32
getUndoBufferSize() const1708 NdbDictionary::LogfileGroup::getUndoBufferSize() const {
1709   return m_impl.m_undo_buffer_size;
1710 }
1711 
1712 void
setAutoGrowSpecification(const NdbDictionary::AutoGrowSpecification & spec)1713 NdbDictionary::LogfileGroup::setAutoGrowSpecification
1714 (const NdbDictionary::AutoGrowSpecification& spec){
1715   m_impl.m_grow_spec = spec;
1716 }
1717 const NdbDictionary::AutoGrowSpecification&
getAutoGrowSpecification() const1718 NdbDictionary::LogfileGroup::getAutoGrowSpecification() const {
1719   return m_impl.m_grow_spec;
1720 }
1721 
getUndoFreeWords() const1722 Uint64 NdbDictionary::LogfileGroup::getUndoFreeWords() const {
1723   return m_impl.m_undo_free_words;
1724 }
1725 
1726 NdbDictionary::Object::Status
getObjectStatus() const1727 NdbDictionary::LogfileGroup::getObjectStatus() const {
1728   return m_impl.m_status;
1729 }
1730 
1731 int
getObjectVersion() const1732 NdbDictionary::LogfileGroup::getObjectVersion() const {
1733   return m_impl.m_version;
1734 }
1735 
1736 int
getObjectId() const1737 NdbDictionary::LogfileGroup::getObjectId() const {
1738   return m_impl.m_id;
1739 }
1740 
1741 /*****************************************************************
1742  * Datafile facade
1743  */
Datafile()1744 NdbDictionary::Datafile::Datafile()
1745   : m_impl(* new NdbDatafileImpl(* this))
1746 {
1747 }
1748 
Datafile(NdbDatafileImpl & impl)1749 NdbDictionary::Datafile::Datafile(NdbDatafileImpl & impl)
1750   : m_impl(impl)
1751 {
1752 }
1753 
Datafile(const NdbDictionary::Datafile & org)1754 NdbDictionary::Datafile::Datafile(const NdbDictionary::Datafile & org)
1755   : Object(org), m_impl(* new NdbDatafileImpl(* this))
1756 {
1757   m_impl.assign(org.m_impl);
1758 }
1759 
~Datafile()1760 NdbDictionary::Datafile::~Datafile(){
1761   NdbDatafileImpl * tmp = &m_impl;
1762   if(this != tmp){
1763     delete tmp;
1764   }
1765 }
1766 
1767 void
setPath(const char * path)1768 NdbDictionary::Datafile::setPath(const char * path){
1769   m_impl.m_path.assign(path);
1770 }
1771 
1772 const char *
getPath() const1773 NdbDictionary::Datafile::getPath() const {
1774   return m_impl.m_path.c_str();
1775 }
1776 
1777 void
setSize(Uint64 sz)1778 NdbDictionary::Datafile::setSize(Uint64 sz){
1779   m_impl.m_size = sz;
1780 }
1781 
1782 Uint64
getSize() const1783 NdbDictionary::Datafile::getSize() const {
1784   return m_impl.m_size;
1785 }
1786 
1787 Uint64
getFree() const1788 NdbDictionary::Datafile::getFree() const {
1789   return m_impl.m_free;
1790 }
1791 
1792 int
setTablespace(const char * tablespace)1793 NdbDictionary::Datafile::setTablespace(const char * tablespace){
1794   m_impl.m_filegroup_id = ~0;
1795   m_impl.m_filegroup_version = ~0;
1796   return !m_impl.m_filegroup_name.assign(tablespace);
1797 }
1798 
1799 int
setTablespace(const NdbDictionary::Tablespace & ts)1800 NdbDictionary::Datafile::setTablespace(const NdbDictionary::Tablespace & ts){
1801   m_impl.m_filegroup_id = NdbTablespaceImpl::getImpl(ts).m_id;
1802   m_impl.m_filegroup_version = ts.getObjectVersion();
1803   return !m_impl.m_filegroup_name.assign(ts.getName());
1804 }
1805 
1806 const char *
getTablespace() const1807 NdbDictionary::Datafile::getTablespace() const {
1808   return m_impl.m_filegroup_name.c_str();
1809 }
1810 
1811 void
getTablespaceId(NdbDictionary::ObjectId * dst) const1812 NdbDictionary::Datafile::getTablespaceId(NdbDictionary::ObjectId* dst) const
1813 {
1814   if (dst)
1815   {
1816     NdbDictObjectImpl::getImpl(* dst).m_id = m_impl.m_filegroup_id;
1817     NdbDictObjectImpl::getImpl(* dst).m_version = m_impl.m_filegroup_version;
1818   }
1819 }
1820 
1821 NdbDictionary::Object::Status
getObjectStatus() const1822 NdbDictionary::Datafile::getObjectStatus() const {
1823   return m_impl.m_status;
1824 }
1825 
1826 int
getObjectVersion() const1827 NdbDictionary::Datafile::getObjectVersion() const {
1828   return m_impl.m_version;
1829 }
1830 
1831 int
getObjectId() const1832 NdbDictionary::Datafile::getObjectId() const {
1833   return m_impl.m_id;
1834 }
1835 
1836 /*****************************************************************
1837  * Undofile facade
1838  */
Undofile()1839 NdbDictionary::Undofile::Undofile()
1840   : m_impl(* new NdbUndofileImpl(* this))
1841 {
1842 }
1843 
Undofile(NdbUndofileImpl & impl)1844 NdbDictionary::Undofile::Undofile(NdbUndofileImpl & impl)
1845   : m_impl(impl)
1846 {
1847 }
1848 
Undofile(const NdbDictionary::Undofile & org)1849 NdbDictionary::Undofile::Undofile(const NdbDictionary::Undofile & org)
1850   : Object(org), m_impl(* new NdbUndofileImpl(* this))
1851 {
1852   m_impl.assign(org.m_impl);
1853 }
1854 
~Undofile()1855 NdbDictionary::Undofile::~Undofile(){
1856   NdbUndofileImpl * tmp = &m_impl;
1857   if(this != tmp){
1858     delete tmp;
1859   }
1860 }
1861 
1862 void
setPath(const char * path)1863 NdbDictionary::Undofile::setPath(const char * path){
1864   m_impl.m_path.assign(path);
1865 }
1866 
1867 const char *
getPath() const1868 NdbDictionary::Undofile::getPath() const {
1869   return m_impl.m_path.c_str();
1870 }
1871 
1872 void
setSize(Uint64 sz)1873 NdbDictionary::Undofile::setSize(Uint64 sz){
1874   m_impl.m_size = sz;
1875 }
1876 
1877 Uint64
getSize() const1878 NdbDictionary::Undofile::getSize() const {
1879   return m_impl.m_size;
1880 }
1881 
1882 void
setLogfileGroup(const char * logfileGroup)1883 NdbDictionary::Undofile::setLogfileGroup(const char * logfileGroup){
1884   m_impl.m_filegroup_id = ~0;
1885   m_impl.m_filegroup_version = ~0;
1886   m_impl.m_filegroup_name.assign(logfileGroup);
1887 }
1888 
1889 void
setLogfileGroup(const NdbDictionary::LogfileGroup & ts)1890 NdbDictionary::Undofile::setLogfileGroup
1891 (const NdbDictionary::LogfileGroup & ts){
1892   m_impl.m_filegroup_id = NdbLogfileGroupImpl::getImpl(ts).m_id;
1893   m_impl.m_filegroup_version = ts.getObjectVersion();
1894   m_impl.m_filegroup_name.assign(ts.getName());
1895 }
1896 
1897 const char *
getLogfileGroup() const1898 NdbDictionary::Undofile::getLogfileGroup() const {
1899   return m_impl.m_filegroup_name.c_str();
1900 }
1901 
1902 void
getLogfileGroupId(NdbDictionary::ObjectId * dst) const1903 NdbDictionary::Undofile::getLogfileGroupId(NdbDictionary::ObjectId * dst)const
1904 {
1905   if (dst)
1906   {
1907     NdbDictObjectImpl::getImpl(* dst).m_id = m_impl.m_filegroup_id;
1908     NdbDictObjectImpl::getImpl(* dst).m_version = m_impl.m_filegroup_version;
1909   }
1910 }
1911 
1912 NdbDictionary::Object::Status
getObjectStatus() const1913 NdbDictionary::Undofile::getObjectStatus() const {
1914   return m_impl.m_status;
1915 }
1916 
1917 int
getObjectVersion() const1918 NdbDictionary::Undofile::getObjectVersion() const {
1919   return m_impl.m_version;
1920 }
1921 
1922 int
getObjectId() const1923 NdbDictionary::Undofile::getObjectId() const {
1924   return m_impl.m_id;
1925 }
1926 
1927 /*****************************************************************
1928  * HashMap facade
1929  */
HashMap()1930 NdbDictionary::HashMap::HashMap()
1931   : m_impl(* new NdbHashMapImpl(* this))
1932 {
1933 }
1934 
HashMap(NdbHashMapImpl & impl)1935 NdbDictionary::HashMap::HashMap(NdbHashMapImpl & impl)
1936   : m_impl(impl)
1937 {
1938 }
1939 
HashMap(const NdbDictionary::HashMap & org)1940 NdbDictionary::HashMap::HashMap(const NdbDictionary::HashMap & org)
1941   : Object(org), m_impl(* new NdbHashMapImpl(* this))
1942 {
1943   m_impl.assign(org.m_impl);
1944 }
1945 
~HashMap()1946 NdbDictionary::HashMap::~HashMap(){
1947   NdbHashMapImpl * tmp = &m_impl;
1948   if(this != tmp){
1949     delete tmp;
1950   }
1951 }
1952 
1953 void
setName(const char * path)1954 NdbDictionary::HashMap::setName(const char * path)
1955 {
1956   m_impl.m_name.assign(path);
1957 }
1958 
1959 const char *
getName() const1960 NdbDictionary::HashMap::getName() const
1961 {
1962   return m_impl.m_name.c_str();
1963 }
1964 
1965 void
setMap(const Uint32 * map,Uint32 len)1966 NdbDictionary::HashMap::setMap(const Uint32* map, Uint32 len)
1967 {
1968   m_impl.m_map.assign(map, len);
1969 }
1970 
1971 Uint32
getMapLen() const1972 NdbDictionary::HashMap::getMapLen() const
1973 {
1974   return m_impl.m_map.size();
1975 }
1976 
1977 int
getMapValues(Uint32 * dst,Uint32 len) const1978 NdbDictionary::HashMap::getMapValues(Uint32* dst, Uint32 len) const
1979 {
1980   if (len != getMapLen())
1981     return -1;
1982 
1983   memcpy(dst, m_impl.m_map.getBase(), sizeof(Uint32) * len);
1984   return 0;
1985 }
1986 
1987 bool
equal(const NdbDictionary::HashMap & obj) const1988 NdbDictionary::HashMap::equal(const NdbDictionary::HashMap & obj) const
1989 {
1990   return m_impl.m_map.equal(obj.m_impl.m_map);
1991 }
1992 
1993 NdbDictionary::Object::Status
getObjectStatus() const1994 NdbDictionary::HashMap::getObjectStatus() const {
1995   return m_impl.m_status;
1996 }
1997 
1998 int
getObjectVersion() const1999 NdbDictionary::HashMap::getObjectVersion() const {
2000   return m_impl.m_version;
2001 }
2002 
2003 int
getObjectId() const2004 NdbDictionary::HashMap::getObjectId() const {
2005   return m_impl.m_id;
2006 }
2007 
2008 int
getDefaultHashMap(NdbDictionary::HashMap & dst,Uint32 partitionCount)2009 NdbDictionary::Dictionary::getDefaultHashMap(NdbDictionary::HashMap& dst,
2010                                              Uint32 partitionCount)
2011 {
2012   return getDefaultHashMap(dst, m_impl.getDefaultHashmapSize(), partitionCount);
2013 }
2014 
2015 int
getDefaultHashMap(NdbDictionary::HashMap & dst,Uint32 buckets,Uint32 partitionCount)2016 NdbDictionary::Dictionary::getDefaultHashMap(NdbDictionary::HashMap& dst,
2017                                              Uint32 buckets,
2018                                              Uint32 partitionCount)
2019 {
2020   BaseString tmp;
2021   tmp.assfmt("DEFAULT-HASHMAP-%u-%u",
2022              buckets, partitionCount);
2023 
2024   return getHashMap(dst, tmp.c_str());
2025 }
2026 
2027 int
getHashMap(NdbDictionary::HashMap & dst,const char * name)2028 NdbDictionary::Dictionary::getHashMap(NdbDictionary::HashMap& dst,
2029                                       const char * name)
2030 {
2031   return m_impl.m_receiver.get_hashmap(NdbHashMapImpl::getImpl(dst), name);
2032 }
2033 
2034 int
getHashMap(NdbDictionary::HashMap & dst,const NdbDictionary::Table * tab)2035 NdbDictionary::Dictionary::getHashMap(NdbDictionary::HashMap& dst,
2036                                       const NdbDictionary::Table* tab)
2037 {
2038   if (tab == 0 ||
2039       tab->getFragmentType() != NdbDictionary::Object::HashMapPartition)
2040   {
2041     return -1;
2042   }
2043   return
2044     m_impl.m_receiver.get_hashmap(NdbHashMapImpl::getImpl(dst),
2045                                   NdbTableImpl::getImpl(*tab).m_hash_map_id);
2046 }
2047 
2048 int
initDefaultHashMap(NdbDictionary::HashMap & dst,Uint32 partitionCount)2049 NdbDictionary::Dictionary::initDefaultHashMap(NdbDictionary::HashMap& dst,
2050                                               Uint32 partitionCount)
2051 {
2052   return initDefaultHashMap(dst, m_impl.getDefaultHashmapSize(), partitionCount);
2053 }
2054 
2055 int
initDefaultHashMap(NdbDictionary::HashMap & dst,Uint32 buckets,Uint32 partitionCount)2056 NdbDictionary::Dictionary::initDefaultHashMap(NdbDictionary::HashMap& dst,
2057                                               Uint32 buckets,
2058                                               Uint32 partitionCount)
2059 {
2060   BaseString tmp;
2061   tmp.assfmt("DEFAULT-HASHMAP-%u-%u",
2062              buckets, partitionCount);
2063 
2064   dst.setName(tmp.c_str());
2065 
2066   Vector<Uint32> map;
2067   for (Uint32 i = 0; i < buckets; i++)
2068   {
2069     map.push_back(i % partitionCount);
2070   }
2071 
2072   dst.setMap(map.getBase(), map.size());
2073   return 0;
2074 }
2075 
2076 int
prepareHashMap(const Table & oldTableF,Table & newTableF)2077 NdbDictionary::Dictionary::prepareHashMap(const Table& oldTableF,
2078                                           Table& newTableF)
2079 {
2080   return prepareHashMap(oldTableF, newTableF, m_impl.getDefaultHashmapSize());
2081 }
2082 
2083 int
prepareHashMap(const Table & oldTableF,Table & newTableF,Uint32 buckets)2084 NdbDictionary::Dictionary::prepareHashMap(const Table& oldTableF,
2085                                           Table& newTableF,
2086                                           Uint32 buckets)
2087 {
2088   if (!hasSchemaTrans())
2089   {
2090     //Schema transaction is not started
2091     m_impl.m_error.code = 4412;
2092     return -1;
2093   }
2094 
2095   const NdbTableImpl& oldTable = NdbTableImpl::getImpl(oldTableF);
2096   NdbTableImpl& newTable = NdbTableImpl::getImpl(newTableF);
2097 
2098   if (oldTable.getFragmentType() == NdbDictionary::Object::HashMapPartition)
2099   {
2100     HashMap oldmap;
2101     if (getHashMap(oldmap, &oldTable) == -1)
2102     {
2103       return -1;
2104     }
2105 
2106     if (oldmap.getObjectVersion() != (int)oldTable.m_hash_map_version)
2107     {
2108       m_impl.m_error.code = 241;
2109       return -1;
2110     }
2111 
2112     HashMap newmapF;
2113 
2114     // Table definitions from data nodes always have partition count set.
2115     Uint32 oldcnt = oldTable.getPartitionCount();
2116     Uint32 newcnt;
2117     if (newTable.getPartitionBalance() == NdbDictionary::Table::PartitionBalance_Specific)
2118     {
2119       if (newTable.getFullyReplicated())
2120       {
2121         /**
2122          * Applications can not yet specify partition count only fragment
2123          * count, which are different for fully replicated tables.
2124          */
2125         m_impl.m_error.code = 797; // WrongPartitionBalanceFullyReplicated
2126         return -1;
2127       }
2128       /**
2129        * For non fully replicated tables fragment count and partition count is
2130        * the same.
2131        */
2132       newcnt = newTable.getFragmentCount();
2133     }
2134     else
2135     {
2136       newcnt = 0;
2137     }
2138     DBUG_PRINT("info", ("prepareHashMap: frag count: %u", newcnt));
2139     if (newcnt == 0)
2140     {
2141       /**
2142        * reorg...we don't know how many fragments new table should have
2143        *   create if exist a default map...which will "know" how many fragments there are
2144        */
2145       ObjectId tmp;
2146       int flags = CreateHashMapReq::CreateDefault |
2147                   CreateHashMapReq::CreateIfNotExists;
2148       if (newTable.getFullyReplicated())
2149       {
2150         flags |= CreateHashMapReq::CreateForOneNodegroup;
2151       }
2152       int ret = m_impl.m_receiver.create_hashmap(NdbHashMapImpl::getImpl(newmapF),
2153                                                  &NdbDictObjectImpl::getImpl(tmp),
2154                                                  flags,
2155                                                  newTable.getPartitionBalance());
2156       if (ret)
2157       {
2158         return -1;
2159       }
2160 
2161       HashMap hm;
2162       ret = m_impl.m_receiver.get_hashmap(NdbHashMapImpl::getImpl(hm), tmp.getObjectId());
2163       if (ret)
2164       {
2165         return -1;
2166       }
2167       Uint32 zero = 0;
2168       Vector<Uint32> values;
2169       values.fill(hm.getMapLen() - 1, zero);
2170       hm.getMapValues(values.getBase(), values.size());
2171       for (Uint32 i = 0; i<hm.getMapLen(); i++)
2172       {
2173         if (values[i] > newcnt)
2174           newcnt = values[i];
2175       }
2176       newcnt++; // Loop will find max val, cnt = max + 1
2177       if (newcnt < oldcnt)
2178       {
2179         /**
2180          * drop partition is currently not supported...
2181          *   and since this is a "reorg" (newcnt == 0) we silently change it to a nop
2182          */
2183         newcnt = oldcnt;
2184       }
2185       if (!newTable.getFullyReplicated())
2186       {
2187         newTable.setFragmentCount(newcnt);
2188       }
2189       else
2190       {
2191         /**
2192          * For fully replicated table new fragment count is still unknown.  Keep it zero.
2193          */
2194         assert(newTable.getFragmentCount() == 0);
2195       }
2196       DBUG_PRINT("info", ("prepareHashMap: New frag count: %u", newcnt));
2197     }
2198 
2199     /*
2200      * If fragment count has not changed, dont move data between partitions and
2201      * keep old hashmap.
2202      * For fully replicated tables copy data to copy fragments are still
2203      * expected to happen, out of Ndbapi control in data nodes.
2204      */
2205 
2206     if (newcnt == oldcnt)
2207     {
2208       newTable.m_hash_map_id = oldTable.m_hash_map_id;
2209       newTable.m_hash_map_version = oldTable.m_hash_map_version;
2210       return 0;
2211     }
2212     else if (newTable.getFullyReplicated())
2213     {
2214       // Fully replicated tables may not change partition count.
2215       m_impl.m_error.code = 797; // WrongPartitionBalanceFullyReplicated
2216       return -1;
2217     }
2218 
2219     Uint32 newmapsize = buckets;
2220     Uint32 oldmapsize = oldmap.getMapLen();
2221 
2222     /**
2223      * if old hashmap size is smaller than new hashmap size
2224      * and new fragment count is a multiple of old hashmap
2225      * size, no need to extend map, keep old hashmap size
2226      */
2227 
2228     if (oldmapsize < newmapsize &&
2229         oldmapsize % newcnt == 0)
2230     {
2231       newmapsize = oldmapsize;
2232     }
2233 
2234     NdbHashMapImpl& newmap = NdbHashMapImpl::getImpl(newmapF);
2235     NdbHashMapImpl const& oldmapimpl = NdbHashMapImpl::getImpl(oldmap);
2236 
2237     newmap.m_map.expand(newmapsize);
2238     for (Uint32 i = 0; i < newmapsize; i++)
2239     {
2240       Uint32 newval = i % newcnt;
2241       if (newval < oldcnt)
2242       {
2243          newval = oldmapimpl.m_map[i % oldmapsize];
2244       }
2245       newmap.m_map.push_back(newval);
2246     }
2247 
2248     /**
2249      * check that new map do not imply data movement
2250      * from old fragment to another old fragment.
2251      * in such case, fall back to use old hashmap size
2252      */
2253 
2254     if (oldmapsize != newmapsize)
2255     {
2256       Uint32 period = lcm(oldmapsize, newmapsize);
2257       Uint32 i;
2258 
2259       for (i = 0; i < period; i++)
2260       {
2261         if (oldmapimpl.m_map[i % oldmapsize] != newmap.m_map[i % newmapsize] &&
2262             newmap.m_map[i % newmapsize] < oldcnt)
2263         {
2264           /**
2265            * move from old fragment to another old fragment
2266            * not supported - keep old hashmap size
2267            */
2268           break;
2269         }
2270       }
2271 
2272       /* keep old hashmap size, recreate newmap */
2273       if (i < period)
2274       {
2275         newmapsize = oldmapsize;
2276         newmap.m_map.clear();
2277         newmap.m_map.expand(newmapsize);
2278         for (Uint32 i = 0; i < newmapsize; i++)
2279         {
2280           Uint32 newval = i % newcnt;
2281           if (newval < oldcnt)
2282           {
2283              newval = oldmapimpl.m_map[i % oldmapsize];
2284           }
2285           newmap.m_map.push_back(newval);
2286         }
2287       }
2288     }
2289 
2290     /**
2291      * Check if this accidently became a "default" map
2292      */
2293     HashMap def;
2294     if (getDefaultHashMap(def, newmapsize, newcnt) == 0)
2295     {
2296       if (def.equal(newmapF))
2297       {
2298         newTable.m_hash_map_id = def.getObjectId();
2299         newTable.m_hash_map_version = def.getObjectVersion();
2300         return 0;
2301       }
2302     }
2303 
2304     initDefaultHashMap(def, newmapsize, newcnt);
2305     if (def.equal(newmapF))
2306     {
2307       ObjectId tmp;
2308       if (createHashMap(def, &tmp) == -1)
2309       {
2310         return -1;
2311       }
2312       newTable.m_hash_map_id = tmp.getObjectId();
2313       newTable.m_hash_map_version = tmp.getObjectVersion();
2314       return 0;
2315     }
2316 
2317     int cnt = 0;
2318 retry:
2319     if (cnt == 0)
2320     {
2321       newmap.m_name.assfmt("HASHMAP-%u-%u-%u",
2322                            newmapsize,
2323                            oldcnt,
2324                            newcnt);
2325     }
2326     else
2327     {
2328       newmap.m_name.assfmt("HASHMAP-%u-%u-%u-#%u",
2329                            newmapsize,
2330                            oldcnt,
2331                            newcnt,
2332                            cnt);
2333 
2334     }
2335 
2336     if (getHashMap(def, newmap.getName()) == 0)
2337     {
2338       if (def.equal(newmap))
2339       {
2340         newTable.m_hash_map_id = def.getObjectId();
2341         newTable.m_hash_map_version = def.getObjectVersion();
2342         return 0;
2343       }
2344       cnt++;
2345       goto retry;
2346     }
2347 
2348     ObjectId tmp;
2349     if (createHashMap(newmapF, &tmp) == -1)
2350     {
2351       return -1;
2352     }
2353     newTable.m_hash_map_id = tmp.getObjectId();
2354     newTable.m_hash_map_version = tmp.getObjectVersion();
2355     return 0;
2356   }
2357   assert(false); // NOT SUPPORTED YET
2358   return -1;
2359 }
2360 
2361 /*****************************************************************
2362  * ForeignKey facade
2363  */
ForeignKey()2364 NdbDictionary::ForeignKey::ForeignKey()
2365   : m_impl(* new NdbForeignKeyImpl(* this))
2366 {
2367 }
2368 
ForeignKey(NdbForeignKeyImpl & impl)2369 NdbDictionary::ForeignKey::ForeignKey(NdbForeignKeyImpl & impl)
2370   : m_impl(impl)
2371 {
2372 }
2373 
ForeignKey(const NdbDictionary::ForeignKey & org)2374 NdbDictionary::ForeignKey::ForeignKey(const NdbDictionary::ForeignKey & org)
2375   : Object(org), m_impl(* new NdbForeignKeyImpl(* this))
2376 {
2377   m_impl.assign(org.m_impl);
2378 }
2379 
~ForeignKey()2380 NdbDictionary::ForeignKey::~ForeignKey(){
2381   NdbForeignKeyImpl * tmp = &m_impl;
2382   if(this != tmp){
2383     delete tmp;
2384   }
2385 }
2386 
2387 const char *
getName() const2388 NdbDictionary::ForeignKey::getName() const
2389 {
2390   return m_impl.m_name.c_str();
2391 }
2392 
2393 NdbDictionary::Object::Status
getObjectStatus() const2394 NdbDictionary::ForeignKey::getObjectStatus() const {
2395   return m_impl.m_status;
2396 }
2397 
2398 int
getObjectVersion() const2399 NdbDictionary::ForeignKey::getObjectVersion() const {
2400   return m_impl.m_version;
2401 }
2402 
2403 int
getObjectId() const2404 NdbDictionary::ForeignKey::getObjectId() const {
2405   return m_impl.m_id;
2406 }
2407 
2408 void
setName(const char * name)2409 NdbDictionary::ForeignKey::setName(const char * name)
2410 {
2411   m_impl.m_name.assign(name);
2412 }
2413 
2414 void
setParent(const Table & tab,const Index * idx,const Column * cols[])2415 NdbDictionary::ForeignKey::setParent(const Table& tab,
2416                                      const Index * idx,
2417                                      const Column * cols[])
2418 {
2419   m_impl.m_references[0].m_name.assign(tab.getName());
2420   m_impl.m_references[0].m_objectId = RNIL;
2421   m_impl.m_references[0].m_objectVersion = RNIL;
2422   m_impl.m_references[2].m_name.clear();
2423   m_impl.m_references[2].m_objectId = RNIL;
2424   m_impl.m_references[2].m_objectVersion = RNIL;
2425 
2426   switch(tab.getObjectStatus()) {
2427   case NdbDictionary::Object::New:
2428     break;
2429   default:
2430     m_impl.m_references[0].m_objectId = tab.getObjectId();
2431     m_impl.m_references[0].m_objectVersion = tab.getObjectVersion();
2432     break;
2433   }
2434 
2435   if (idx)
2436   {
2437     m_impl.m_references[2].m_name.assign(idx->getName());
2438     switch(idx->getObjectStatus()){
2439     case NdbDictionary::Object::New:
2440       break;
2441     default:
2442       m_impl.m_references[2].m_objectId = idx->getObjectId();
2443       m_impl.m_references[2].m_objectVersion = idx->getObjectVersion();
2444     }
2445   }
2446 
2447   m_impl.m_parent_columns.clear();
2448   if (cols)
2449   {
2450     for (Uint32 i = 0; cols[i] != 0; i++)
2451     {
2452       m_impl.m_parent_columns.push_back(cols[i]->getColumnNo());
2453     }
2454   }
2455   else if (idx == 0)
2456   {
2457     for (int i = 0; i < tab.getNoOfColumns(); i++)
2458     {
2459       if (tab.getColumn(i)->getPrimaryKey())
2460       {
2461         m_impl.m_parent_columns.push_back(tab.getColumn(i)->getColumnNo());
2462       }
2463     }
2464   }
2465   else
2466   {
2467     for (unsigned i = 0; i < idx->getNoOfColumns(); i++)
2468     {
2469       const Column * idxcol = idx->getColumn(i);
2470       const Column * tabcol = tab.getColumn(idxcol->getName());
2471       if (tabcol)
2472       {
2473         // no way of reporting error...just add the if...
2474         // and let dict complain at ::create()
2475         m_impl.m_parent_columns.push_back(tabcol->getColumnNo());
2476       }
2477     }
2478   }
2479 }
2480 
2481 const char *
getParentTable() const2482 NdbDictionary::ForeignKey::getParentTable() const
2483 {
2484   return m_impl.m_references[0].m_name.c_str();
2485 }
2486 
2487 const char *
getParentIndex() const2488 NdbDictionary::ForeignKey::getParentIndex() const
2489 {
2490   if (m_impl.m_references[2].m_name.empty())
2491     return 0;
2492   return m_impl.m_references[2].m_name.c_str();
2493 }
2494 
2495 void
setChild(const Table & tab,const Index * idx,const Column * cols[])2496 NdbDictionary::ForeignKey::setChild(const Table& tab,
2497                                      const Index * idx,
2498                                      const Column * cols[])
2499 {
2500   m_impl.m_references[1].m_name.assign(tab.getName());
2501   m_impl.m_references[1].m_objectId = RNIL;
2502   m_impl.m_references[1].m_objectVersion = RNIL;
2503   m_impl.m_references[3].m_name.clear();
2504   m_impl.m_references[3].m_objectId = RNIL;
2505   m_impl.m_references[3].m_objectVersion = RNIL;
2506 
2507   switch(tab.getObjectStatus()) {
2508   case NdbDictionary::Object::New:
2509     break;
2510   default:
2511     m_impl.m_references[1].m_objectId = tab.getObjectId();
2512     m_impl.m_references[1].m_objectVersion = tab.getObjectVersion();
2513     break;
2514   }
2515 
2516   if (idx)
2517   {
2518     m_impl.m_references[3].m_name.assign(idx->getName());
2519     switch(idx->getObjectStatus()){
2520     case NdbDictionary::Object::New:
2521       break;
2522     default:
2523       m_impl.m_references[3].m_objectId = idx->getObjectId();
2524       m_impl.m_references[3].m_objectVersion = idx->getObjectVersion();
2525     }
2526   }
2527 
2528   m_impl.m_child_columns.clear();
2529   if (cols)
2530   {
2531     for (Uint32 i = 0; cols[i] != 0; i++)
2532     {
2533       m_impl.m_child_columns.push_back(cols[i]->getColumnNo());
2534     }
2535   }
2536   else if (idx == 0)
2537   {
2538     for (int i = 0; i < tab.getNoOfColumns(); i++)
2539     {
2540       if (tab.getColumn(i)->getPrimaryKey())
2541       {
2542         m_impl.m_child_columns.push_back(tab.getColumn(i)->getColumnNo());
2543       }
2544     }
2545   }
2546   else
2547   {
2548     for (unsigned i = 0; i < idx->getNoOfColumns(); i++)
2549     {
2550       const Column * idxcol = idx->getColumn(i);
2551       const Column * tabcol = tab.getColumn(idxcol->getName());
2552       if (tabcol)
2553       {
2554         // no way of reporting error...just add the if...
2555         // and let dict complain at ::create()
2556         m_impl.m_child_columns.push_back(tabcol->getColumnNo());
2557       }
2558     }
2559   }
2560 }
2561 
2562 const char *
getChildTable() const2563 NdbDictionary::ForeignKey::getChildTable() const
2564 {
2565   return m_impl.m_references[1].m_name.c_str();
2566 }
2567 
2568 const char *
getChildIndex() const2569 NdbDictionary::ForeignKey::getChildIndex() const
2570 {
2571   if (m_impl.m_references[3].m_name.empty())
2572     return 0;
2573   return m_impl.m_references[3].m_name.c_str();
2574 }
2575 
2576 
2577 NdbDictionary::ForeignKey::FkAction
getOnUpdateAction() const2578 NdbDictionary::ForeignKey::getOnUpdateAction() const
2579 {
2580   return m_impl.m_on_update_action;
2581 }
2582 
2583 void
setOnUpdateAction(FkAction _action)2584 NdbDictionary::ForeignKey::setOnUpdateAction(FkAction _action)
2585 {
2586   m_impl.m_on_update_action = _action;
2587 }
2588 
2589 NdbDictionary::ForeignKey::FkAction
getOnDeleteAction() const2590 NdbDictionary::ForeignKey::getOnDeleteAction() const
2591 {
2592   return m_impl.m_on_delete_action;
2593 }
2594 
2595 void
setOnDeleteAction(FkAction _action)2596 NdbDictionary::ForeignKey::setOnDeleteAction(FkAction _action)
2597 {
2598   m_impl.m_on_delete_action = _action;
2599 }
2600 
2601 unsigned
getParentColumnCount() const2602 NdbDictionary::ForeignKey::getParentColumnCount() const
2603 {
2604   return m_impl.m_parent_columns.size();
2605 }
2606 
2607 int
getParentColumnNo(unsigned no) const2608 NdbDictionary::ForeignKey::getParentColumnNo(unsigned no) const
2609 {
2610   if (no < m_impl.m_parent_columns.size())
2611   {
2612     return (int)m_impl.m_parent_columns[no];
2613   }
2614   return -1;
2615 }
2616 
2617 unsigned
getChildColumnCount() const2618 NdbDictionary::ForeignKey::getChildColumnCount() const
2619 {
2620   return m_impl.m_child_columns.size();
2621 }
2622 
2623 int
getChildColumnNo(unsigned no) const2624 NdbDictionary::ForeignKey::getChildColumnNo(unsigned no) const
2625 {
2626   if (no < m_impl.m_child_columns.size())
2627   {
2628     return (int)m_impl.m_child_columns[no];
2629   }
2630   return -1;
2631 }
2632 
2633 /*****************************************************************
2634  * Dictionary facade
2635  */
Dictionary(Ndb & ndb)2636 NdbDictionary::Dictionary::Dictionary(Ndb & ndb)
2637   : m_impl(* new NdbDictionaryImpl(ndb, *this))
2638 {
2639 }
2640 
Dictionary(NdbDictionaryImpl & impl)2641 NdbDictionary::Dictionary::Dictionary(NdbDictionaryImpl & impl)
2642   : m_impl(impl)
2643 {
2644 }
~Dictionary()2645 NdbDictionary::Dictionary::~Dictionary(){
2646   NdbDictionaryImpl * tmp = &m_impl;
2647   if(this != tmp){
2648     delete tmp;
2649   }
2650 }
2651 
2652 // do op within trans if no trans exists
2653 #define DO_TRANS(ret, action) \
2654   { \
2655     bool trans = hasSchemaTrans(); \
2656     if ((trans || (ret = beginSchemaTrans()) == 0) && \
2657         (ret = (action)) == 0 && \
2658         (trans || (ret = endSchemaTrans()) == 0)) \
2659       ; \
2660     else if (!trans) { \
2661       NdbError save_error = m_impl.m_error; \
2662       (void)endSchemaTrans(SchemaTransAbort); \
2663       m_impl.m_error = save_error; \
2664     } \
2665   }
2666 
2667 int
createTable(const Table & t)2668 NdbDictionary::Dictionary::createTable(const Table & t)
2669 {
2670   return createTable(t, 0);
2671 }
2672 
2673 int
createTable(const Table & t,ObjectId * objId)2674 NdbDictionary::Dictionary::createTable(const Table & t, ObjectId * objId)
2675 {
2676   int ret;
2677   ObjectId tmp;
2678   if (objId == 0)
2679     objId = &tmp;
2680 
2681   if (likely(! is_ndb_blob_table(t.getName())))
2682   {
2683     DO_TRANS(
2684       ret,
2685       m_impl.createTable(NdbTableImpl::getImpl(t),
2686                          NdbDictObjectImpl::getImpl( *objId))
2687     );
2688   }
2689   else
2690   {
2691     /* 4307 : Invalid table name */
2692     m_impl.m_error.code = 4307;
2693     ret = -1;
2694   }
2695   return ret;
2696 }
2697 
2698 int
optimizeTable(const Table & t,OptimizeTableHandle & h)2699 NdbDictionary::Dictionary::optimizeTable(const Table &t,
2700                                          OptimizeTableHandle &h){
2701   DBUG_ENTER("NdbDictionary::Dictionary::optimzeTable");
2702   DBUG_RETURN(m_impl.optimizeTable(NdbTableImpl::getImpl(t),
2703                                    NdbOptimizeTableHandleImpl::getImpl(h)));
2704 }
2705 
2706 int
optimizeIndex(const Index & ind,NdbDictionary::OptimizeIndexHandle & h)2707 NdbDictionary::Dictionary::optimizeIndex(const Index &ind,
2708                                          NdbDictionary::OptimizeIndexHandle &h)
2709 {
2710   DBUG_ENTER("NdbDictionary::Dictionary::optimzeIndex");
2711   DBUG_RETURN(m_impl.optimizeIndex(NdbIndexImpl::getImpl(ind),
2712                                    NdbOptimizeIndexHandleImpl::getImpl(h)));
2713 }
2714 
2715 int
dropTable(Table & t)2716 NdbDictionary::Dictionary::dropTable(Table & t)
2717 {
2718   int ret;
2719   if (likely(! is_ndb_blob_table(t.getName())))
2720   {
2721     DO_TRANS(
2722       ret,
2723       m_impl.dropTable(NdbTableImpl::getImpl(t))
2724     );
2725   }
2726   else
2727   {
2728     /* 4249 : Invalid table */
2729     m_impl.m_error.code = 4249;
2730     ret = -1;
2731   }
2732   return ret;
2733 }
2734 
2735 int
dropTableGlobal(const Table & t)2736 NdbDictionary::Dictionary::dropTableGlobal(const Table & t)
2737 {
2738   return dropTableGlobal(t, 0);
2739 }
2740 
2741 int
dropTableGlobal(const Table & t,int flags)2742 NdbDictionary::Dictionary::dropTableGlobal(const Table & t, int flags)
2743 {
2744   int ret;
2745   if (likely(! is_ndb_blob_table(t.getName())))
2746   {
2747     DO_TRANS(
2748       ret,
2749       m_impl.dropTableGlobal(NdbTableImpl::getImpl(t), flags)
2750     );
2751   }
2752   else
2753   {
2754     /* 4249 : Invalid table */
2755     m_impl.m_error.code = 4249;
2756     ret = -1;
2757   }
2758   return ret;
2759 }
2760 
2761 int
dropTable(const char * name)2762 NdbDictionary::Dictionary::dropTable(const char * name)
2763 {
2764   int ret;
2765   if (likely(! is_ndb_blob_table(name)))
2766   {
2767     DO_TRANS(
2768       ret,
2769       m_impl.dropTable(name)
2770     );
2771   }
2772   else
2773   {
2774     /* 4307 : Invalid table name */
2775     m_impl.m_error.code = 4307;
2776     ret = -1;
2777   }
2778   return ret;
2779 }
2780 
2781 bool
supportedAlterTable(const Table & f,const Table & t)2782 NdbDictionary::Dictionary::supportedAlterTable(const Table & f,
2783 					       const Table & t)
2784 {
2785   return m_impl.supportedAlterTable(NdbTableImpl::getImpl(f),
2786                                     NdbTableImpl::getImpl(t));
2787 }
2788 
2789 int
alterTable(const Table & f,const Table & t)2790 NdbDictionary::Dictionary::alterTable(const Table & f, const Table & t)
2791 {
2792   int ret;
2793   DO_TRANS(
2794     ret,
2795     m_impl.alterTable(NdbTableImpl::getImpl(f),
2796                       NdbTableImpl::getImpl(t))
2797   );
2798   return ret;
2799 }
2800 
2801 int
alterTableGlobal(const Table & f,const Table & t)2802 NdbDictionary::Dictionary::alterTableGlobal(const Table & f,
2803                                             const Table & t)
2804 {
2805   int ret;
2806   DO_TRANS(
2807     ret,
2808     m_impl.alterTableGlobal(NdbTableImpl::getImpl(f),
2809                             NdbTableImpl::getImpl(t))
2810   );
2811   return ret;
2812 }
2813 
2814 const NdbDictionary::Table *
getTable(const char * name,void ** data) const2815 NdbDictionary::Dictionary::getTable(const char * name, void **data) const
2816 {
2817   NdbTableImpl * t = m_impl.getTable(name, data);
2818   if(t)
2819     return t->m_facade;
2820   return 0;
2821 }
2822 
2823 const NdbDictionary::Index *
getIndexGlobal(const char * indexName,const Table & ndbtab) const2824 NdbDictionary::Dictionary::getIndexGlobal(const char * indexName,
2825                                           const Table &ndbtab) const
2826 {
2827   NdbIndexImpl * i = m_impl.getIndexGlobal(indexName,
2828                                            NdbTableImpl::getImpl(ndbtab));
2829   if(i)
2830     return i->m_facade;
2831   return 0;
2832 }
2833 
2834 const NdbDictionary::Index *
getIndexGlobal(const char * indexName,const char * tableName) const2835 NdbDictionary::Dictionary::getIndexGlobal(const char * indexName,
2836                                           const char * tableName) const
2837 {
2838   NdbIndexImpl * i = m_impl.getIndexGlobal(indexName,
2839                                            tableName);
2840   if(i)
2841     return i->m_facade;
2842   return 0;
2843 }
2844 
2845 const NdbDictionary::Table *
getTableGlobal(const char * name) const2846 NdbDictionary::Dictionary::getTableGlobal(const char * name) const
2847 {
2848   NdbTableImpl * t = m_impl.getTableGlobal(name);
2849   if(t)
2850     return t->m_facade;
2851   return 0;
2852 }
2853 
2854 int
removeIndexGlobal(const Index & ndbidx,int invalidate) const2855 NdbDictionary::Dictionary::removeIndexGlobal(const Index &ndbidx,
2856                                              int invalidate) const
2857 {
2858   return m_impl.releaseIndexGlobal(NdbIndexImpl::getImpl(ndbidx), invalidate);
2859 }
2860 
2861 int
removeTableGlobal(const Table & ndbtab,int invalidate) const2862 NdbDictionary::Dictionary::removeTableGlobal(const Table &ndbtab,
2863                                              int invalidate) const
2864 {
2865   return m_impl.releaseTableGlobal(NdbTableImpl::getImpl(ndbtab), invalidate);
2866 }
2867 
2868 NdbRecord *
createRecord(const Table * table,const RecordSpecification * recSpec,Uint32 length,Uint32 elemSize,Uint32 flags)2869 NdbDictionary::Dictionary::createRecord(const Table *table,
2870                                         const RecordSpecification *recSpec,
2871                                         Uint32 length,
2872                                         Uint32 elemSize,
2873                                         Uint32 flags)
2874 {
2875   /* We want to obtain a global reference to the Table object */
2876   NdbTableImpl* impl=&NdbTableImpl::getImpl(*table);
2877   Ndb* myNdb= &m_impl.m_ndb;
2878 
2879   /* Temporarily change Ndb object to use table's database
2880    * and schema
2881    */
2882   BaseString currentDb(myNdb->getDatabaseName());
2883   BaseString currentSchema(myNdb->getDatabaseSchemaName());
2884 
2885   myNdb->setDatabaseName
2886     (Ndb::getDatabaseFromInternalName(impl->m_internalName.c_str()).c_str());
2887   myNdb->setDatabaseSchemaName
2888     (Ndb::getSchemaFromInternalName(impl->m_internalName.c_str()).c_str());
2889 
2890   /* Get global ref to table.  This is released below, or when the
2891    * NdbRecord is released
2892    */
2893   const Table* globalTab= getTableGlobal(impl->m_externalName.c_str());
2894 
2895   /* Restore Ndb object's DB and Schema */
2896   myNdb->setDatabaseName(currentDb.c_str());
2897   myNdb->setDatabaseSchemaName(currentSchema.c_str());
2898 
2899   if (globalTab == NULL)
2900     /* An error is set on the dictionary */
2901     return NULL;
2902 
2903   NdbTableImpl* globalTabImpl= &NdbTableImpl::getImpl(*globalTab);
2904 
2905   assert(impl->m_id == globalTabImpl->m_id);
2906   if (table_version_major(impl->m_version) !=
2907       table_version_major(globalTabImpl->m_version))
2908   {
2909     removeTableGlobal(*globalTab, false); // Don't invalidate
2910     m_impl.m_error.code= 241; //Invalid schema object version
2911     return NULL;
2912   }
2913 
2914   NdbRecord* result= m_impl.createRecord(globalTabImpl,
2915                                          recSpec,
2916                                          length,
2917                                          elemSize,
2918                                          flags,
2919                                          false); // Not default NdbRecord
2920 
2921   if (!result)
2922   {
2923     removeTableGlobal(*globalTab, false); // Don't invalidate
2924   }
2925   return result;
2926 }
2927 
2928 NdbRecord *
createRecord(const Index * index,const Table * table,const RecordSpecification * recSpec,Uint32 length,Uint32 elemSize,Uint32 flags)2929 NdbDictionary::Dictionary::createRecord(const Index *index,
2930                                         const Table *table,
2931                                         const RecordSpecification *recSpec,
2932                                         Uint32 length,
2933                                         Uint32 elemSize,
2934                                         Uint32 flags)
2935 {
2936   /* We want to obtain a global reference to the Index's underlying
2937    * table object
2938    */
2939   NdbTableImpl* tabImpl=&NdbTableImpl::getImpl(*table);
2940   Ndb* myNdb= &m_impl.m_ndb;
2941 
2942   /* Temporarily change Ndb object to use table's database
2943    * and schema.  Index's database and schema are not
2944    * useful for finding global table reference
2945    */
2946   BaseString currentDb(myNdb->getDatabaseName());
2947   BaseString currentSchema(myNdb->getDatabaseSchemaName());
2948 
2949   myNdb->setDatabaseName
2950     (Ndb::getDatabaseFromInternalName(tabImpl->m_internalName.c_str()).c_str());
2951   myNdb->setDatabaseSchemaName
2952     (Ndb::getSchemaFromInternalName(tabImpl->m_internalName.c_str()).c_str());
2953 
2954   /* Get global ref to index.  This is released below, or when the
2955    * NdbRecord object is released
2956    */
2957   const Index* globalIndex= getIndexGlobal(index->getName(), *table);
2958 
2959   /* Restore Ndb object's DB and Schema */
2960   myNdb->setDatabaseName(currentDb.c_str());
2961   myNdb->setDatabaseSchemaName(currentSchema.c_str());
2962 
2963   if (globalIndex == NULL)
2964     /* An error is set on the dictionary */
2965     return NULL;
2966 
2967   NdbIndexImpl* indexImpl= &NdbIndexImpl::getImpl(*index);
2968   NdbIndexImpl* globalIndexImpl= &NdbIndexImpl::getImpl(*globalIndex);
2969 
2970   assert(indexImpl->m_id == globalIndexImpl->m_id);
2971 
2972   if (table_version_major(indexImpl->m_version) !=
2973       table_version_major(globalIndexImpl->m_version))
2974   {
2975     removeIndexGlobal(*globalIndex, false); // Don't invalidate
2976     m_impl.m_error.code= 241; //Invalid schema object version
2977     return NULL;
2978   }
2979 
2980   NdbRecord* result= m_impl.createRecord(globalIndexImpl->m_table,
2981                                          recSpec,
2982                                          length,
2983                                          elemSize,
2984                                          flags,
2985                                          false); // Not default NdbRecord
2986 
2987   if (!result)
2988   {
2989     removeIndexGlobal(*globalIndex, false); // Don't invalidate
2990   }
2991   return result;
2992 }
2993 
2994 NdbRecord *
createRecord(const Index * index,const RecordSpecification * recSpec,Uint32 length,Uint32 elemSize,Uint32 flags)2995 NdbDictionary::Dictionary::createRecord(const Index *index,
2996                                         const RecordSpecification *recSpec,
2997                                         Uint32 length,
2998                                         Uint32 elemSize,
2999                                         Uint32 flags)
3000 {
3001   const NdbDictionary::Table *table= getTable(index->getTable());
3002   if (!table)
3003     return NULL;
3004   return createRecord(index,
3005                       table,
3006                       recSpec,
3007                       length,
3008                       elemSize,
3009                       flags);
3010 }
3011 
3012 void
releaseRecord(NdbRecord * rec)3013 NdbDictionary::Dictionary::releaseRecord(NdbRecord *rec)
3014 {
3015   m_impl.releaseRecord_impl(rec);
3016 }
3017 
putTable(const NdbDictionary::Table * table)3018 void NdbDictionary::Dictionary::putTable(const NdbDictionary::Table * table)
3019 {
3020  NdbDictionary::Table  *copy_table = new NdbDictionary::Table;
3021   *copy_table = *table;
3022   m_impl.putTable(&NdbTableImpl::getImpl(*copy_table));
3023 }
3024 
set_local_table_data_size(unsigned sz)3025 void NdbDictionary::Dictionary::set_local_table_data_size(unsigned sz)
3026 {
3027   m_impl.m_local_table_data_size= sz;
3028 }
3029 
3030 const NdbDictionary::Table *
getTable(const char * name) const3031 NdbDictionary::Dictionary::getTable(const char * name) const
3032 {
3033   return getTable(name, 0);
3034 }
3035 
3036 const NdbDictionary::Table *
getBlobTable(const NdbDictionary::Table * table,const char * col_name)3037 NdbDictionary::Dictionary::getBlobTable(const NdbDictionary::Table* table,
3038                                         const char* col_name)
3039 {
3040   const NdbDictionary::Column* col = table->getColumn(col_name);
3041   if (col == NULL) {
3042     m_impl.m_error.code = 4318;
3043     return NULL;
3044   }
3045   return getBlobTable(table, col->getColumnNo());
3046 }
3047 
3048 const NdbDictionary::Table *
getBlobTable(const NdbDictionary::Table * table,Uint32 col_no)3049 NdbDictionary::Dictionary::getBlobTable(const NdbDictionary::Table* table,
3050                                         Uint32 col_no)
3051 {
3052   return m_impl.getBlobTable(NdbTableImpl::getImpl(*table), col_no);
3053 }
3054 
3055 void
invalidateTable(const char * name)3056 NdbDictionary::Dictionary::invalidateTable(const char * name){
3057   DBUG_ENTER("NdbDictionaryImpl::invalidateTable");
3058   NdbTableImpl * t = m_impl.getTable(name);
3059   if(t)
3060     m_impl.invalidateObject(* t);
3061   DBUG_VOID_RETURN;
3062 }
3063 
3064 void
invalidateTable(const Table * table)3065 NdbDictionary::Dictionary::invalidateTable(const Table *table){
3066   NdbTableImpl &t = NdbTableImpl::getImpl(*table);
3067   m_impl.invalidateObject(t);
3068 }
3069 
3070 void
removeCachedTable(const char * name)3071 NdbDictionary::Dictionary::removeCachedTable(const char * name){
3072   NdbTableImpl * t = m_impl.getTable(name);
3073   if(t)
3074     m_impl.removeCachedObject(* t);
3075 }
3076 
3077 void
removeCachedTable(const Table * table)3078 NdbDictionary::Dictionary::removeCachedTable(const Table *table){
3079   NdbTableImpl &t = NdbTableImpl::getImpl(*table);
3080   m_impl.removeCachedObject(t);
3081 }
3082 
3083 int
createIndex(const Index & ind,bool offline)3084 NdbDictionary::Dictionary::createIndex(const Index & ind, bool offline)
3085 {
3086   int ret;
3087   DO_TRANS(
3088     ret,
3089     m_impl.createIndex(NdbIndexImpl::getImpl(ind), offline)
3090   );
3091   return ret;
3092 }
3093 
3094 int
createIndex(const Index & ind,const Table & tab,bool offline)3095 NdbDictionary::Dictionary::createIndex(const Index & ind, const Table & tab,
3096                                        bool offline)
3097 {
3098   int ret;
3099   DO_TRANS(
3100     ret,
3101     m_impl.createIndex(NdbIndexImpl::getImpl(ind),
3102                        NdbTableImpl::getImpl(tab),
3103 		       offline)
3104   );
3105   return ret;
3106 }
3107 
3108 int
dropIndex(const char * indexName,const char * tableName)3109 NdbDictionary::Dictionary::dropIndex(const char * indexName,
3110 				     const char * tableName)
3111 {
3112   int ret;
3113   DO_TRANS(
3114     ret,
3115     m_impl.dropIndex(indexName, tableName)
3116   );
3117   return ret;
3118 }
3119 
3120 int
dropIndexGlobal(const Index & ind)3121 NdbDictionary::Dictionary::dropIndexGlobal(const Index &ind)
3122 {
3123   int ret;
3124   DO_TRANS(
3125     ret,
3126     m_impl.dropIndexGlobal(NdbIndexImpl::getImpl(ind))
3127   );
3128   return ret;
3129 }
3130 
3131 int
updateIndexStat(const Index & index,const Table & table)3132 NdbDictionary::Dictionary::updateIndexStat(const Index& index,
3133                                            const Table& table)
3134 {
3135   int ret;
3136   DO_TRANS(
3137     ret,
3138     m_impl.updateIndexStat(NdbIndexImpl::getImpl(index),
3139                            NdbTableImpl::getImpl(table))
3140   );
3141   return ret;
3142 }
3143 
3144 int
updateIndexStat(Uint32 indexId,Uint32 indexVersion,Uint32 tableId)3145 NdbDictionary::Dictionary::updateIndexStat(Uint32 indexId,
3146                                            Uint32 indexVersion,
3147                                            Uint32 tableId)
3148 {
3149   int ret;
3150   DO_TRANS(
3151     ret,
3152     m_impl.updateIndexStat(indexId,
3153                            indexVersion,
3154                            tableId)
3155   );
3156   return ret;
3157 }
3158 
3159 int
deleteIndexStat(const Index & index,const Table & table)3160 NdbDictionary::Dictionary::deleteIndexStat(const Index& index,
3161                                            const Table& table)
3162 {
3163   int ret;
3164   DO_TRANS(
3165     ret,
3166     m_impl.deleteIndexStat(NdbIndexImpl::getImpl(index),
3167                            NdbTableImpl::getImpl(table))
3168   );
3169   return ret;
3170 }
3171 
3172 int
deleteIndexStat(Uint32 indexId,Uint32 indexVersion,Uint32 tableId)3173 NdbDictionary::Dictionary::deleteIndexStat(Uint32 indexId,
3174                                            Uint32 indexVersion,
3175                                            Uint32 tableId)
3176 {
3177   int ret;
3178   DO_TRANS(
3179     ret,
3180     m_impl.deleteIndexStat(indexId,
3181                            indexVersion,
3182                            tableId)
3183   );
3184   return ret;
3185 }
3186 
3187 const NdbDictionary::Index *
getIndex(const char * indexName,const char * tableName) const3188 NdbDictionary::Dictionary::getIndex(const char * indexName,
3189 				    const char * tableName) const
3190 {
3191   NdbIndexImpl * i = m_impl.getIndex(indexName, tableName);
3192   if(i)
3193     return i->m_facade;
3194   return 0;
3195 }
3196 
3197 const NdbDictionary::Index *
getIndex(const char * indexName,const NdbDictionary::Table & base) const3198 NdbDictionary::Dictionary::getIndex(const char * indexName,
3199                                     const NdbDictionary::Table& base) const
3200 {
3201   NdbIndexImpl * i = m_impl.getIndex(indexName, NdbTableImpl::getImpl(base));
3202   if (i)
3203     return i->m_facade;
3204   return 0;
3205 }
3206 
3207 void
invalidateIndex(const Index * index)3208 NdbDictionary::Dictionary::invalidateIndex(const Index *index){
3209   DBUG_ENTER("NdbDictionary::Dictionary::invalidateIndex");
3210   NdbIndexImpl &i = NdbIndexImpl::getImpl(*index);
3211   assert(i.m_table != 0);
3212   m_impl.invalidateObject(* i.m_table);
3213   DBUG_VOID_RETURN;
3214 }
3215 
3216 void
invalidateIndex(const char * indexName,const char * tableName)3217 NdbDictionary::Dictionary::invalidateIndex(const char * indexName,
3218                                            const char * tableName){
3219   DBUG_ENTER("NdbDictionaryImpl::invalidateIndex");
3220   NdbIndexImpl * i = m_impl.getIndex(indexName, tableName);
3221   if(i) {
3222     assert(i->m_table != 0);
3223     m_impl.invalidateObject(* i->m_table);
3224   }
3225   DBUG_VOID_RETURN;
3226 }
3227 
3228 int
forceGCPWait()3229 NdbDictionary::Dictionary::forceGCPWait()
3230 {
3231   return forceGCPWait(0);
3232 }
3233 
3234 int
forceGCPWait(int type)3235 NdbDictionary::Dictionary::forceGCPWait(int type)
3236 {
3237   return m_impl.forceGCPWait(type);
3238 }
3239 
3240 int
getRestartGCI(Uint32 * gci)3241 NdbDictionary::Dictionary::getRestartGCI(Uint32 * gci)
3242 {
3243   return m_impl.getRestartGCI(gci);
3244 }
3245 
3246 void
removeCachedIndex(const Index * index)3247 NdbDictionary::Dictionary::removeCachedIndex(const Index *index){
3248   DBUG_ENTER("NdbDictionary::Dictionary::removeCachedIndex");
3249   NdbIndexImpl &i = NdbIndexImpl::getImpl(*index);
3250   assert(i.m_table != 0);
3251   m_impl.removeCachedObject(* i.m_table);
3252   DBUG_VOID_RETURN;
3253 }
3254 
3255 void
removeCachedIndex(const char * indexName,const char * tableName)3256 NdbDictionary::Dictionary::removeCachedIndex(const char * indexName,
3257 					     const char * tableName){
3258   NdbIndexImpl * i = m_impl.getIndex(indexName, tableName);
3259   if(i) {
3260     assert(i->m_table != 0);
3261     m_impl.removeCachedObject(* i->m_table);
3262   }
3263 }
3264 
3265 const NdbDictionary::Table *
getIndexTable(const char * indexName,const char * tableName) const3266 NdbDictionary::Dictionary::getIndexTable(const char * indexName,
3267 					 const char * tableName) const
3268 {
3269   NdbIndexImpl * i = m_impl.getIndex(indexName, tableName);
3270   NdbTableImpl * t = m_impl.getTable(tableName);
3271   if(i && t) {
3272     NdbTableImpl * it = m_impl.getIndexTable(i, t);
3273     return it->m_facade;
3274   }
3275   return 0;
3276 }
3277 
3278 
3279 int
createEvent(const Event & ev)3280 NdbDictionary::Dictionary::createEvent(const Event & ev)
3281 {
3282   return m_impl.createEvent(NdbEventImpl::getImpl(ev));
3283 }
3284 
3285 int
dropEvent(const char * eventName,int force)3286 NdbDictionary::Dictionary::dropEvent(const char * eventName, int force)
3287 {
3288   return m_impl.dropEvent(eventName, force);
3289 }
3290 
3291 const NdbDictionary::Event *
getEvent(const char * eventName)3292 NdbDictionary::Dictionary::getEvent(const char * eventName)
3293 {
3294   NdbEventImpl * t = m_impl.getEvent(eventName);
3295   if(t)
3296     return t->m_facade;
3297   return 0;
3298 }
3299 
3300 int
listEvents(List & list)3301 NdbDictionary::Dictionary::listEvents(List& list)
3302 {
3303   // delegate to overloaded const function for same semantics
3304   const NdbDictionary::Dictionary * const cthis = this;
3305   return cthis->NdbDictionary::Dictionary::listEvents(list);
3306 }
3307 
3308 int
listEvents(List & list) const3309 NdbDictionary::Dictionary::listEvents(List& list) const
3310 {
3311   return m_impl.listEvents(list);
3312 }
3313 
3314 int
listObjects(List & list,Object::Type type)3315 NdbDictionary::Dictionary::listObjects(List& list, Object::Type type)
3316 {
3317   // delegate to overloaded const function for same semantics
3318   const NdbDictionary::Dictionary * const cthis = this;
3319   return cthis->NdbDictionary::Dictionary::listObjects(list, type);
3320 }
3321 
3322 int
listObjects(List & list,Object::Type type) const3323 NdbDictionary::Dictionary::listObjects(List& list, Object::Type type) const
3324 {
3325   // delegate to variant with FQ names param
3326   return listObjects(list, type,
3327                      m_impl.m_ndb.usingFullyQualifiedNames());
3328 }
3329 
3330 int
listObjects(List & list,Object::Type type,bool fullyQualified) const3331 NdbDictionary::Dictionary::listObjects(List& list, Object::Type type,
3332                                        bool fullyQualified) const
3333 {
3334   return m_impl.listObjects(list, type,
3335                             fullyQualified);
3336 }
3337 
3338 int
listIndexes(List & list,const char * tableName)3339 NdbDictionary::Dictionary::listIndexes(List& list, const char * tableName)
3340 {
3341   // delegate to overloaded const function for same semantics
3342   const NdbDictionary::Dictionary * const cthis = this;
3343   return cthis->NdbDictionary::Dictionary::listIndexes(list, tableName);
3344 }
3345 
3346 int
listIndexes(List & list,const char * tableName) const3347 NdbDictionary::Dictionary::listIndexes(List& list,
3348                                       const char * tableName) const
3349 {
3350   // delegate to overloaded function with FQ names param
3351   return listIndexes(list, tableName, m_impl.m_ndb.usingFullyQualifiedNames());
3352 }
3353 
3354 int
listIndexes(List & list,const char * tableName,bool fullyQualified) const3355 NdbDictionary::Dictionary::listIndexes(List& list,
3356 				       const char * tableName, bool fullyQualified) const
3357 {
3358   const NdbDictionary::Table* tab= getTable(tableName);
3359   if(tab == 0)
3360   {
3361     return -1;
3362   }
3363   return m_impl.listIndexes(list, tab->getTableId(), fullyQualified);
3364 }
3365 
3366 int
listIndexes(List & list,const NdbDictionary::Table & table) const3367 NdbDictionary::Dictionary::listIndexes(List& list,
3368 				       const NdbDictionary::Table &table) const
3369 {
3370   return m_impl.listIndexes(list, table.getTableId(),
3371                             m_impl.m_ndb.usingFullyQualifiedNames());
3372 }
3373 
3374 int
listDependentObjects(List & list,const NdbDictionary::Table & tab) const3375 NdbDictionary::Dictionary::listDependentObjects(List& list,
3376                                                 const NdbDictionary::Table&tab)
3377   const
3378 {
3379   return m_impl.listDependentObjects(list, tab.getTableId());
3380 }
3381 
3382 const struct NdbError &
getNdbError() const3383 NdbDictionary::Dictionary::getNdbError() const {
3384   return m_impl.getNdbError();
3385 }
3386 
3387 int
getWarningFlags() const3388 NdbDictionary::Dictionary::getWarningFlags() const
3389 {
3390   return m_impl.m_warn;
3391 }
3392 
3393 // printers
3394 
3395 static
3396 void
pretty_print_string(NdbOut & out,const NdbDictionary::NdbDataPrintFormat & f,const char * type,bool is_binary,const void * aref,unsigned sz)3397 pretty_print_string(NdbOut& out,
3398                     const NdbDictionary::NdbDataPrintFormat &f,
3399                     const char *type, bool is_binary,
3400                     const void *aref, unsigned sz)
3401 {
3402   const unsigned char* ref = (const unsigned char*)aref;
3403   int i, len, printable= 1;
3404 
3405   if (is_binary && f.hex_format)
3406   {
3407     if (sz == 0)
3408     {
3409       out.print("0x0");
3410       return;
3411     }
3412     out.print("0x");
3413     for (len = 0; len < (int)sz; len++)
3414       out.print("%02X", (int)ref[len]);
3415     return;
3416   }
3417 
3418   // trailing zeroes are not printed
3419   for (i=sz-1; i >= 0; i--)
3420     if (ref[i] == 0) sz--;
3421     else break;
3422   if (!is_binary)
3423   {
3424     // trailing spaces are not printed
3425     for (i=sz-1; i >= 0; i--)
3426       if (ref[i] == 32) sz--;
3427       else break;
3428   }
3429   if (sz == 0) return; // empty
3430 
3431   // NOTE! This for loop both checks printable and counts length
3432   for (len=0; len < (int)sz && ref[i] != 0; len++)
3433   {
3434     if (printable && !isprint((int)ref[i]))
3435       printable= 0;
3436   }
3437 
3438   if (printable)
3439     out.print("%.*s", len, ref);
3440   else
3441   {
3442     out.print("0x");
3443     for (i=0; i < len; i++)
3444       out.print("%02X", (int)ref[i]);
3445   }
3446   if (len != (int)sz)
3447   {
3448     out.print("[");
3449     for (i= len+1; ref[i] != 0; i++)
3450     out.print("%u]",len-i);
3451     assert((int)sz > i);
3452     pretty_print_string(out,f,type,is_binary,ref+i,sz-i);
3453   }
3454 }
3455 
3456 /* Three MySQL defs duplicated here : */
3457 static const int MaxMySQLDecimalPrecision= 65;
3458 static const int MaxMySQLDecimalScale= 30;
3459 static const int DigitsPerDigit_t= 9; // (Decimal digits in 2^32)
3460 
3461 /* Implications */
3462 /* Space for -, . and \0 */
3463 static const int MaxDecimalStrLen= MaxMySQLDecimalPrecision + 3;
3464 static const int IntPartDigit_ts=
3465   ((MaxMySQLDecimalPrecision -
3466     MaxMySQLDecimalScale) +
3467    DigitsPerDigit_t -1) / DigitsPerDigit_t;
3468 static const int FracPartDigit_ts=
3469   (MaxMySQLDecimalScale +
3470    DigitsPerDigit_t - 1) / DigitsPerDigit_t;
3471 static const int DigitArraySize= IntPartDigit_ts + FracPartDigit_ts;
3472 
3473 NdbOut&
printFormattedValue(NdbOut & out,const NdbDataPrintFormat & format,const NdbDictionary::Column * c,const void * val)3474 NdbDictionary::printFormattedValue(NdbOut& out,
3475                                    const NdbDataPrintFormat& format,
3476                                    const NdbDictionary::Column* c,
3477                                    const void* val)
3478 {
3479   if (val == NULL)
3480   {
3481     out << format.null_string;
3482     return out;
3483   }
3484 
3485   const unsigned char* val_p= (const unsigned char*) val;
3486 
3487   uint length = c->getLength();
3488   Uint32 j;
3489   {
3490     const char *fields_optionally_enclosed_by;
3491     if (format.fields_enclosed_by[0] == '\0')
3492       fields_optionally_enclosed_by=
3493         format.fields_optionally_enclosed_by;
3494     else
3495       fields_optionally_enclosed_by= "";
3496     out << format.fields_enclosed_by;
3497 
3498     switch(c->getType()){
3499     case NdbDictionary::Column::Bigunsigned:
3500     {
3501       Uint64 temp;
3502       memcpy(&temp, val, 8);
3503       out << temp;
3504       break;
3505     }
3506     case NdbDictionary::Column::Bit:
3507     {
3508       out << format.hex_prefix << "0x";
3509       {
3510         const Uint32 *buf = (const Uint32 *)val;
3511         unsigned int k = (length+31)/32;
3512         const unsigned int sigbits= length & 31;
3513         Uint32 wordMask= (1 << sigbits) -1;
3514 
3515         /* Skip leading all-0 words */
3516         while (k > 0)
3517         {
3518           const Uint32 v= buf[--k] & wordMask;
3519           if (v != 0)
3520             break;
3521           /* Following words have all bits significant */
3522           wordMask= ~0;
3523         }
3524 
3525         /* Write first sig word with non-zero bits */
3526         out.print("%X", (buf[k] & wordMask));
3527 
3528         /* Write remaining words (less significant) */
3529         while (k > 0)
3530           out.print("%.8X", buf[--k]);
3531       }
3532       break;
3533     }
3534     case NdbDictionary::Column::Unsigned:
3535     {
3536       if (length > 1)
3537         out << format.start_array_enclosure;
3538       out << *(const Uint32*)val;
3539       for (j = 1; j < length; j++)
3540         out << " " << *(((const Uint32*)val) + j);
3541       if (length > 1)
3542         out << format.end_array_enclosure;
3543       break;
3544     }
3545     case NdbDictionary::Column::Mediumunsigned:
3546       out << (static_cast<Uint32>(uint3korr(val_p)));
3547       break;
3548     case NdbDictionary::Column::Smallunsigned:
3549       out << *((const Uint16*) val);
3550       break;
3551     case NdbDictionary::Column::Tinyunsigned:
3552       out << *((const Uint8*) val);
3553       break;
3554     case NdbDictionary::Column::Bigint:
3555     {
3556       Int64 temp;
3557       memcpy(&temp, val, 8);
3558       out << temp;
3559       break;
3560     }
3561     case NdbDictionary::Column::Int:
3562       out << *((Int32*)val);
3563       break;
3564     case NdbDictionary::Column::Mediumint:
3565       out << sint3korr(val_p);
3566       break;
3567     case NdbDictionary::Column::Smallint:
3568       out << *((const short*) val);
3569       break;
3570     case NdbDictionary::Column::Tinyint:
3571       out << *((Int8*) val);
3572       break;
3573     case NdbDictionary::Column::Binary:
3574       if (!format.hex_format)
3575         out << fields_optionally_enclosed_by;
3576       j = c->getLength();
3577       pretty_print_string(out,format,"Binary", true, val, j);
3578       if (!format.hex_format)
3579         out << fields_optionally_enclosed_by;
3580       break;
3581     case NdbDictionary::Column::Char:
3582       out << fields_optionally_enclosed_by;
3583       j = c->getLength();
3584       pretty_print_string(out,format,"Char", false, val, j);
3585       out << fields_optionally_enclosed_by;
3586       break;
3587     case NdbDictionary::Column::Varchar:
3588     {
3589       out << fields_optionally_enclosed_by;
3590       unsigned len = *val_p;
3591       pretty_print_string(out,format,"Varchar", false, val_p+1,len);
3592       j = length;
3593       out << fields_optionally_enclosed_by;
3594     }
3595     break;
3596     case NdbDictionary::Column::Varbinary:
3597     {
3598       if (!format.hex_format)
3599         out << fields_optionally_enclosed_by;
3600       unsigned len = *val_p;
3601       pretty_print_string(out,format,"Varbinary", true, val_p+1,len);
3602       j = length;
3603       if (!format.hex_format)
3604         out << fields_optionally_enclosed_by;
3605     }
3606     break;
3607     case NdbDictionary::Column::Float:
3608     {
3609       float temp;
3610       memcpy(&temp, val, sizeof(temp));
3611       out << temp;
3612       break;
3613     }
3614     case NdbDictionary::Column::Double:
3615     {
3616       double temp;
3617       memcpy(&temp, val, sizeof(temp));
3618       out << temp;
3619       break;
3620     }
3621     case NdbDictionary::Column::Olddecimal:
3622     {
3623       short len = 1 + c->getPrecision() + (c->getScale() > 0);
3624       out.print("%.*s", len, val_p);
3625     }
3626     break;
3627     case NdbDictionary::Column::Olddecimalunsigned:
3628     {
3629       short len = 0 + c->getPrecision() + (c->getScale() > 0);
3630       out.print("%.*s", len, val_p);
3631     }
3632     break;
3633     case NdbDictionary::Column::Decimal:
3634     case NdbDictionary::Column::Decimalunsigned:
3635     {
3636       int precision= c->getPrecision();
3637       int scale= c->getScale();
3638 
3639       assert(precision <= MaxMySQLDecimalPrecision);
3640       assert(scale <= MaxMySQLDecimalScale);
3641       assert(decimal_size(precision, scale) <= DigitArraySize );
3642       decimal_digit_t buff[ DigitArraySize ];
3643       decimal_t tmpDec;
3644       tmpDec.buf= buff;
3645       tmpDec.len= DigitArraySize;
3646       decimal_make_zero(&tmpDec);
3647       int rc;
3648 
3649       const uchar* data= (const uchar*) val_p;
3650       if ((rc= bin2decimal(data, &tmpDec, precision, scale)))
3651       {
3652         out.print("***Error : Bad bin2decimal conversion %d ***",
3653                   rc);
3654         break;
3655       }
3656 
3657       /* Get null terminated var-length string representation */
3658       char decStr[MaxDecimalStrLen];
3659       assert(decimal_string_size(&tmpDec) <= MaxDecimalStrLen);
3660       int len= MaxDecimalStrLen;
3661       if ((rc= decimal2string(&tmpDec, decStr, &len)))
3662       {
3663         out.print("***Error : bad decimal2string conversion %d ***",
3664                   rc);
3665         break;
3666       }
3667 
3668       out.print("%s", decStr);
3669 
3670       break;
3671     }
3672     case NdbDictionary::Column::Datetime:
3673     {
3674       NdbSqlUtil::Datetime s;
3675       NdbSqlUtil::unpack_datetime(s, val_p);
3676       out.print("%04d-%02d-%02d", s.year, s.month, s.day);
3677       out.print("/%02d:%02d:%02d", s.hour, s.minute, s.second);
3678     }
3679     break;
3680     case NdbDictionary::Column::Date:
3681     {
3682       NdbSqlUtil::Date s;
3683       NdbSqlUtil::unpack_date(s, val_p);
3684       out.print("%04d-%02d-%02d", s.year, s.month, s.day);
3685     }
3686     break;
3687     case NdbDictionary::Column::Time:
3688     {
3689       NdbSqlUtil::Time s;
3690       NdbSqlUtil::unpack_time(s, val_p);
3691       const char* sign = (s.sign ? "" : "-");
3692       out.print("%s%02u:%02u:%02u", sign, s.hour, s.minute, s.second);
3693     }
3694     break;
3695     case NdbDictionary::Column::Year:
3696     {
3697       NdbSqlUtil::Year s;
3698       NdbSqlUtil::unpack_year(s, val_p);
3699       out.print("%04d", s.year);
3700     }
3701     break;
3702     case NdbDictionary::Column::Timestamp:
3703     {
3704       NdbSqlUtil::Timestamp s;
3705       NdbSqlUtil::unpack_timestamp(s, val_p);
3706       out.print("%u", s.second);
3707     }
3708     break;
3709     case NdbDictionary::Column::Blob:
3710     case NdbDictionary::Column::Text:
3711     {
3712       NdbBlob::Head head;
3713       NdbBlob::unpackBlobHead(head, (const char*) val_p, c->getBlobVersion());
3714       out << head.length << ":";
3715       const unsigned char* p = val_p + head.headsize;
3716       unsigned n = c->getInlineSize();
3717       for (unsigned k = 0; k < n && k < head.length; k++) {
3718         if (c->getType() == NdbDictionary::Column::Blob)
3719           out.print("%02X", (int)p[k]);
3720         else
3721           out.print("%c", (int)p[k]);
3722       }
3723       j = length;
3724     }
3725     break;
3726     case NdbDictionary::Column::Longvarchar:
3727     {
3728       out << fields_optionally_enclosed_by;
3729       unsigned len = uint2korr(val_p);
3730       pretty_print_string(out,format,"Longvarchar", false,
3731                           val_p+2,len);
3732       j = length;
3733       out << fields_optionally_enclosed_by;
3734     }
3735     break;
3736     case NdbDictionary::Column::Longvarbinary:
3737     {
3738       if (!format.hex_format)
3739         out << fields_optionally_enclosed_by;
3740       unsigned len = uint2korr(val_p);
3741       pretty_print_string(out,format,"Longvarbinary", true,
3742                           val_p+2,len);
3743       j = length;
3744       if (!format.hex_format)
3745         out << fields_optionally_enclosed_by;
3746     }
3747     break;
3748     // fractional time types, see wl#946
3749     case NdbDictionary::Column::Time2:
3750     {
3751       uint prec = c->getPrecision();
3752       assert(prec <= 6);
3753       NdbSqlUtil::Time2 s;
3754       NdbSqlUtil::unpack_time2(s, val_p, prec);
3755       const char* sign = (s.sign ? "" : "-");
3756       out.print("%s%02d:%02d:%02d", sign, s.hour, s.minute, s.second);
3757       if (prec != 0)
3758         out.print(".%0*d", prec, s.fraction);
3759     }
3760     break;
3761     case NdbDictionary::Column::Datetime2:
3762     {
3763       uint prec = c->getPrecision();
3764       assert(prec <= 6);
3765       NdbSqlUtil::Datetime2 s;
3766       NdbSqlUtil::unpack_datetime2(s, val_p, prec);
3767       out.print("%04d-%02d-%02d", s.year, s.month, s.day);
3768       out.print("/%02d:%02d:%02d", s.hour, s.minute, s.second);
3769       if (prec != 0)
3770         out.print(".%0*d", prec, s.fraction);
3771     }
3772     break;
3773     case NdbDictionary::Column::Timestamp2:
3774     {
3775       uint prec = c->getPrecision();
3776       assert(prec <= 6);
3777       NdbSqlUtil::Timestamp2 s;
3778       NdbSqlUtil::unpack_timestamp2(s, val_p, prec);
3779       out.print("%u", s.second);
3780       if (prec != 0)
3781         out.print(".%0*d", prec, s.fraction);
3782     }
3783     break;
3784 
3785     default: /* no print functions for the rest, just print type */
3786       out << "Unable to format type ("
3787           << (int) c->getType()
3788           << ")";
3789       if (length > 1)
3790         out << " " << length << " times";
3791       break;
3792     }
3793     out << format.fields_enclosed_by;
3794   }
3795 
3796   return out;
3797 }
3798 
NdbDataPrintFormat()3799 NdbDictionary::NdbDataPrintFormat::NdbDataPrintFormat()
3800 {
3801   fields_terminated_by= ";";
3802   start_array_enclosure= "[";
3803   end_array_enclosure= "]";
3804   fields_enclosed_by= "";
3805   fields_optionally_enclosed_by= "\"";
3806   lines_terminated_by= "\n";
3807   hex_prefix= "H'";
3808   null_string= "[NULL]";
3809   hex_format= 0;
3810 }
~NdbDataPrintFormat()3811 NdbDictionary::NdbDataPrintFormat::~NdbDataPrintFormat() {}
3812 
3813 
3814 NdbOut&
operator <<(NdbOut & out,const NdbDictionary::Column & col)3815 operator<<(NdbOut& out, const NdbDictionary::Column& col)
3816 {
3817   const CHARSET_INFO *cs = col.getCharset();
3818   const char *csname = cs ? cs->name : "?";
3819   out << col.getName() << " ";
3820   switch (col.getType()) {
3821   case NdbDictionary::Column::Tinyint:
3822     out << "Tinyint";
3823     break;
3824   case NdbDictionary::Column::Tinyunsigned:
3825     out << "Tinyunsigned";
3826     break;
3827   case NdbDictionary::Column::Smallint:
3828     out << "Smallint";
3829     break;
3830   case NdbDictionary::Column::Smallunsigned:
3831     out << "Smallunsigned";
3832     break;
3833   case NdbDictionary::Column::Mediumint:
3834     out << "Mediumint";
3835     break;
3836   case NdbDictionary::Column::Mediumunsigned:
3837     out << "Mediumunsigned";
3838     break;
3839   case NdbDictionary::Column::Int:
3840     out << "Int";
3841     break;
3842   case NdbDictionary::Column::Unsigned:
3843     out << "Unsigned";
3844     break;
3845   case NdbDictionary::Column::Bigint:
3846     out << "Bigint";
3847     break;
3848   case NdbDictionary::Column::Bigunsigned:
3849     out << "Bigunsigned";
3850     break;
3851   case NdbDictionary::Column::Float:
3852     out << "Float";
3853     break;
3854   case NdbDictionary::Column::Double:
3855     out << "Double";
3856     break;
3857   case NdbDictionary::Column::Olddecimal:
3858     out << "Olddecimal(" << col.getPrecision() << "," << col.getScale() << ")";
3859     break;
3860   case NdbDictionary::Column::Olddecimalunsigned:
3861     out << "Olddecimalunsigned(" << col.getPrecision() << "," << col.getScale() << ")";
3862     break;
3863   case NdbDictionary::Column::Decimal:
3864     out << "Decimal(" << col.getPrecision() << "," << col.getScale() << ")";
3865     break;
3866   case NdbDictionary::Column::Decimalunsigned:
3867     out << "Decimalunsigned(" << col.getPrecision() << "," << col.getScale() << ")";
3868     break;
3869   case NdbDictionary::Column::Char:
3870     out << "Char(" << col.getLength() << ";" << csname << ")";
3871     break;
3872   case NdbDictionary::Column::Varchar:
3873     out << "Varchar(" << col.getLength() << ";" << csname << ")";
3874     break;
3875   case NdbDictionary::Column::Binary:
3876     out << "Binary(" << col.getLength() << ")";
3877     break;
3878   case NdbDictionary::Column::Varbinary:
3879     out << "Varbinary(" << col.getLength() << ")";
3880     break;
3881   case NdbDictionary::Column::Datetime:
3882     out << "Datetime";
3883     break;
3884   case NdbDictionary::Column::Date:
3885     out << "Date";
3886     break;
3887   case NdbDictionary::Column::Blob:
3888     out << "Blob(" << col.getInlineSize() << "," << col.getPartSize()
3889         << "," << col.getStripeSize() << ")";
3890     break;
3891   case NdbDictionary::Column::Text:
3892     out << "Text(" << col.getInlineSize() << "," << col.getPartSize()
3893         << "," << col.getStripeSize() << ";" << csname << ")";
3894     break;
3895   case NdbDictionary::Column::Time:
3896     out << "Time";
3897     break;
3898   case NdbDictionary::Column::Year:
3899     out << "Year";
3900     break;
3901   case NdbDictionary::Column::Timestamp:
3902     out << "Timestamp";
3903     break;
3904   case NdbDictionary::Column::Undefined:
3905     out << "Undefined";
3906     break;
3907   case NdbDictionary::Column::Bit:
3908     out << "Bit(" << col.getLength() << ")";
3909     break;
3910   case NdbDictionary::Column::Longvarchar:
3911     out << "Longvarchar(" << col.getLength() << ";" << csname << ")";
3912     break;
3913   case NdbDictionary::Column::Longvarbinary:
3914     out << "Longvarbinary(" << col.getLength() << ")";
3915     break;
3916   case NdbDictionary::Column::Datetime2:
3917     out << "Datetime2(" << col.getPrecision() << ")";
3918     break;
3919   case NdbDictionary::Column::Time2:
3920     out << "Time2(" << col.getPrecision() << ")";
3921     break;
3922   case NdbDictionary::Column::Timestamp2:
3923     out << "Timestamp2(" << col.getPrecision() << ")";
3924     break;
3925   default:
3926     out << "Type" << (Uint32)col.getType();
3927     break;
3928   }
3929   // show unusual (non-MySQL) array size
3930   if (col.getLength() != 1) {
3931     switch (col.getType()) {
3932     case NdbDictionary::Column::Char:
3933     case NdbDictionary::Column::Varchar:
3934     case NdbDictionary::Column::Binary:
3935     case NdbDictionary::Column::Varbinary:
3936     case NdbDictionary::Column::Blob:
3937     case NdbDictionary::Column::Text:
3938     case NdbDictionary::Column::Bit:
3939     case NdbDictionary::Column::Longvarchar:
3940     case NdbDictionary::Column::Longvarbinary:
3941       break;
3942     default:
3943       out << " [" << col.getLength() << "]";
3944       break;
3945     }
3946   }
3947 
3948   if (col.getPrimaryKey())
3949     out << " PRIMARY KEY";
3950   else if (! col.getNullable())
3951     out << " NOT NULL";
3952   else
3953     out << " NULL";
3954 
3955   if(col.getDistributionKey())
3956     out << " DISTRIBUTION KEY";
3957 
3958   switch (col.getArrayType()) {
3959   case NDB_ARRAYTYPE_FIXED:
3960     out << " AT=FIXED";
3961     break;
3962   case NDB_ARRAYTYPE_SHORT_VAR:
3963     out << " AT=SHORT_VAR";
3964     break;
3965   case NDB_ARRAYTYPE_MEDIUM_VAR:
3966     out << " AT=MEDIUM_VAR";
3967     break;
3968   default:
3969     out << " AT=" << (int)col.getArrayType() << "?";
3970     break;
3971   }
3972 
3973   switch (col.getStorageType()) {
3974   case NDB_STORAGETYPE_MEMORY:
3975     out << " ST=MEMORY";
3976     break;
3977   case NDB_STORAGETYPE_DISK:
3978     out << " ST=DISK";
3979     break;
3980   default:
3981     out << " ST=" << (int)col.getStorageType() << "?";
3982     break;
3983   }
3984 
3985   if (col.getAutoIncrement())
3986     out << " AUTO_INCR";
3987 
3988   switch (col.getType()) {
3989   case NdbDictionary::Column::Blob:
3990   case NdbDictionary::Column::Text:
3991     out << " BV=" << col.getBlobVersion();
3992     out << " BT=" << ((col.getBlobTable() != 0) ? col.getBlobTable()->getName() : "<none>");
3993     break;
3994   default:
3995     break;
3996   }
3997 
3998   if(col.getDynamic())
3999     out << " DYNAMIC";
4000 
4001   const void *default_data = col.getDefaultValue();
4002 
4003   if (default_data != NULL)
4004   {
4005     NdbDictionary::NdbDataPrintFormat f;
4006 
4007     /* Display binary field defaults as hex */
4008     f.hex_format = 1;
4009 
4010     out << " DEFAULT ";
4011 
4012     NdbDictionary::printFormattedValue(out,
4013                                        f,
4014                                        &col,
4015                                        default_data);
4016   }
4017 
4018   return out;
4019 }
4020 
4021 int
createLogfileGroup(const LogfileGroup & lg,ObjectId * obj)4022 NdbDictionary::Dictionary::createLogfileGroup(const LogfileGroup & lg,
4023 					      ObjectId * obj)
4024 {
4025   int ret;
4026   DO_TRANS(ret,
4027            m_impl.createLogfileGroup(NdbLogfileGroupImpl::getImpl(lg),
4028                                      obj ?
4029                                      & NdbDictObjectImpl::getImpl(* obj) : 0));
4030   return ret;
4031 }
4032 
4033 int
dropLogfileGroup(const LogfileGroup & lg)4034 NdbDictionary::Dictionary::dropLogfileGroup(const LogfileGroup & lg)
4035 {
4036   int ret;
4037   DO_TRANS(ret,
4038            m_impl.dropLogfileGroup(NdbLogfileGroupImpl::getImpl(lg)));
4039   return ret;
4040 }
4041 
4042 NdbDictionary::LogfileGroup
getLogfileGroup(const char * name)4043 NdbDictionary::Dictionary::getLogfileGroup(const char * name)
4044 {
4045   NdbDictionary::LogfileGroup tmp;
4046   m_impl.m_receiver.get_filegroup(NdbLogfileGroupImpl::getImpl(tmp),
4047 				  NdbDictionary::Object::LogfileGroup, name);
4048   return tmp;
4049 }
4050 
4051 int
createTablespace(const Tablespace & lg,ObjectId * obj)4052 NdbDictionary::Dictionary::createTablespace(const Tablespace & lg,
4053 					    ObjectId * obj)
4054 {
4055   int ret;
4056   DO_TRANS(ret,
4057            m_impl.createTablespace(NdbTablespaceImpl::getImpl(lg),
4058                                    obj ?
4059                                    & NdbDictObjectImpl::getImpl(* obj) : 0));
4060   return ret;
4061 }
4062 
4063 int
dropTablespace(const Tablespace & lg)4064 NdbDictionary::Dictionary::dropTablespace(const Tablespace & lg)
4065 {
4066   int ret;
4067   DO_TRANS(ret,
4068            m_impl.dropTablespace(NdbTablespaceImpl::getImpl(lg)));
4069   return ret;
4070 }
4071 
4072 NdbDictionary::Tablespace
getTablespace(const char * name)4073 NdbDictionary::Dictionary::getTablespace(const char * name)
4074 {
4075   NdbDictionary::Tablespace tmp;
4076   m_impl.m_receiver.get_filegroup(NdbTablespaceImpl::getImpl(tmp),
4077 				  NdbDictionary::Object::Tablespace, name);
4078   return tmp;
4079 }
4080 
4081 NdbDictionary::Tablespace
getTablespace(Uint32 tablespaceId)4082 NdbDictionary::Dictionary::getTablespace(Uint32 tablespaceId)
4083 {
4084   NdbDictionary::Tablespace tmp;
4085   m_impl.m_receiver.get_filegroup(NdbTablespaceImpl::getImpl(tmp),
4086 				  NdbDictionary::Object::Tablespace,
4087                                   tablespaceId);
4088   return tmp;
4089 }
4090 
4091 int
createDatafile(const Datafile & df,bool force,ObjectId * obj)4092 NdbDictionary::Dictionary::createDatafile(const Datafile & df,
4093 					  bool force,
4094 					  ObjectId * obj)
4095 {
4096   int ret;
4097   DO_TRANS(ret,
4098            m_impl.createDatafile(NdbDatafileImpl::getImpl(df),
4099                                  force,
4100                                  obj ? & NdbDictObjectImpl::getImpl(* obj): 0));
4101   return ret;
4102 }
4103 
4104 int
dropDatafile(const Datafile & df)4105 NdbDictionary::Dictionary::dropDatafile(const Datafile& df)
4106 {
4107   int ret;
4108   DO_TRANS(ret,
4109            m_impl.dropDatafile(NdbDatafileImpl::getImpl(df)));
4110   return ret;
4111 }
4112 
4113 NdbDictionary::Datafile
getDatafile(Uint32 node,const char * path)4114 NdbDictionary::Dictionary::getDatafile(Uint32 node, const char * path)
4115 {
4116   NdbDictionary::Datafile tmp;
4117   m_impl.m_receiver.get_file(NdbDatafileImpl::getImpl(tmp),
4118 			     NdbDictionary::Object::Datafile,
4119 			     node ? (int)node : -1, path);
4120   return tmp;
4121 }
4122 
4123 int
createUndofile(const Undofile & df,bool force,ObjectId * obj)4124 NdbDictionary::Dictionary::createUndofile(const Undofile & df,
4125 					  bool force,
4126 					  ObjectId * obj)
4127 {
4128   int ret;
4129   DO_TRANS(ret,
4130            m_impl.createUndofile(NdbUndofileImpl::getImpl(df),
4131                                  force,
4132                                  obj ? & NdbDictObjectImpl::getImpl(* obj): 0));
4133   return ret;
4134 }
4135 
4136 int
dropUndofile(const Undofile & df)4137 NdbDictionary::Dictionary::dropUndofile(const Undofile& df)
4138 {
4139   int ret;
4140   DO_TRANS(ret,
4141            m_impl.dropUndofile(NdbUndofileImpl::getImpl(df)));
4142   return ret;
4143 }
4144 
4145 NdbDictionary::Undofile
getUndofile(Uint32 node,const char * path)4146 NdbDictionary::Dictionary::getUndofile(Uint32 node, const char * path)
4147 {
4148   NdbDictionary::Undofile tmp;
4149   m_impl.m_receiver.get_file(NdbUndofileImpl::getImpl(tmp),
4150 			     NdbDictionary::Object::Undofile,
4151 			     node ? (int)node : -1, path);
4152   return tmp;
4153 }
4154 
4155 void
invalidateDbGlobal(const char * name)4156 NdbDictionary::Dictionary::invalidateDbGlobal(const char * name)
4157 {
4158   if (m_impl.m_globalHash && name != 0)
4159   {
4160     size_t len = strlen(name);
4161     m_impl.m_globalHash->lock();
4162     m_impl.m_globalHash->invalidateDb(name, len);
4163     m_impl.m_globalHash->unlock();
4164   }
4165 }
4166 
4167 int
beginSchemaTrans()4168 NdbDictionary::Dictionary::beginSchemaTrans()
4169 {
4170   return m_impl.beginSchemaTrans();
4171 }
4172 
4173 int
endSchemaTrans(Uint32 flags)4174 NdbDictionary::Dictionary::endSchemaTrans(Uint32 flags)
4175 {
4176   return m_impl.endSchemaTrans(flags);
4177 }
4178 
4179 bool
hasSchemaTrans() const4180 NdbDictionary::Dictionary::hasSchemaTrans() const
4181 {
4182   return m_impl.hasSchemaTrans();
4183 }
4184 
4185 int
createHashMap(const HashMap & map,ObjectId * dst)4186 NdbDictionary::Dictionary::createHashMap(const HashMap& map, ObjectId * dst)
4187 {
4188   ObjectId tmp;
4189   if (dst == 0)
4190     dst = &tmp;
4191 
4192   int ret;
4193   DO_TRANS(ret,
4194            m_impl.m_receiver.create_hashmap(NdbHashMapImpl::getImpl(map),
4195                                             &NdbDictObjectImpl::getImpl(*dst),
4196                                             0,
4197                      NdbDictionary::Object::PartitionBalance_ForRPByLDM));
4198   return ret;
4199 }
4200 
4201 int
createForeignKey(const ForeignKey & fk,ObjectId * dst,int flags)4202 NdbDictionary::Dictionary::createForeignKey(const ForeignKey& fk,
4203                                             ObjectId * dst,
4204                                             int flags)
4205 {
4206   ObjectId tmp;
4207   if (dst == 0)
4208     dst = &tmp;
4209 
4210   if (fk.getParentIndex() == 0 // primary key
4211       && fk.getOnUpdateAction() == NdbDictionary::ForeignKey::Cascade)
4212   {
4213     m_impl.m_error.code = 21000;
4214     return -1;
4215   }
4216 
4217   int ret;
4218   int implFlags = 0;
4219   if (flags & CreateFK_NoVerify)
4220   {
4221     implFlags |= DictSignal::RF_NO_BUILD;
4222   }
4223 
4224   DO_TRANS(ret,
4225            m_impl.m_receiver.create_fk(NdbForeignKeyImpl::getImpl(fk),
4226                                        &NdbDictObjectImpl::getImpl(*dst),
4227                                        implFlags));
4228   return ret;
4229 }
4230 
4231 int
getForeignKey(ForeignKey & fk,const char * name)4232 NdbDictionary::Dictionary::getForeignKey(ForeignKey& fk,
4233                                          const char * name)
4234 {
4235   return m_impl.m_receiver.get_fk(NdbForeignKeyImpl::getImpl(fk), name);
4236 }
4237 
4238 int
dropForeignKey(const ForeignKey & fk)4239 NdbDictionary::Dictionary::dropForeignKey(const ForeignKey& fk)
4240 {
4241   int ret;
4242   DO_TRANS(ret,
4243            m_impl.m_receiver.drop_fk(NdbForeignKeyImpl::getImpl(fk)));
4244   return ret;
4245 }
4246 
4247 int
compareById(const void * p,const void * q)4248 NdbDictionary::Dictionary::List::Element::compareById(const void * p, const void * q)
4249 {
4250   const Element* x = static_cast<const Element*>(p);
4251   const Element* y = static_cast<const Element*>(q);
4252   int cmp = (x->id < y->id) ? -1 : (x->id > y->id) ? + 1 : 0;
4253   if (cmp != 0)
4254     return cmp;
4255   /**
4256    * Trigger object can have same id as the other schema objects.
4257    * Use type to give a stable ordering between trigger object and other
4258    * objects.
4259    */
4260   cmp = (x->type < y->type) ? -1 : (x->type > y->type) ? + 1 : 0;
4261   return cmp;
4262 }
4263 
4264 int
compareByName(const void * p,const void * q)4265 NdbDictionary::Dictionary::List::Element::compareByName(const void * p, const void * q)
4266 {
4267   const Element* x = static_cast<const Element*>(p);
4268   const Element* y = static_cast<const Element*>(q);
4269   int cmp = strcmp(x->database, y->database);
4270   if (cmp != 0)
4271     return cmp;
4272   cmp = strcmp(x->schema, y->schema);
4273   if (cmp != 0)
4274     return cmp;
4275   cmp = strcmp(x->name, y->name);
4276   return cmp;
4277 }
4278 
4279 void
sortById()4280 NdbDictionary::Dictionary::List::sortById()
4281 {
4282   qsort(elements, count, sizeof(Element), Element::compareById);
4283 }
4284 
4285 void
sortByName()4286 NdbDictionary::Dictionary::List::sortByName()
4287 {
4288   qsort(elements, count, sizeof(Element), Element::compareByName);
4289 }
4290 
operator <<(NdbOut & ndbout,NdbDictionary::Object::FragmentType const fragtype)4291 NdbOut& operator <<(NdbOut& ndbout, NdbDictionary::Object::FragmentType const fragtype)
4292 {
4293   switch (fragtype)
4294   {
4295   case NdbDictionary::Object::FragUndefined:
4296     ndbout << "FragUndefined";
4297     break;
4298   case NdbDictionary::Object::FragSingle:
4299     ndbout << "FragSingle";
4300     break;
4301   case NdbDictionary::Object::FragAllSmall:
4302     ndbout << "FragAllSmall";
4303     break;
4304   case NdbDictionary::Object::FragAllMedium:
4305     ndbout << "FragAllMedium";
4306     break;
4307   case NdbDictionary::Object::FragAllLarge:
4308     ndbout << "FragAllLarge";
4309     break;
4310   case NdbDictionary::Object::DistrKeyHash:
4311     ndbout << "DistrKeyHash";
4312     break;
4313   case NdbDictionary::Object::DistrKeyLin:
4314     ndbout << "DistrKeyLin";
4315     break;
4316   case NdbDictionary::Object::UserDefined:
4317     ndbout << "UserDefined";
4318     break;
4319   case NdbDictionary::Object::HashMapPartition:
4320     ndbout << "HashMapPartition";
4321     break;
4322   default:
4323     ndbout << "Unknown(" << (unsigned) fragtype << ")";
4324   }
4325   return ndbout;
4326 }
4327 
operator <<(NdbOut & ndbout,NdbDictionary::Object::Type const type)4328 NdbOut& operator <<(NdbOut& ndbout, NdbDictionary::Object::Type const type)
4329 {
4330   switch (type)
4331   {
4332   case NdbDictionary::Object::TypeUndefined:
4333     ndbout << "Undefined";
4334     break;
4335   case NdbDictionary::Object::SystemTable:
4336     ndbout << "SystemTable";
4337     break;
4338   case NdbDictionary::Object::UserTable:
4339     ndbout << "UserTable";
4340     break;
4341   case NdbDictionary::Object::UniqueHashIndex:
4342     ndbout << "UniqueHashIndex";
4343     break;
4344   case NdbDictionary::Object::OrderedIndex:
4345     ndbout << "OrderedIndex";
4346     break;
4347   case NdbDictionary::Object::HashIndexTrigger:
4348     ndbout << "HashIndexTrigger";
4349     break;
4350   case NdbDictionary::Object::IndexTrigger:
4351     ndbout << "IndexTrigger";
4352     break;
4353   case NdbDictionary::Object::SubscriptionTrigger:
4354     ndbout << "SubscriptionTrigger";
4355     break;
4356   case NdbDictionary::Object::ReadOnlyConstraint:
4357     ndbout << "ReadOnlyConstraint";
4358     break;
4359   case NdbDictionary::Object::TableEvent:
4360     ndbout << "TableEvent";
4361     break;
4362   case NdbDictionary::Object::Tablespace:
4363     ndbout << "Tablespace";
4364     break;
4365   case NdbDictionary::Object::LogfileGroup:
4366     ndbout << "LogfileGroup";
4367     break;
4368   case NdbDictionary::Object::Datafile:
4369     ndbout << "Datafile";
4370     break;
4371   case NdbDictionary::Object::Undofile:
4372     ndbout << "Undofile";
4373     break;
4374   case NdbDictionary::Object::ReorgTrigger:
4375     ndbout << "ReorgTrigger";
4376     break;
4377   case NdbDictionary::Object::FullyReplicatedTrigger:
4378     ndbout << "FullyReplicatedTrigger";
4379     break;
4380   case NdbDictionary::Object::HashMap:
4381     ndbout << "HashMap";
4382     break;
4383   case NdbDictionary::Object::ForeignKey:
4384     ndbout << "ForeignKey";
4385     break;
4386   case NdbDictionary::Object::FKParentTrigger:
4387     ndbout << "FKParentTrigger";
4388     break;
4389   case NdbDictionary::Object::FKChildTrigger:
4390     ndbout << "FKChildTrigger";
4391     break;
4392   default:
4393     ndbout << "Type " << (unsigned) type;
4394   }
4395   return ndbout;
4396 }
4397 
operator <<(NdbOut & ndbout,NdbDictionary::Index::Type const type)4398 NdbOut& operator <<(NdbOut& ndbout, NdbDictionary::Index::Type const type)
4399 {
4400   switch (type)
4401   {
4402   case NdbDictionary::Index::Undefined:
4403     ndbout << "Undefined";
4404     break;
4405   case NdbDictionary::Index::UniqueHashIndex:
4406     ndbout << "UniqueHashIndex";
4407     break;
4408   case NdbDictionary::Index::OrderedIndex:
4409     ndbout << "OrderedIndex";
4410     break;
4411   default:
4412     ndbout << "Type " << (unsigned) type;
4413   }
4414   return ndbout;
4415 }
4416 
operator <<(NdbOut & ndbout,NdbDictionary::Object::Status const status)4417 NdbOut& operator <<(NdbOut& ndbout, NdbDictionary::Object::Status const status)
4418 {
4419   switch (status)
4420   {
4421   case NdbDictionary::Object::New:
4422     ndbout << "New";
4423     break;
4424   case NdbDictionary::Object::Changed:
4425     ndbout << "Changed";
4426     break;
4427   case NdbDictionary::Object::Retrieved:
4428     ndbout << "Retrieved";
4429     break;
4430   case NdbDictionary::Object::Invalid:
4431     ndbout << "Invalid";
4432     break;
4433   case NdbDictionary::Object::Altered:
4434     ndbout << "Altered";
4435     break;
4436   default:
4437     ndbout << "Undefined(" << (unsigned) status << ")";
4438   }
4439   return ndbout;
4440 }
4441 
operator <<(NdbOut & ndbout,NdbDictionary::Index const & idx)4442 NdbOut& operator <<(NdbOut& ndbout, NdbDictionary::Index const& idx)
4443 {
4444   ndbout << "Version: " << idx.getObjectVersion() << endl;
4445   ndbout << "Base table: " << idx.getTable() << endl;
4446   ndbout << "Number of attributes: " << idx.getNoOfColumns() << endl;
4447   ndbout << "Logging: " << idx.getLogging() << endl;
4448   ndbout << "Index type: " << idx.getType() << endl;
4449   ndbout << "Index status: " << idx.getObjectStatus() << endl;
4450 
4451   return ndbout;
4452 }
4453 
print(NdbOut & ndbout,NdbDictionary::Index const & idx)4454 void NdbDictionary::Dictionary::print(NdbOut& ndbout, NdbDictionary::Index const& idx)
4455 {
4456   ndbout << idx;
4457 
4458   ndbout << "-- Attributes --" << endl;
4459   for (unsigned col = 0; col < idx.getNoOfColumns() ; col++)
4460   {
4461     ndbout << *idx.getColumn(col) << endl;
4462   }
4463 
4464   Table const& indexTable = *NdbIndexImpl::getImpl(idx).getIndexTable();
4465   ndbout << "-- IndexTable " << indexTable.getName() << " --" << endl;
4466 
4467   print(ndbout, indexTable);
4468 }
4469 
operator <<(class NdbOut &,NdbDictionary::Table const & tab)4470 NdbOut& operator <<(class NdbOut&, NdbDictionary::Table const& tab)
4471 {
4472   ndbout << "Version: " <<  tab.getObjectVersion() << endl;
4473   ndbout << "Fragment type: " <<  tab.getFragmentType() << endl;
4474   ndbout << "K Value: " <<  tab.getKValue()<< endl;
4475   ndbout << "Min load factor: " <<  tab.getMinLoadFactor()<< endl;
4476   ndbout << "Max load factor: " <<  tab.getMaxLoadFactor()<< endl;
4477   ndbout << "Temporary table: " <<  (tab.getStoredTable() ? "no" : "yes") << endl;
4478   ndbout << "Number of attributes: " <<  tab.getNoOfColumns() << endl;
4479   ndbout << "Number of primary keys: " <<  tab.getNoOfPrimaryKeys() << endl;
4480   ndbout << "Length of frm data: " << tab.getFrmLength() << endl;
4481   ndbout << "Max Rows: " << tab.getMaxRows() << endl;
4482   ndbout << "Row Checksum: " << tab.getRowChecksumIndicator() << endl;
4483   ndbout << "Row GCI: " << tab.getRowGCIIndicator() << endl;
4484   ndbout << "SingleUserMode: " << (Uint32) tab.getSingleUserMode() << endl;
4485   ndbout << "ForceVarPart: " << tab.getForceVarPart() << endl;
4486   ndbout << "PartitionCount: " << tab.getPartitionCount() << endl;
4487   ndbout << "FragmentCount: " << tab.getFragmentCount() << endl;
4488   ndbout << "PartitionBalance: " << tab.getPartitionBalanceString() << endl;
4489   ndbout << "ExtraRowGciBits: " << tab.getExtraRowGciBits() << endl;
4490   ndbout << "ExtraRowAuthorBits: " << tab.getExtraRowAuthorBits() << endl;
4491   ndbout << "TableStatus: " << tab.getObjectStatus() << endl;
4492 
4493   ndbout << "Table options:";
4494   bool first = true;
4495   if (NdbTableImpl::getImpl(tab).m_read_backup) {
4496     if (!first)
4497       ndbout << ", ";
4498     else
4499       ndbout << " ";
4500     ndbout << "readbackup";
4501     first = false;
4502   }
4503   if (tab.getFullyReplicated())
4504   {
4505     if (!first)
4506       ndbout << ", ";
4507     ndbout << "fullyreplicated";
4508     first = false;
4509   }
4510   ndbout << endl;
4511   return ndbout;
4512 }
4513 
4514 NdbOut&
print_fk_tab_ref(NdbOut & ndbout,const char * fqn)4515 print_fk_tab_ref(NdbOut& ndbout, const char * fqn)
4516 {
4517   int cnt_slash = 0;
4518   {
4519     const char * ptr = fqn;
4520     while ((ptr = strchr(ptr, '/')) != 0)
4521     {
4522       ptr++;
4523       cnt_slash++;
4524     }
4525   }
4526 
4527   if (cnt_slash == 2) // expected...
4528   {
4529     for (; * fqn != '/' ; fqn++)
4530       ndbout.print("%c", (* fqn));
4531     ndbout << ".";
4532 
4533     for (fqn++ ; * fqn != '/' ; fqn++)
4534     {
4535       /**
4536        * catalog...
4537        */
4538     }
4539     for (fqn++ ; * fqn != 0; fqn++)
4540     {
4541       ndbout.print("%c", (* fqn));
4542     }
4543   }
4544   else
4545   {
4546     ndbout << fqn;
4547   }
4548   return ndbout;
4549 }
4550 
4551 NdbOut&
print_fk_idx_ref(NdbOut & ndbout,const char * fqn)4552 print_fk_idx_ref(NdbOut& ndbout, const char * fqn)
4553 {
4554   if (fqn == 0)
4555   {
4556     ndbout << "PRIMARY KEY";
4557   }
4558   else
4559   {
4560     const char * ptr = strrchr(fqn, '/');
4561     if (ptr)
4562     {
4563       ndbout << (ptr + 1);
4564     }
4565   }
4566   return ndbout;
4567 }
4568 
print(NdbOut & ndbout,NdbDictionary::Table const & tab)4569 void NdbDictionary::Dictionary::print(NdbOut& ndbout, NdbDictionary::Table const& tab)
4570 {
4571   ndbout << tab;
4572 
4573   HashMap hashmap;
4574   if (getHashMap(hashmap, &tab) != -1)
4575   {
4576     ndbout << "HashMap: " << hashmap.getName() << endl;
4577   }
4578 
4579   Uint32 tablespace_id;
4580   if (tab.getTablespace(&tablespace_id))
4581   {
4582     ndbout << "Tablespace id: " << tablespace_id << endl;
4583 
4584     // Look up tablespace by id and show the name
4585     // NOTE! The tablespace name of a table object which
4586     // has been fetched from NDB is not assigned any value.
4587     const NdbDictionary::Tablespace ts = getTablespace(tablespace_id);
4588     if (getNdbError().code == 0)
4589     {
4590       ndbout << "Tablespace: " << ts.getName() << endl;
4591     }
4592   }
4593 
4594   ndbout << "-- Attributes --" << endl;
4595   for (int col = 0; col < tab.getNoOfColumns() ; col++)
4596   {
4597     ndbout << *tab.getColumn(col) << endl;
4598   }
4599 
4600   ndbout << "-- Indexes -- " << endl;
4601   ndbout << "PRIMARY KEY(";
4602   unsigned j;
4603   for (j= 0; (int)j < tab.getNoOfPrimaryKeys(); j++)
4604   {
4605     const Column * col= tab.getColumn(tab.getPrimaryKey(j));
4606     ndbout << col->getName();
4607     if ((int)j < tab.getNoOfPrimaryKeys()-1)
4608       ndbout << ", ";
4609   }
4610   ndbout << ") - UniqueHashIndex" << endl;
4611 
4612   List list;
4613   if (listDependentObjects(list, tab) == 0)
4614   {
4615     list.sortById();
4616     for (j= 0; j < list.count; j++) {
4617       List::Element& elt = list.elements[j];
4618       if (elt.type != NdbDictionary::Object::UniqueHashIndex &&
4619           elt.type != NdbDictionary::Object::OrderedIndex)
4620         continue;
4621 
4622       const Index *pIdx = getIndex(elt.name, tab);
4623       if (!pIdx)
4624       {
4625 #ifdef VM_TRACE
4626         assert(false);
4627 #endif
4628         continue;
4629       }
4630 
4631       ndbout << pIdx->getName();
4632       ndbout << "(";
4633       unsigned noOfAttributes = pIdx->getNoOfColumns();
4634       for (unsigned i = 0; i < noOfAttributes; i++)
4635       {
4636         const Column *col = pIdx->getColumn(i);
4637         ndbout << col->getName();
4638         if (i < noOfAttributes - 1)
4639           ndbout << ", ";
4640       }
4641       ndbout << ")";
4642       ndbout << " - " << pIdx->getType();
4643       ndbout << endl;
4644     }
4645   }
4646 #ifdef VM_TRACE
4647   else assert(false);
4648 #endif
4649 
4650   bool first = true;
4651   for (j= 0; j < list.count; j++)
4652   {
4653     List::Element& elt = list.elements[j];
4654     if (elt.type != NdbDictionary::Object::ForeignKey)
4655       continue;
4656 
4657     NdbDictionary::ForeignKey fk;
4658     if (getForeignKey(fk, elt.name) == 0)
4659     {
4660       if (strcmp(fk.getChildTable(),
4661                  NdbTableImpl::getImpl(tab).m_internalName.c_str()) == 0)
4662       {
4663         if (first)
4664         {
4665           first = false;
4666           ndbout << "-- ForeignKeys --" << endl;
4667         }
4668 
4669         ndbout << fk.getName() << " ";
4670         print_fk_idx_ref(ndbout, fk.getChildIndex());
4671         ndbout << " (";
4672         for (unsigned i = 0; i < fk.getChildColumnCount(); i++)
4673         {
4674           ndbout << tab.getColumn(fk.getChildColumnNo(i))->getName();
4675           if (i + 1 != fk.getChildColumnCount())
4676             ndbout << ", ";
4677         }
4678         ndbout << ") REFERENCES ";
4679         print_fk_tab_ref(ndbout, fk.getParentTable());
4680         ndbout << "/";
4681         print_fk_idx_ref(ndbout, fk.getParentIndex());
4682         ndbout << " (";
4683         /**
4684          * TODO...
4685          */
4686         ndbout << ") ";
4687 
4688         ndbout << "on update ";
4689         switch(fk.getOnUpdateAction()) {
4690         case NdbDictionary::ForeignKey::NoAction:
4691           ndbout << "noaction";
4692           break;
4693         case NdbDictionary::ForeignKey::Restrict:
4694           ndbout << "restrict";
4695           break;
4696         case NdbDictionary::ForeignKey::Cascade:
4697           ndbout << "cascade";
4698           break;
4699         case NdbDictionary::ForeignKey::SetNull:
4700           ndbout << "set null";
4701           break;
4702         case NdbDictionary::ForeignKey::SetDefault:
4703           ndbout << "set default";
4704           break;
4705         }
4706 
4707         ndbout << " on delete ";
4708         switch(fk.getOnDeleteAction()) {
4709         case NdbDictionary::ForeignKey::NoAction:
4710           ndbout << "noaction";
4711           break;
4712         case NdbDictionary::ForeignKey::Restrict:
4713           ndbout << "restrict";
4714           break;
4715         case NdbDictionary::ForeignKey::Cascade:
4716           ndbout << "cascade";
4717           break;
4718         case NdbDictionary::ForeignKey::SetNull:
4719           ndbout << "set null";
4720           break;
4721         case NdbDictionary::ForeignKey::SetDefault:
4722           ndbout << "set default";
4723           break;
4724         }
4725 
4726         ndbout << endl;
4727       }
4728     }
4729   }
4730 }
4731