1 /*
2    Copyright (c) 2003, 2010, 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 #ifndef NdbDictionaryImpl_H
26 #define NdbDictionaryImpl_H
27 
28 #include <ndb_types.h>
29 #include <kernel_types.h>
30 #include <NdbError.hpp>
31 #include <BaseString.hpp>
32 #include <Vector.hpp>
33 #include <UtilBuffer.hpp>
34 #include <SimpleProperties.hpp>
35 #include <NdbSqlUtil.hpp>
36 #include <NdbDictionary.hpp>
37 #include <Bitmask.hpp>
38 #include <AttributeList.hpp>
39 #include <Ndb.hpp>
40 #include "DictCache.hpp"
41 #include <signaldata/DictSignal.hpp>
42 
43 class ListTablesReq;
44 
45 bool
46 is_ndb_blob_table(const char* name, Uint32* ptab_id = 0, Uint32* pcol_no = 0);
47 bool
48 is_ndb_blob_table(const class NdbTableImpl* t);
49 
50 extern int ndb_dictionary_is_mysqld;
51 #define ASSERT_NOT_MYSQLD assert(ndb_dictionary_is_mysqld == 0)
52 
53 class NdbDictObjectImpl {
54 public:
55   int m_id;
56   Uint32 m_version;
57   NdbDictionary::Object::Type m_type;
58   NdbDictionary::Object::Status m_status;
59 
60   bool change();
61 
getImpl(NdbDictionary::ObjectId & t)62   static NdbDictObjectImpl & getImpl(NdbDictionary::ObjectId & t) {
63     return t.m_impl;
64   }
getImpl(const NdbDictionary::ObjectId & t)65   static const NdbDictObjectImpl & getImpl(const NdbDictionary::ObjectId & t){
66     return t.m_impl;
67   }
68 
69 protected:
70   friend class NdbDictionary::ObjectId;
71 
NdbDictObjectImpl(NdbDictionary::Object::Type type)72   NdbDictObjectImpl(NdbDictionary::Object::Type type) :
73     m_type(type),
74     m_status(NdbDictionary::Object::New) {
75     m_id = -1;
76   }
77 };
78 
79 /**
80  * Column
81  */
82 class NdbColumnImpl : public NdbDictionary::Column {
83 public:
84   NdbColumnImpl();
85   NdbColumnImpl(NdbDictionary::Column &); // This is not a copy constructor
86   ~NdbColumnImpl();
87   NdbColumnImpl& operator=(const NdbColumnImpl&);
88   void init(Type t = Unsigned);
89 
90   int m_attrId;
91   BaseString m_name;
92   NdbDictionary::Column::Type m_type;
93   int m_precision;
94   int m_scale;
95   int m_length;
96   int m_column_no;
97   CHARSET_INFO * m_cs;          // not const in MySQL
98 
99   bool m_pk;
100   bool m_distributionKey;
101   bool m_nullable;
102   bool m_autoIncrement;
103   Uint64 m_autoIncrementInitialValue;
104   UtilBuffer m_defaultValue;
105   /*
106    * Table holding the blob parts.
107    *
108    * Note that if getPartSize() is 0, there is no parts table, so
109    * m_blobTable==NULL.
110    */
111   NdbTableImpl * m_blobTable;
112 
113   /**
114    * Internal types and sizes, and aggregates
115    */
116   Uint32 m_orgAttrSize;
117   Uint32 m_attrSize;            // element size (size when arraySize==1)
118   Uint32 m_arraySize;           // length or maxlength+1/2 for Var* types
119   Uint32 m_arrayType;           // NDB_ARRAYTYPE_FIXED or _VAR
120   Uint32 m_storageType;         // NDB_STORAGETYPE_MEMORY or _DISK
121                                 // for blob, storage type of NDB$DATA
122   bool m_dynamic;
123 
124   bool m_indexSourced;          // Computed when column defined, or when
125                                 // table schema read.  Not stored in kernel
126 
127   /*
128    * NdbTableImpl: if m_pk, 0-based index of key in m_attrId order
129    * NdbIndexImpl: m_column_no of primary table column
130    */
131   Uint32 m_keyInfoPos;
132   // TODO: use bits in attr desc 2
133   bool getInterpretableType() const ;
134   bool getCharType() const;
135   bool getStringType() const;
136   bool getBlobType() const;
137 
138   int m_blobVersion;            // if blob, NDB_BLOB_V1 or NDB_BLOB_V2
139   int getBlobVersion() const;
140   void setBlobVersion(int blobVersion);
141 
142   /**
143    * Equality/assign
144    */
145   bool equal(const NdbColumnImpl&) const;
146 
147   static NdbColumnImpl & getImpl(NdbDictionary::Column & t);
148   static const NdbColumnImpl & getImpl(const NdbDictionary::Column & t);
149   NdbDictionary::Column * m_facade;
150 
151   static void create_pseudo_columns();
152   static void destory_pseudo_columns();
153   static NdbDictionary::Column * create_pseudo(const char *);
154 
155   // Get total length in bytes, used by NdbOperation
156   bool get_var_length(const void* value, Uint32& len) const;
157 };
158 
159 class NdbTableImpl : public NdbDictionary::Table, public NdbDictObjectImpl {
160 public:
161   NdbTableImpl();
162   NdbTableImpl(NdbDictionary::Table &);
163   ~NdbTableImpl();
164 
165   void init();
166   int setName(const char * name);
167   const char * getName() const;
168   void setFragmentCount(Uint32 count);
169   Uint32 getFragmentCount() const;
170   int setFrm(const void* data, Uint32 len);
171   const void * getFrmData() const;
172   Uint32 getFrmLength() const;
173 
174   int setFragmentData(const Uint32* data, Uint32 cnt);
175   const Uint32 * getFragmentData() const;
176   Uint32 getFragmentDataLen() const;
177 
178   int setRangeListData(const Int32* data, Uint32 cnt);
179   const Int32 * getRangeListData() const;
180   Uint32 getRangeListDataLen() const;
181 
182   Uint32 getFragmentNodes(Uint32 fragmentId,
183                           Uint32* nodeIdArrayPtr,
184                           Uint32 arraySize) const;
185 
186   const char * getMysqlName() const;
187   int updateMysqlName();
188 
189   bool matchDb(const char * name, size_t len) const;
190 
191   int aggregate(NdbError& error);
192   int validate(NdbError& error);
193 
194   Uint32 m_primaryTableId;
195   BaseString m_internalName; // db/schema/table
196   BaseString m_externalName; //           table
197   BaseString m_mysqlName;    //        db/table
198   UtilBuffer m_frm;
199   Vector<Uint32> m_fd;
200   Vector<Int32> m_range;
201   NdbDictionary::Object::FragmentType m_fragmentType;
202 
203   int getDbName(char * buf, size_t len) const;
204   int getSchemaName(char * buf, size_t len) const;
205   void setDbSchema(const char * db, const char * schema);
206 
207   /**
208    *
209    */
210   Uint32 m_columnHashMask;
211   Vector<Uint32> m_columnHash;
212   /*
213     List of all columns in the table.
214     Note that for index table objects, there is one additional column at the
215     end, NDB$TNODE (ordered index) or NDB$PK. This must be taken into account
216     if iterating over columns.
217   */
218   Vector<NdbColumnImpl *> m_columns;
219   Uint32 m_noOfAutoIncColumns;
220   void computeAggregates();
221   int buildColumnHash();
222 
223   /**
224    * Fragment info
225    */
226   Uint32 m_hashValueMask;
227   Uint32 m_hashpointerValue;
228   Vector<Uint16> m_fragments;
229   Vector<Uint8> m_hash_map;
230 
231   Uint64 m_max_rows;
232   Uint64 m_min_rows;
233   Uint32 m_default_no_part_flag;
234   bool m_linear_flag;
235   bool m_logging;
236   bool m_temporary;
237   bool m_row_gci;
238   bool m_row_checksum;
239   bool m_force_var_part;
240   bool m_has_default_values;
241   int m_kvalue;
242   int m_minLoadFactor;
243   int m_maxLoadFactor;
244   Uint16 m_keyLenInWords;
245   Uint16 m_fragmentCount;
246   Uint8 m_single_user_mode;
247   Uint8 m_storageType;  // NDB_STORAGETYPE_MEMORY or _DISK or DEFAULT
248   Uint8 m_extra_row_gci_bits;
249   Uint8 m_extra_row_author_bits;
250 
251   NdbIndexImpl * m_index;
252   NdbColumnImpl * getColumn(unsigned attrId);
253   NdbColumnImpl * getColumn(const char * name);
254   const NdbColumnImpl * getColumn(unsigned attrId) const;
255   const NdbColumnImpl * getColumn(const char * name) const;
256 
257   /**
258    * Index only stuff
259    */
260   BaseString m_primaryTable;    // Name of table indexed by us
261   NdbDictionary::Object::Type m_indexType;
262 
263   /**
264    * Aggregates
265    */
266   Uint8 m_noOfKeys;
267   // if all pk = dk then this is zero!
268   Uint8 m_noOfDistributionKeys;
269   Uint8 m_noOfBlobs;
270   Uint8 m_noOfDiskColumns;
271   Uint8 m_replicaCount;
272 
273   /**
274    * Default NdbRecord for this table or index
275    * Currently used by old-Api scans to use NdbRecord API internally.
276    */
277   NdbRecord *m_ndbrecord;
278 
279   /**
280    * Bitmask describing PK column positions for this table
281    * Currently used by old-Api scans to use NdbRecord API internally.
282    */
283   const unsigned char * m_pkMask;
284 
285   /**
286    * Equality/assign
287    */
288   bool equal(const NdbTableImpl&) const;
289   int assign(const NdbTableImpl&);
290 
291   static NdbTableImpl & getImpl(NdbDictionary::Table & t);
292   static NdbTableImpl & getImpl(const NdbDictionary::Table & t);
293   NdbDictionary::Table * m_facade;
294 
295   /**
296    * Return count
297    */
298   Uint32 get_nodes(Uint32 partitionId, const Uint16** nodes) const ;
299 
300   /**
301    * Disk stuff
302    */
303   BaseString m_tablespace_name;
304   Uint32 m_tablespace_id;
305   Uint32 m_tablespace_version;
306 
307   Uint32 m_hash_map_id;
308   Uint32 m_hash_map_version;
309 };
310 
311 class NdbIndexImpl : public NdbDictionary::Index, public NdbDictObjectImpl {
312 public:
313   NdbIndexImpl();
314   NdbIndexImpl(NdbDictionary::Index &);
315   ~NdbIndexImpl();
316 
317   void init();
318   int setName(const char * name);
319   const char * getName() const;
320   int setTable(const char * table);
321   const char * getTable() const;
322   const NdbTableImpl * getIndexTable() const;
323 
324   BaseString m_internalName;
325   BaseString m_externalName;
326   BaseString m_tableName;
327   Uint32 m_table_id;
328   Uint32 m_table_version;
329   Vector<NdbColumnImpl *> m_columns;
330   Vector<int> m_key_ids;
331 
332   bool m_logging;
333   bool m_temporary;
334 
335   /*
336     The m_table member refers to the NDB table object that holds the actual
337     index, not the table that is indexed by the index (so it is of index
338     type, not table type).
339   */
340   NdbTableImpl * m_table;
341 
342   static NdbIndexImpl & getImpl(NdbDictionary::Index & t);
343   static NdbIndexImpl & getImpl(const NdbDictionary::Index & t);
344   NdbDictionary::Index * m_facade;
345 };
346 
347 class NdbOptimizeTableHandleImpl : public NdbDictionary::OptimizeTableHandle
348 {
349   enum State { CREATED, INITIALIZED, FINISHED, ABORTED, CLOSED };
350 private:
351   int start();
352 
353   State m_state;
354   Ndb *m_ndb;
355   struct fifo_element_st {
fifo_element_stNdbOptimizeTableHandleImpl::fifo_element_st356     fifo_element_st(const NdbTableImpl *tab, fifo_element_st *prev)
357       {
358         table = tab;
359         previous = prev;
360         next = NULL;
361         if (prev)
362           prev->next = this;
363       }
364     const NdbTableImpl * table;
365     fifo_element_st * previous;
366     fifo_element_st * next;
367   };
368   const NdbTableImpl * m_table;
369   fifo_element_st * m_table_queue;
370   fifo_element_st * m_table_queue_first;
371   fifo_element_st * m_table_queue_end;
372   NdbTransaction * m_trans;
373   NdbScanOperation * m_scan_op;
374 
375   NdbDictionary::OptimizeTableHandle * m_facade;
376 public:
377   NdbOptimizeTableHandleImpl(NdbDictionary::OptimizeTableHandle &);
378   ~NdbOptimizeTableHandleImpl();
getImpl(NdbDictionary::OptimizeTableHandle & h)379   static NdbOptimizeTableHandleImpl & getImpl(NdbDictionary::OptimizeTableHandle &h)
380     { return h.m_impl; }
381 
382   int init(Ndb *ndb, const NdbTableImpl &table);
383   int next();
384   int close();
385 };
386 
387 class NdbOptimizeIndexHandleImpl : public NdbDictionary::OptimizeIndexHandle
388 {
389   enum State { CREATED, INITIALIZED, FINISHED, ABORTED, CLOSED };
390 private:
391   State m_state;
392   Ndb *m_ndb;
393   const NdbIndexImpl *m_index;
394   class NdbDictionary::OptimizeTableHandle m_optimize_table_handle;
395   NdbDictionary::OptimizeIndexHandle * m_facade;
396 public:
397   NdbOptimizeIndexHandleImpl(NdbDictionary::OptimizeIndexHandle &);
398   ~NdbOptimizeIndexHandleImpl();
getImpl(NdbDictionary::OptimizeIndexHandle & h)399   static NdbOptimizeIndexHandleImpl & getImpl(NdbDictionary::OptimizeIndexHandle &h)
400     { return h.m_impl; }
401 
402   int init(Ndb *ndb, const NdbIndexImpl &index);
403   int next();
404   int close();
405 };
406 
407 class NdbEventImpl : public NdbDictionary::Event, public NdbDictObjectImpl {
408   friend class NdbDictInterface;
409   friend class NdbDictionaryImpl;
410   friend class NdbEventOperation;
411   friend class NdbEventOperationImpl;
412   friend class NdbEventBuffer;
413   friend class EventBufData_hash;
414   friend class NdbBlob;
415 public:
416   NdbEventImpl();
417   NdbEventImpl(NdbDictionary::Event &);
418   ~NdbEventImpl();
419 
420   void init();
421   int setName(const char * name);
422   const char * getName() const;
423   int setTable(const NdbDictionary::Table& table);
424   const NdbDictionary::Table * getTable() const;
425   int setTable(const char * table);
426   const char * getTableName() const;
427   void addTableEvent(const NdbDictionary::Event::TableEvent t);
428   bool getTableEvent(const NdbDictionary::Event::TableEvent t) const;
429   void setDurability(NdbDictionary::Event::EventDurability d);
430   NdbDictionary::Event::EventDurability  getDurability() const;
431   void setReport(NdbDictionary::Event::EventReport r);
432   NdbDictionary::Event::EventReport  getReport() const;
433   int getNoOfEventColumns() const;
434   const NdbDictionary::Column * getEventColumn(unsigned no) const;
435 
print()436   void print() {
437     ndbout_c("NdbEventImpl: id=%d, key=%d",
438 	     m_eventId,
439 	     m_eventKey);
440   };
441 
442   Uint32 m_eventId;
443   Uint32 m_eventKey;
444   AttributeMask m_attrListBitmask;
445   Uint32 m_table_id;
446   Uint32 m_table_version;
447   BaseString m_name;
448   Uint32 mi_type;
449   NdbDictionary::Event::EventDurability m_dur;
450   NdbDictionary::Event::EventReport m_rep;
451   bool m_mergeEvents;
452 
453   BaseString m_tableName;
454   Vector<NdbColumnImpl *> m_columns;
455   Vector<unsigned> m_attrIds;
456 
457   static NdbEventImpl & getImpl(NdbDictionary::Event & t);
458   static NdbEventImpl & getImpl(const NdbDictionary::Event & t);
459   NdbDictionary::Event * m_facade;
460 private:
461   NdbTableImpl *m_tableImpl;
462   void setTable(NdbTableImpl *tableImpl);
463 };
464 
465 struct NdbFilegroupImpl : public NdbDictObjectImpl {
466   NdbFilegroupImpl(NdbDictionary::Object::Type t);
467 
468   BaseString m_name;
469   NdbDictionary::AutoGrowSpecification m_grow_spec;
470 
471   union {
472     Uint32 m_extent_size;
473     Uint32 m_undo_buffer_size;
474   };
475 
476   BaseString m_logfile_group_name;
477   Uint32 m_logfile_group_id;
478   Uint32 m_logfile_group_version;
479   Uint64 m_undo_free_words;
480 };
481 
482 class NdbTablespaceImpl : public NdbDictionary::Tablespace,
483 			  public NdbFilegroupImpl {
484 public:
485   NdbTablespaceImpl();
486   NdbTablespaceImpl(NdbDictionary::Tablespace &);
487   ~NdbTablespaceImpl();
488 
489   int assign(const NdbTablespaceImpl&);
490 
491   static NdbTablespaceImpl & getImpl(NdbDictionary::Tablespace & t);
492   static const NdbTablespaceImpl & getImpl(const NdbDictionary::Tablespace &);
493   NdbDictionary::Tablespace * m_facade;
494 };
495 
496 class NdbLogfileGroupImpl : public NdbDictionary::LogfileGroup,
497 			    public NdbFilegroupImpl {
498 public:
499   NdbLogfileGroupImpl();
500   NdbLogfileGroupImpl(NdbDictionary::LogfileGroup &);
501   ~NdbLogfileGroupImpl();
502 
503   int assign(const NdbLogfileGroupImpl&);
504 
505   static NdbLogfileGroupImpl & getImpl(NdbDictionary::LogfileGroup & t);
506   static const NdbLogfileGroupImpl& getImpl(const
507 					    NdbDictionary::LogfileGroup&);
508   NdbDictionary::LogfileGroup * m_facade;
509 };
510 
511 struct NdbFileImpl : public NdbDictObjectImpl {
512   NdbFileImpl(NdbDictionary::Object::Type t);
513 
514   Uint64 m_size;
515   Uint64 m_free;
516   BaseString m_path;
517   BaseString m_filegroup_name;
518   Uint32 m_filegroup_id;
519   Uint32 m_filegroup_version;
520 };
521 
522 class NdbDatafileImpl : public NdbDictionary::Datafile, public NdbFileImpl {
523 public:
524   NdbDatafileImpl();
525   NdbDatafileImpl(NdbDictionary::Datafile &);
526   ~NdbDatafileImpl();
527 
528   int assign(const NdbDatafileImpl&);
529 
530   static NdbDatafileImpl & getImpl(NdbDictionary::Datafile & t);
531   static const NdbDatafileImpl & getImpl(const NdbDictionary::Datafile & t);
532   NdbDictionary::Datafile * m_facade;
533 };
534 
535 class NdbUndofileImpl : public NdbDictionary::Undofile, public NdbFileImpl {
536 public:
537   NdbUndofileImpl();
538   NdbUndofileImpl(NdbDictionary::Undofile &);
539   ~NdbUndofileImpl();
540 
541   int assign(const NdbUndofileImpl&);
542 
543   static NdbUndofileImpl & getImpl(NdbDictionary::Undofile & t);
544   static const NdbUndofileImpl & getImpl(const NdbDictionary::Undofile & t);
545   NdbDictionary::Undofile * m_facade;
546 };
547 
548 class NdbHashMapImpl : public NdbDictionary::HashMap, public NdbDictObjectImpl
549 {
550 public:
551   NdbHashMapImpl();
552   NdbHashMapImpl(NdbDictionary::HashMap &);
553   ~NdbHashMapImpl();
554 
555   int assign(const NdbHashMapImpl& src);
556 
557   BaseString m_name;
558   Vector<Uint32> m_map;
559   NdbDictionary::HashMap * m_facade;
560 
getImpl(NdbDictionary::HashMap & t)561   static NdbHashMapImpl & getImpl(NdbDictionary::HashMap & t){
562     return t.m_impl;
563   }
564 
getImpl(const NdbDictionary::HashMap & t)565   static const NdbHashMapImpl & getImpl(const NdbDictionary::HashMap & t){
566     return t.m_impl;
567   }
568 
569 
570 };
571 
572 class NdbDictInterface {
573 public:
574   // one transaction per Dictionary instance is supported
575   struct Tx {
576     // api-side schema op, currently only for alter table
577     struct Op {
578       Uint32 m_gsn;
579       NdbTableImpl* m_impl;
580     };
581     enum State {
582       NotStarted,
583       Started,
584       Committed,
585       Aborted
586     };
587     State m_state;
588     NdbError m_error;
589     Uint32 m_transId;   // API
590     Uint32 m_transKey;  // DICT
591     Vector<Op> m_op;
TxNdbDictInterface::Tx592     Tx() :
593       m_state(NotStarted),
594       m_transId(0),
595       m_transKey(0)
596     {
597       m_error.code = 0;
598     }
transIdNdbDictInterface::Tx599     Uint32 transId() const {
600       return (m_state == Started) ? m_transId : 0;
601     }
transKeyNdbDictInterface::Tx602     Uint32 transKey() const {
603       return (m_state == Started) ? m_transKey : 0;
604     }
requestFlagsNdbDictInterface::Tx605     Uint32 requestFlags() const {
606       Uint32 flags = 0;
607       // not yet supported in DICT
608       return flags;
609     }
610   };
611 
NdbDictInterface(Tx & tx,NdbError & err,int & warn)612   NdbDictInterface(Tx& tx, NdbError& err, int& warn) :
613     m_tx(tx), m_error(err), m_warn(warn) {
614     m_reference = 0;
615     m_masterNodeId = 0;
616     m_impl = 0;
617   }
618   ~NdbDictInterface();
619 
620   bool setTransporter(class Ndb * ndb);
621   class TransporterFacade *getTransporter() const;
622 
623   // To abstract the stuff thats made in all create/drop/lists below
624   int dictSignal(NdbApiSignal* signal, LinearSectionPtr ptr[3], int secs,
625 		 int nodeId, // -1 any, 0 = master, >1 = specified
626 		 Uint32 waitsignaltype,
627 		 int timeout, Uint32 RETRIES,
628 		 const int *errcodes = 0, int temporaryMask = 0);
629 
630   int createTable(class Ndb & ndb, NdbTableImpl &);
631   bool supportedAlterTable(const NdbTableImpl &,
632 			   NdbTableImpl &);
633   int alterTable(class Ndb & ndb, const NdbTableImpl &, NdbTableImpl&, Uint32&);
634   void syncInternalName(Ndb & ndb, NdbTableImpl &impl);
635   int compChangeMask(const NdbTableImpl &old_impl,
636                      const NdbTableImpl &impl,
637                      Uint32 &change_mask);
638   int serializeTableDesc(Ndb & ndb,
639                          NdbTableImpl & impl,
640                          UtilBufferWriter & w);
641   int sendAlterTable(const NdbTableImpl &impl,
642                      Uint32 change_mask,
643                      UtilBufferWriter &w);
644   int sendCreateTable(const NdbTableImpl &impl, UtilBufferWriter &w);
645 
646   int dropTable(const NdbTableImpl &);
647 
648   int createIndex(class Ndb & ndb, const NdbIndexImpl &, const NdbTableImpl &,
649                   bool offline);
650   int dropIndex(const NdbIndexImpl &, const NdbTableImpl &);
651   int doIndexStatReq(class Ndb& ndb,
652                      const NdbIndexImpl&, const NdbTableImpl&,
653                      Uint32 requestType);
654   int doIndexStatReq(class Ndb& ndb,
655                      Uint32 indexId, Uint32 indexVersion, Uint32 tableId,
656                      Uint32 requestType);
657 
658   int createEvent(class Ndb & ndb, NdbEventImpl &, int getFlag);
659   int dropEvent(const NdbEventImpl &);
660   int dropEvent(NdbApiSignal* signal, LinearSectionPtr ptr[3], int noLSP);
661 
662   int executeSubscribeEvent(class Ndb & ndb, NdbEventOperationImpl &, Uint32&);
663   int stopSubscribeEvent(class Ndb & ndb, NdbEventOperationImpl &);
664 
665   int listObjects(NdbDictionary::Dictionary::List& list,
666                   ListTablesReq& ltreq, bool fullyQualifiedNames);
667   int listObjects(NdbApiSignal* signal, bool& listTablesLongSignal);
668 
669   int unpackListTables(NdbDictionary::Dictionary::List& list,
670                        bool fullyQualifiedNames);
671   int unpackOldListTables(NdbDictionary::Dictionary::List& list,
672                           bool fullyQualifiedNames);
673 
674   NdbTableImpl * getTable(int tableId, bool fullyQualifiedNames);
675   NdbTableImpl * getTable(const BaseString& name, bool fullyQualifiedNames);
676   NdbTableImpl * getTable(class NdbApiSignal * signal,
677 			  LinearSectionPtr ptr[3],
678 			  Uint32 noOfSections, bool fullyQualifiedNames);
679 
680   int forceGCPWait(int type);
681   int getRestartGCI(Uint32 *);
682 
683   static int parseTableInfo(NdbTableImpl ** dst,
684 			    const Uint32 * data, Uint32 len,
685 			    bool fullyQualifiedNames,
686                             Uint32 version= 0xFFFFFFFF);
687 
688   static int parseFileInfo(NdbFileImpl &dst,
689 			   const Uint32 * data, Uint32 len);
690 
691   static int parseFilegroupInfo(NdbFilegroupImpl &dst,
692 				const Uint32 * data, Uint32 len);
693 
694   static int parseHashMapInfo(NdbHashMapImpl& dst,
695                               const Uint32 * data, Uint32 len);
696 
697   int create_file(const NdbFileImpl &, const NdbFilegroupImpl&,
698 		  bool overwrite, NdbDictObjectImpl*);
699   int drop_file(const NdbFileImpl &);
700   int create_filegroup(const NdbFilegroupImpl &, NdbDictObjectImpl*);
701   int drop_filegroup(const NdbFilegroupImpl &);
702 
703   int get_filegroup(NdbFilegroupImpl&, NdbDictionary::Object::Type, Uint32);
704   int get_filegroup(NdbFilegroupImpl&,NdbDictionary::Object::Type,const char*);
705   int get_file(NdbFileImpl&, NdbDictionary::Object::Type, int, int);
706   int get_file(NdbFileImpl&, NdbDictionary::Object::Type, int, const char *);
707 
708   static int create_index_obj_from_table(NdbIndexImpl ** dst,
709 					 NdbTableImpl* index_table,
710 					 const NdbTableImpl* primary_table);
711 
712   int create_hashmap(const NdbHashMapImpl&, NdbDictObjectImpl*, Uint32 flags);
713   int get_hashmap(NdbHashMapImpl&, Uint32 id);
714   int get_hashmap(NdbHashMapImpl&, const char * name);
715 
716   int beginSchemaTrans(bool retry711 = true);
717   int endSchemaTrans(Uint32 flags);
718   Tx & m_tx; // shared with NdbDictionaryImpl
719 
720   bool checkAllNodeVersionsMin(Uint32 minNdbVersion) const;
721 
722   const NdbError &getNdbError() const;
723   NdbError & m_error;
724   int & m_warn;
725 private:
726   Uint32 m_reference;
727   Uint32 m_masterNodeId;
728 
729   class NdbImpl * m_impl;
730 
731   friend class Ndb;
732   friend class NdbImpl;
733   friend class NdbDictionaryImpl;
734   static void execSignal(void* dictImpl,
735 			 const class NdbApiSignal* signal,
736 			 const struct LinearSectionPtr ptr[3]);
737 
738   static void execNodeStatus(void* dictImpl, Uint32, Uint32);
739 
740   void execGET_TABINFO_REF(const NdbApiSignal *, const LinearSectionPtr p[3]);
741   void execGET_TABINFO_CONF(const NdbApiSignal *, const LinearSectionPtr p[3]);
742   void execCREATE_TABLE_REF(const NdbApiSignal *, const LinearSectionPtr p[3]);
743   void execCREATE_TABLE_CONF(const NdbApiSignal *, const LinearSectionPtr [3]);
744   void execALTER_TABLE_REF(const NdbApiSignal *, const LinearSectionPtr pr[3]);
745   void execALTER_TABLE_CONF(const NdbApiSignal *, const LinearSectionPtr p[3]);
746 
747   void execCREATE_INDX_REF(const NdbApiSignal *, const LinearSectionPtr pr[3]);
748   void execCREATE_INDX_CONF(const NdbApiSignal *, const LinearSectionPtr p[3]);
749   void execDROP_INDX_REF(const NdbApiSignal *, const LinearSectionPtr ptr[3]);
750   void execDROP_INDX_CONF(const NdbApiSignal *, const LinearSectionPtr ptr[3]);
751 
752   void execINDEX_STAT_CONF(const NdbApiSignal *, const LinearSectionPtr ptr[3]);
753   void execINDEX_STAT_REF(const NdbApiSignal *, const LinearSectionPtr ptr[3]);
754 
755   void execCREATE_EVNT_REF(const NdbApiSignal *, const LinearSectionPtr pr[3]);
756   void execCREATE_EVNT_CONF(const NdbApiSignal *, const LinearSectionPtr p[3]);
757   void execSUB_START_CONF(const NdbApiSignal*, const LinearSectionPtr ptr[3]);
758   void execSUB_START_REF(const NdbApiSignal*, const LinearSectionPtr ptr[3]);
759   void execSUB_STOP_CONF(const NdbApiSignal*, const LinearSectionPtr ptr[3]);
760   void execSUB_STOP_REF(const NdbApiSignal*, const LinearSectionPtr ptr[3]);
761   void execDROP_EVNT_REF(const NdbApiSignal*, const LinearSectionPtr ptr[3]);
762   void execDROP_EVNT_CONF(const NdbApiSignal*, const LinearSectionPtr ptr[3]);
763 
764   void execDROP_TABLE_REF(const NdbApiSignal*, const LinearSectionPtr ptr[3]);
765   void execDROP_TABLE_CONF(const NdbApiSignal*, const LinearSectionPtr ptr[3]);
766   void execOLD_LIST_TABLES_CONF(const NdbApiSignal*,
767 				const LinearSectionPtr ptr[3]);
768   void execLIST_TABLES_CONF(const NdbApiSignal*, const LinearSectionPtr pt[3]);
769 
770   void execCREATE_FILE_REF(const NdbApiSignal*, const LinearSectionPtr ptr[3]);
771   void execCREATE_FILE_CONF(const NdbApiSignal*, const LinearSectionPtr pr[3]);
772 
773   void execCREATE_FILEGROUP_REF(const NdbApiSignal*,
774 				const LinearSectionPtr ptr[3]);
775   void execCREATE_FILEGROUP_CONF(const NdbApiSignal*,
776 				 const LinearSectionPtr ptr[3]);
777 
778   void execDROP_FILE_REF(const NdbApiSignal*, const LinearSectionPtr ptr[3]);
779   void execDROP_FILE_CONF(const NdbApiSignal*, const LinearSectionPtr ptr[3]);
780 
781   void execDROP_FILEGROUP_REF(const NdbApiSignal*, const LinearSectionPtr [3]);
782   void execDROP_FILEGROUP_CONF(const NdbApiSignal*,
783 			       const LinearSectionPtr ptr[3]);
784 
785   void execSCHEMA_TRANS_BEGIN_CONF(const NdbApiSignal*,
786 				   const LinearSectionPtr ptr[3]);
787   void execSCHEMA_TRANS_BEGIN_REF(const NdbApiSignal*,
788 				  const LinearSectionPtr ptr[3]);
789   void execSCHEMA_TRANS_END_CONF(const NdbApiSignal*,
790 				 const LinearSectionPtr ptr[3]);
791   void execSCHEMA_TRANS_END_REF(const NdbApiSignal*,
792 				const LinearSectionPtr ptr[3]);
793   void execSCHEMA_TRANS_END_REP(const NdbApiSignal*, const LinearSectionPtr ptr[3]);
794 
795   void execWAIT_GCP_CONF(const NdbApiSignal*, const LinearSectionPtr ptr[3]);
796   void execWAIT_GCP_REF(const NdbApiSignal*, const LinearSectionPtr ptr[3]);
797 
798   void execCREATE_HASH_MAP_REF(const NdbApiSignal*,
799 			       const LinearSectionPtr ptr[3]);
800   void execCREATE_HASH_MAP_CONF(const NdbApiSignal*,
801 				const LinearSectionPtr ptr[3]);
802 
803   Uint32 m_fragmentId;
804   UtilBuffer m_buffer;
805 
806   Uint32 m_noOfTables;
807   UtilBuffer m_tableData;
808   UtilBuffer m_tableNames;
809 
810   union {
811     struct SubStartConfData {
812       Uint32 m_buckets;
813     } m_sub_start_conf;
814     struct WaitGcpData {
815       Uint32 gci_hi;
816       Uint32 gci_lo;
817     } m_wait_gcp_conf;
818   } m_data;
819 };
820 
821 class NdbDictionaryImpl;
822 class GlobalCacheInitObject
823 {
824 public:
825   const BaseString &m_name;
GlobalCacheInitObject(const BaseString & name)826   GlobalCacheInitObject(const BaseString &name) :
827     m_name(name)
828   {}
~GlobalCacheInitObject()829   virtual ~GlobalCacheInitObject() {}
830   virtual int init(NdbDictionaryImpl *dict, NdbTableImpl &tab) const = 0;
831 };
832 
833 class NdbDictionaryImpl : public NdbDictionary::Dictionary {
834 public:
835   NdbDictionaryImpl(Ndb &ndb);
836   NdbDictionaryImpl(Ndb &ndb, NdbDictionary::Dictionary & f);
837   ~NdbDictionaryImpl();
838 
839   bool setTransporter(class Ndb * ndb, class TransporterFacade * tf);
840   bool setTransporter(class TransporterFacade * tf);
841 
842   int createTable(NdbTableImpl &t, NdbDictObjectImpl &);
843   int optimizeTable(const NdbTableImpl &t,
844                     NdbOptimizeTableHandleImpl &h);
845   int optimizeIndex(const NdbIndexImpl &index,
846                     NdbOptimizeIndexHandleImpl &h);
847   int createBlobTables(const NdbTableImpl& t);
848   bool supportedAlterTable(NdbTableImpl &old_impl, NdbTableImpl &impl);
849   int alterTable(NdbTableImpl &old_impl, NdbTableImpl &impl);
850   int dropTable(const char * name);
851   int dropTable(NdbTableImpl &);
852   int dropBlobTables(NdbTableImpl &);
853   int renameBlobTables(const NdbTableImpl &old_impl, const NdbTableImpl &impl);
854   int invalidateObject(NdbTableImpl &);
855   int removeCachedObject(NdbTableImpl &);
856 
857   int createIndex(NdbIndexImpl &ix, bool offline);
858   int createIndex(NdbIndexImpl &ix, NdbTableImpl & tab, bool offline);
859   int dropIndex(const char * indexName,
860 		const char * tableName);
861   int dropIndex(NdbIndexImpl &, const char * tableName);
862   NdbTableImpl * getIndexTable(NdbIndexImpl * index,
863 			       NdbTableImpl * table);
864 
865   int updateIndexStat(const NdbIndexImpl&, const NdbTableImpl&);
866   int updateIndexStat(Uint32 indexId, Uint32 indexVersion, Uint32 tableId);
867   int deleteIndexStat(const NdbIndexImpl&, const NdbTableImpl&);
868   int deleteIndexStat(Uint32 indexId, Uint32 indexVersion, Uint32 tableId);
869 
870   int createEvent(NdbEventImpl &);
871   int createBlobEvents(NdbEventImpl &);
872   int dropEvent(const char * eventName, int force);
873   int dropEvent(const NdbEventImpl &);
874   int dropBlobEvents(const NdbEventImpl &);
875   int listEvents(List& list);
876 
877   int executeSubscribeEvent(NdbEventOperationImpl &, Uint32 & buckets);
878   int stopSubscribeEvent(NdbEventOperationImpl &);
879 
880   int forceGCPWait(int type);
881   int getRestartGCI(Uint32*);
882 
883   int listObjects(List& list, NdbDictionary::Object::Type type,
884                   bool fullyQualified);
885   int listIndexes(List& list, Uint32 indexId);
886 
887   NdbTableImpl * getTableGlobal(const char * tableName);
888   NdbIndexImpl * getIndexGlobal(const char * indexName,
889                                 NdbTableImpl &ndbtab);
890   NdbIndexImpl * getIndexGlobal(const char * indexName,
891                                 const char * tableName);
892   int alterTableGlobal(NdbTableImpl &orig_impl, NdbTableImpl &impl);
893   int dropTableGlobal(NdbTableImpl &);
894   int dropIndexGlobal(NdbIndexImpl & impl);
895   int releaseTableGlobal(const NdbTableImpl & impl, int invalidate);
896   int releaseIndexGlobal(const NdbIndexImpl & impl, int invalidate);
897 
898   NdbTableImpl * getTable(const char * tableName, void **data= 0);
899   NdbTableImpl * getBlobTable(const NdbTableImpl&, uint col_no);
900   NdbTableImpl * getBlobTable(uint tab_id, uint col_no);
901   void putTable(NdbTableImpl *impl);
902   int getBlobTables(NdbTableImpl &);
903   Ndb_local_table_info*
904     get_local_table_info(const BaseString& internalTableName);
905   NdbIndexImpl * getIndex(const char * indexName,
906 			  const char * tableName);
907   NdbIndexImpl * getIndex(const char * indexName, const NdbTableImpl& prim);
908   NdbEventImpl * getEvent(const char * eventName, NdbTableImpl* = NULL);
909   NdbEventImpl * getBlobEvent(const NdbEventImpl& ev, uint col_no);
910   NdbEventImpl * getEventImpl(const char * internalName);
911 
912   int createDatafile(const NdbDatafileImpl &, bool force, NdbDictObjectImpl*);
913   int dropDatafile(const NdbDatafileImpl &);
914   int createUndofile(const NdbUndofileImpl &, bool force, NdbDictObjectImpl*);
915   int dropUndofile(const NdbUndofileImpl &);
916 
917   int createTablespace(const NdbTablespaceImpl &, NdbDictObjectImpl*);
918   int dropTablespace(const NdbTablespaceImpl &);
919 
920   int createLogfileGroup(const NdbLogfileGroupImpl &, NdbDictObjectImpl*);
921   int dropLogfileGroup(const NdbLogfileGroupImpl &);
922 
923   int beginSchemaTrans(bool retry711 = true);
924   int endSchemaTrans(Uint32 flags);
hasSchemaTrans() const925   bool hasSchemaTrans() const
926     { return (m_tx.m_state == NdbDictInterface::Tx::Started); }
927   NdbDictInterface::Tx m_tx;
928 
929   const NdbError & getNdbError() const;
930   NdbError m_error;
931   int m_warn;
932   Uint32 m_local_table_data_size;
933 
934   LocalDictCache m_localHash;
935   GlobalDictCache * m_globalHash;
936 
937   static NdbDictionaryImpl & getImpl(NdbDictionary::Dictionary & t);
938   static const NdbDictionaryImpl & getImpl(const NdbDictionary::Dictionary &t);
939   NdbDictionary::Dictionary * m_facade;
940   int initialiseColumnData(bool isIndex,
941                            Uint32 flags,
942                            const NdbDictionary::RecordSpecification *recSpec,
943                            Uint32 colNum,
944                            NdbRecord *rec);
945 
946   NdbDictInterface m_receiver;
947   Ndb & m_ndb;
948 
949   NdbIndexImpl* getIndexImpl(const char * externalName,
950                              const BaseString& internalName,
951                              NdbTableImpl &tab,
952                              NdbTableImpl &prim);
953   NdbIndexImpl * getIndexImpl(const char * name,
954                               const BaseString& internalName);
955 
956 
957   int createDefaultNdbRecord(NdbTableImpl* tableOrIndex,
958                              const NdbTableImpl* baseTableForIndex);
959 
960   bool validateRecordSpec(const NdbDictionary::RecordSpecification *recSpec,
961                           Uint32 length,
962                           Uint32 flags);
963 
964   NdbRecord *createRecord(const NdbTableImpl *table,
965                           const NdbDictionary::RecordSpecification *recSpec,
966                           Uint32 length,
967                           Uint32 elemSize,
968                           Uint32 flags,
969                           bool defaultRecord);
970   void releaseRecord_impl(NdbRecord *rec);
971 
972   static NdbDictionary::RecordType
973   getRecordType(const NdbRecord* record);
974   static const char* getRecordTableName(const NdbRecord* record);
975   static const char* getRecordIndexName(const NdbRecord* record);
976   static bool getNextAttrIdFrom(const NdbRecord* record,
977                                 Uint32 startAttrId,
978                                 Uint32& nextAttrId);
979   static bool getOffset(const NdbRecord* record,
980                         Uint32 attrId,
981                         Uint32& offset);
982   static bool getNullBitOffset(const NdbRecord* record,
983                                Uint32 attrId,
984                                Uint32& nullbit_byte_offset,
985                                Uint32& nullbit_bit_in_byte);
986   static const char* getValuePtr(const NdbRecord* record,
987                                  const char* row,
988                                  Uint32 attrId);
989   static char* getValuePtr(const NdbRecord* record,
990                            char* row,
991                            Uint32 attrId);
992   static bool isNull(const NdbRecord* record,
993                      const char* row,
994                      Uint32 attrId);
995   static int setNull(const NdbRecord* record,
996                      char* row,
997                      Uint32 attrId,
998                      bool value);
999   static Uint32 getRecordRowLength(const NdbRecord* record);
1000 
1001   /* Empty NdbRecord column mask for user convenience */
1002   static const Uint32 m_emptyMask[MAXNROFATTRIBUTESINWORDS];
1003 
1004 private:
1005   NdbTableImpl * fetchGlobalTableImplRef(const GlobalCacheInitObject &obj);
1006 };
1007 
1008 inline
1009 NdbEventImpl &
getImpl(const NdbDictionary::Event & t)1010 NdbEventImpl::getImpl(const NdbDictionary::Event & t){
1011   return t.m_impl;
1012 }
1013 
1014 inline
1015 NdbEventImpl &
getImpl(NdbDictionary::Event & t)1016 NdbEventImpl::getImpl(NdbDictionary::Event & t){
1017   return t.m_impl;
1018 }
1019 
1020 inline
1021 NdbColumnImpl &
getImpl(NdbDictionary::Column & t)1022 NdbColumnImpl::getImpl(NdbDictionary::Column & t){
1023   return t.m_impl;
1024 }
1025 
1026 inline
1027 const NdbColumnImpl &
getImpl(const NdbDictionary::Column & t)1028 NdbColumnImpl::getImpl(const NdbDictionary::Column & t){
1029   return t.m_impl;
1030 }
1031 
1032 inline
1033 bool
getInterpretableType() const1034 NdbColumnImpl::getInterpretableType() const {
1035   return (m_type == NdbDictionary::Column::Unsigned ||
1036 	  m_type == NdbDictionary::Column::Bigunsigned);
1037 }
1038 
1039 inline
1040 bool
getCharType() const1041 NdbColumnImpl::getCharType() const {
1042   return (m_type == NdbDictionary::Column::Char ||
1043           m_type == NdbDictionary::Column::Varchar ||
1044           m_type == NdbDictionary::Column::Text ||
1045           m_type == NdbDictionary::Column::Longvarchar);
1046 }
1047 
1048 inline
1049 bool
getStringType() const1050 NdbColumnImpl::getStringType() const {
1051   return (m_type == NdbDictionary::Column::Char ||
1052           m_type == NdbDictionary::Column::Varchar ||
1053           m_type == NdbDictionary::Column::Longvarchar ||
1054           m_type == NdbDictionary::Column::Binary ||
1055           m_type == NdbDictionary::Column::Varbinary ||
1056           m_type == NdbDictionary::Column::Longvarbinary);
1057 }
1058 
1059 inline
1060 bool
getBlobType() const1061 NdbColumnImpl::getBlobType() const {
1062   return (m_type == NdbDictionary::Column::Blob ||
1063 	  m_type == NdbDictionary::Column::Text);
1064 }
1065 
1066 inline
1067 int
getBlobVersion() const1068 NdbColumnImpl::getBlobVersion() const {
1069   return m_blobVersion;
1070 }
1071 
1072 inline
1073 void
setBlobVersion(int blobVersion)1074 NdbColumnImpl::setBlobVersion(int blobVersion) {
1075   if (blobVersion == NDB_BLOB_V1) {
1076     m_arrayType = NDB_ARRAYTYPE_FIXED;
1077   } else if (blobVersion == NDB_BLOB_V2) {
1078     // always 2 length bytes for head+inline
1079     m_arrayType = NDB_ARRAYTYPE_MEDIUM_VAR;
1080   }
1081   // invalid value should be detected at validate
1082   m_blobVersion = blobVersion;
1083 }
1084 
1085 inline
1086 bool
get_var_length(const void * value,Uint32 & len) const1087 NdbColumnImpl::get_var_length(const void* value, Uint32& len) const
1088 {
1089   DBUG_ENTER("NdbColumnImpl::get_var_length");
1090   Uint32 max_len = m_attrSize * m_arraySize;
1091   switch (m_arrayType) {
1092   case NDB_ARRAYTYPE_SHORT_VAR:
1093     len = 1 + *((Uint8*)value);
1094     DBUG_PRINT("info", ("SHORT_VAR: len=%u max_len=%u", len, max_len));
1095     break;
1096   case NDB_ARRAYTYPE_MEDIUM_VAR:
1097     len = 2 + uint2korr((char*)value);
1098     DBUG_PRINT("info", ("MEDIUM_VAR: len=%u max_len=%u", len, max_len));
1099     break;
1100   default:
1101     len = max_len;
1102     DBUG_PRINT("info", ("FIXED: len=%u max_len=%u", len, max_len));
1103     DBUG_RETURN(true);
1104   }
1105   DBUG_RETURN(len <= max_len);
1106 }
1107 
1108 inline
1109 NdbTableImpl &
getImpl(NdbDictionary::Table & t)1110 NdbTableImpl::getImpl(NdbDictionary::Table & t){
1111   return t.m_impl;
1112 }
1113 
1114 inline
1115 NdbTableImpl &
getImpl(const NdbDictionary::Table & t)1116 NdbTableImpl::getImpl(const NdbDictionary::Table & t){
1117   return t.m_impl;
1118 }
1119 
1120 inline
1121 NdbColumnImpl *
getColumn(unsigned attrId)1122 NdbTableImpl::getColumn(unsigned attrId){
1123   if(m_columns.size() > attrId){
1124     return m_columns[attrId];
1125   }
1126   return 0;
1127 }
1128 
1129 inline
1130 const char *
getMysqlName() const1131 NdbTableImpl::getMysqlName() const
1132 {
1133   return m_mysqlName.c_str();
1134 }
1135 
1136 inline
1137 bool
matchDb(const char * name,size_t len) const1138 NdbTableImpl::matchDb(const char * name, size_t len) const
1139 {
1140   return
1141     len < m_internalName.length() &&
1142     memcmp(name, m_internalName.c_str(), len) == 0;
1143 }
1144 
1145 inline
1146 Uint32
Hash(const char * str)1147 Hash( const char* str ){
1148   Uint32 h = 0;
1149   size_t len = strlen(str);
1150   while(len >= 4){
1151     h = (h << 5) + h + str[0];
1152     h = (h << 5) + h + str[1];
1153     h = (h << 5) + h + str[2];
1154     h = (h << 5) + h + str[3];
1155     len -= 4;
1156     str += 4;
1157   }
1158 
1159   switch(len){
1160   case 3:
1161     h = (h << 5) + h + *str++;
1162   case 2:
1163     h = (h << 5) + h + *str++;
1164   case 1:
1165     h = (h << 5) + h + *str++;
1166   }
1167   return h + h;
1168 }
1169 
1170 
1171 inline
1172 NdbColumnImpl *
getColumn(const char * name)1173 NdbTableImpl::getColumn(const char * name){
1174 
1175   Uint32 sz = m_columns.size();
1176   NdbColumnImpl** cols = m_columns.getBase();
1177   const Uint32 * hashtable = m_columnHash.getBase();
1178 
1179   if(sz > 5 && false){
1180     Uint32 hashValue = Hash(name) & 0xFFFE;
1181     Uint32 bucket = hashValue & m_columnHashMask;
1182     bucket = (bucket < sz ? bucket : bucket - sz);
1183     hashtable += bucket;
1184     Uint32 tmp = * hashtable;
1185     if((tmp & 1) == 1 ){ // No chaining
1186       sz = 1;
1187     } else {
1188       sz = (tmp >> 16);
1189       hashtable += (tmp & 0xFFFE) >> 1;
1190       tmp = * hashtable;
1191     }
1192     do {
1193       if(hashValue == (tmp & 0xFFFE)){
1194 	NdbColumnImpl* col = cols[tmp >> 16];
1195 	if(strncmp(name, col->m_name.c_str(), col->m_name.length()) == 0){
1196 	  return col;
1197 	}
1198       }
1199       hashtable++;
1200       tmp = * hashtable;
1201     } while(--sz > 0);
1202 #if 0
1203     Uint32 dir = m_columnHash[bucket];
1204     Uint32 pos = bucket + ((dir & 0xFFFE) >> 1);
1205     Uint32 cnt = dir >> 16;
1206     ndbout_c("col: %s hv: %x bucket: %d dir: %x pos: %d cnt: %d tmp: %d -> 0",
1207 	     name, hashValue, bucket, dir, pos, cnt, tmp);
1208 #endif
1209     return 0;
1210   } else {
1211     for(Uint32 i = 0; i<sz; i++){
1212       NdbColumnImpl* col = * cols++;
1213       if(col != 0 && strcmp(name, col->m_name.c_str()) == 0)
1214 	return col;
1215     }
1216   }
1217   return 0;
1218 }
1219 
1220 inline
1221 const NdbColumnImpl *
getColumn(unsigned attrId) const1222 NdbTableImpl::getColumn(unsigned attrId) const {
1223   if(m_columns.size() > attrId){
1224     return m_columns[attrId];
1225   }
1226   return 0;
1227 }
1228 
1229 inline
1230 const NdbColumnImpl *
getColumn(const char * name) const1231 NdbTableImpl::getColumn(const char * name) const {
1232   Uint32 sz = m_columns.size();
1233   NdbColumnImpl* const * cols = m_columns.getBase();
1234   for(Uint32 i = 0; i<sz; i++, cols++){
1235     NdbColumnImpl* col = * cols;
1236     if(col != 0 && strcmp(name, col->m_name.c_str()) == 0)
1237       return col;
1238   }
1239   return 0;
1240 }
1241 
1242 inline
1243 NdbIndexImpl &
getImpl(NdbDictionary::Index & t)1244 NdbIndexImpl::getImpl(NdbDictionary::Index & t){
1245   return t.m_impl;
1246 }
1247 
1248 inline
1249 NdbIndexImpl &
getImpl(const NdbDictionary::Index & t)1250 NdbIndexImpl::getImpl(const NdbDictionary::Index & t){
1251   return t.m_impl;
1252 }
1253 
1254 inline
1255 NdbDictionaryImpl &
getImpl(NdbDictionary::Dictionary & t)1256 NdbDictionaryImpl::getImpl(NdbDictionary::Dictionary & t){
1257   return t.m_impl;
1258 }
1259 
1260 inline
1261 const NdbDictionaryImpl &
getImpl(const NdbDictionary::Dictionary & t)1262 NdbDictionaryImpl::getImpl(const NdbDictionary::Dictionary & t){
1263   return t.m_impl;
1264 }
1265 
1266 /*****************************************************************
1267  * Inline:d getters
1268  */
1269 
1270 class InitTable : public GlobalCacheInitObject
1271 {
1272 public:
InitTable(const BaseString & name)1273   InitTable(const BaseString &name) :
1274     GlobalCacheInitObject(name)
1275   {}
init(NdbDictionaryImpl * dict,NdbTableImpl & tab) const1276   int init(NdbDictionaryImpl *dict, NdbTableImpl &tab) const
1277   {
1278     int res= dict->getBlobTables(tab);
1279     if (res == 0)
1280       res= dict->createDefaultNdbRecord(&tab, NULL);
1281 
1282     return res;
1283   }
1284 };
1285 
1286 inline
1287 NdbTableImpl *
getTableGlobal(const char * table_name)1288 NdbDictionaryImpl::getTableGlobal(const char * table_name)
1289 {
1290   if (unlikely(strchr(table_name, '$') != 0)) {
1291     if (is_ndb_blob_table(table_name))
1292     {
1293       /* Could attempt to get the Blob table here, but
1294        * instead we will generate an error.
1295        * The non-global getTable() calls can fetch Blob
1296        * tables correctly if necessary.
1297        *
1298        * 4307 Invalid Table name
1299        */
1300       m_error.code = 4307;
1301       return NULL;
1302     }
1303   }
1304 
1305   const BaseString internal_tabname(m_ndb.internalize_table_name(table_name));
1306   return fetchGlobalTableImplRef(InitTable(internal_tabname));
1307 }
1308 
1309 inline
1310 NdbTableImpl *
getTable(const char * table_name,void ** data)1311 NdbDictionaryImpl::getTable(const char * table_name, void **data)
1312 {
1313   DBUG_ENTER("NdbDictionaryImpl::getTable");
1314   DBUG_PRINT("enter", ("table: %s", table_name));
1315 
1316   if (unlikely(strchr(table_name, '$') != 0)) {
1317     Uint32 tab_id, col_no;
1318     if (is_ndb_blob_table(table_name, &tab_id, &col_no)) {
1319       NdbTableImpl* t = getBlobTable(tab_id, col_no);
1320       DBUG_RETURN(t);
1321     }
1322   }
1323 
1324   const BaseString internal_tabname(m_ndb.internalize_table_name(table_name));
1325   Ndb_local_table_info *info=
1326     get_local_table_info(internal_tabname);
1327   if (info == 0)
1328     DBUG_RETURN(0);
1329   if (data)
1330     *data= info->m_local_data;
1331   DBUG_RETURN(info->m_table_impl);
1332 }
1333 
1334 inline
1335 Ndb_local_table_info *
get_local_table_info(const BaseString & internalTableName)1336 NdbDictionaryImpl::get_local_table_info(const BaseString& internalTableName)
1337 {
1338   DBUG_ENTER("NdbDictionaryImpl::get_local_table_info");
1339   DBUG_PRINT("enter", ("table: %s", internalTableName.c_str()));
1340 
1341   Ndb_local_table_info *info= m_localHash.get(internalTableName.c_str());
1342   if (info == 0)
1343   {
1344     NdbTableImpl *tab=
1345       fetchGlobalTableImplRef(InitTable(internalTableName));
1346     if (tab)
1347     {
1348       info= Ndb_local_table_info::create(tab, m_local_table_data_size);
1349       if (info)
1350       {
1351         m_localHash.put(internalTableName.c_str(), info);
1352       }
1353     }
1354   }
1355   DBUG_RETURN(info); // autoincrement already initialized
1356 }
1357 
1358 class InitIndex : public GlobalCacheInitObject
1359 {
1360 public:
1361   const char *m_index_name;
1362   const NdbTableImpl &m_prim;
1363 
InitIndex(const BaseString & internal_indexname,const char * index_name,const NdbTableImpl & prim)1364   InitIndex(const BaseString &internal_indexname,
1365 	    const char *index_name,
1366 	    const NdbTableImpl &prim) :
1367     GlobalCacheInitObject(internal_indexname),
1368     m_index_name(index_name),
1369     m_prim(prim)
1370     {}
1371 
init(NdbDictionaryImpl * dict,NdbTableImpl & tab) const1372   int init(NdbDictionaryImpl *dict, NdbTableImpl &tab) const {
1373     DBUG_ENTER("InitIndex::init");
1374     DBUG_ASSERT(tab.m_indexType != NdbDictionary::Object::TypeUndefined);
1375     /**
1376      * Create index impl
1377      */
1378     NdbIndexImpl* idx;
1379     if(NdbDictInterface::create_index_obj_from_table(&idx, &tab, &m_prim) == 0)
1380     {
1381       idx->m_table = &tab;
1382       if (!idx->m_externalName.assign(m_index_name) ||
1383           !idx->m_internalName.assign(m_name))
1384         DBUG_RETURN(4000);
1385       tab.m_index = idx;
1386 
1387       /* Finally, create default NdbRecord for this index */
1388       DBUG_RETURN(dict->createDefaultNdbRecord(&tab, &m_prim));
1389     }
1390     DBUG_RETURN(1);
1391   }
1392 };
1393 
1394 inline
1395 NdbIndexImpl *
getIndexGlobal(const char * index_name,NdbTableImpl & ndbtab)1396 NdbDictionaryImpl::getIndexGlobal(const char * index_name,
1397                                   NdbTableImpl &ndbtab)
1398 {
1399   DBUG_ENTER("NdbDictionaryImpl::getIndexGlobal");
1400   const BaseString
1401     internal_indexname(m_ndb.internalize_index_name(&ndbtab, index_name));
1402   int retry= 2;
1403 
1404   while (retry)
1405   {
1406     NdbTableImpl *tab=
1407       fetchGlobalTableImplRef(InitIndex(internal_indexname,
1408 					index_name, ndbtab));
1409     if (tab)
1410     {
1411       // tab->m_index sould be set. otherwise tab == 0
1412       NdbIndexImpl *idx= tab->m_index;
1413       if (idx->m_table_id != (unsigned)ndbtab.getObjectId() ||
1414           idx->m_table_version != (unsigned)ndbtab.getObjectVersion())
1415       {
1416         releaseIndexGlobal(*idx, 1);
1417         retry--;
1418         continue;
1419       }
1420       DBUG_RETURN(idx);
1421     }
1422     break;
1423   }
1424   {
1425     // Index not found, try old format
1426     const BaseString
1427       old_internal_indexname(m_ndb.old_internalize_index_name(&ndbtab,
1428 							      index_name));
1429     retry= 2;
1430     while (retry)
1431     {
1432       NdbTableImpl *tab=
1433 	fetchGlobalTableImplRef(InitIndex(old_internal_indexname,
1434 					  index_name, ndbtab));
1435       if (tab)
1436       {
1437 	// tab->m_index sould be set. otherwise tab == 0
1438 	NdbIndexImpl *idx= tab->m_index;
1439 	if (idx->m_table_id != (unsigned)ndbtab.getObjectId() ||
1440 	    idx->m_table_version != (unsigned)ndbtab.getObjectVersion())
1441 	{
1442 	  releaseIndexGlobal(*idx, 1);
1443 	  retry--;
1444 	  continue;
1445 	}
1446 	DBUG_RETURN(idx);
1447       }
1448       break;
1449     }
1450   }
1451   m_error.code= 4243;
1452   DBUG_RETURN(0);
1453 }
1454 
1455 inline
1456 NdbIndexImpl *
getIndexGlobal(const char * indexName,const char * tableName)1457 NdbDictionaryImpl::getIndexGlobal(const char * indexName,
1458                                   const char * tableName)
1459 {
1460   DBUG_ENTER("NdbDictionaryImpl::getIndexGlobal");
1461   NdbTableImpl * t = getTableGlobal(tableName);
1462   if(t == NULL)
1463     DBUG_RETURN(0);
1464   DBUG_RETURN(getIndexGlobal(indexName, *t));
1465 }
1466 
1467 inline int
releaseTableGlobal(const NdbTableImpl & impl,int invalidate)1468 NdbDictionaryImpl::releaseTableGlobal(const NdbTableImpl & impl, int invalidate)
1469 {
1470   DBUG_ENTER("NdbDictionaryImpl::releaseTableGlobal");
1471   DBUG_PRINT("enter", ("internal_name: %s", impl.m_internalName.c_str()));
1472   m_globalHash->lock();
1473   m_globalHash->release(&impl, invalidate);
1474   m_globalHash->unlock();
1475   DBUG_RETURN(0);
1476 }
1477 
1478 inline int
releaseIndexGlobal(const NdbIndexImpl & impl,int invalidate)1479 NdbDictionaryImpl::releaseIndexGlobal(const NdbIndexImpl & impl, int invalidate)
1480 {
1481   DBUG_ENTER("NdbDictionaryImpl::releaseIndexGlobal");
1482   DBUG_PRINT("enter", ("internal_name: %s", impl.m_internalName.c_str()));
1483   m_globalHash->lock();
1484   m_globalHash->release(impl.m_table, invalidate);
1485   m_globalHash->unlock();
1486   DBUG_RETURN(0);
1487 }
1488 
1489 inline
1490 NdbIndexImpl *
getIndex(const char * index_name,const char * table_name)1491 NdbDictionaryImpl::getIndex(const char * index_name,
1492 			    const char * table_name)
1493 {
1494   if (table_name == 0)
1495   {
1496     assert(0);
1497     m_error.code= 4243;
1498     return 0;
1499   }
1500 
1501 
1502   NdbTableImpl* prim = getTable(table_name);
1503   if (prim == 0)
1504   {
1505     m_error.code= 4243;
1506     return 0;
1507   }
1508 
1509   return getIndex(index_name, *prim);
1510 }
1511 
1512 inline
1513 NdbIndexImpl *
getIndex(const char * index_name,const NdbTableImpl & prim)1514 NdbDictionaryImpl::getIndex(const char* index_name,
1515 			    const NdbTableImpl& prim)
1516 {
1517 
1518   const BaseString
1519     internal_indexname(m_ndb.internalize_index_name(&prim, index_name));
1520 
1521   Ndb_local_table_info *info= m_localHash.get(internal_indexname.c_str());
1522   NdbTableImpl *tab;
1523   if (info == 0)
1524   {
1525     tab= fetchGlobalTableImplRef(InitIndex(internal_indexname,
1526 					   index_name,
1527 					   prim));
1528     if (!tab)
1529       goto retry;
1530 
1531     info= Ndb_local_table_info::create(tab, 0);
1532     if (!info)
1533       goto retry;
1534     m_localHash.put(internal_indexname.c_str(), info);
1535   }
1536   else
1537     tab= info->m_table_impl;
1538 
1539   return tab->m_index;
1540 
1541 retry:
1542   // Index not found, try fetching it from current database
1543   const BaseString
1544     old_internal_indexname(m_ndb.old_internalize_index_name(&prim, index_name));
1545 
1546   info= m_localHash.get(old_internal_indexname.c_str());
1547   if (info == 0)
1548   {
1549     tab= fetchGlobalTableImplRef(InitIndex(old_internal_indexname,
1550 					   index_name,
1551 					   prim));
1552     if (!tab)
1553       goto err;
1554 
1555     info= Ndb_local_table_info::create(tab, 0);
1556     if (!info)
1557       goto err;
1558     m_localHash.put(old_internal_indexname.c_str(), info);
1559   }
1560   else
1561     tab= info->m_table_impl;
1562 
1563   return tab->m_index;
1564 
1565 err:
1566   m_error.code= 4243;
1567   return 0;
1568 }
1569 
1570 inline
1571 NdbTablespaceImpl &
getImpl(NdbDictionary::Tablespace & t)1572 NdbTablespaceImpl::getImpl(NdbDictionary::Tablespace & t){
1573   return t.m_impl;
1574 }
1575 
1576 inline
1577 const NdbTablespaceImpl &
getImpl(const NdbDictionary::Tablespace & t)1578 NdbTablespaceImpl::getImpl(const NdbDictionary::Tablespace & t){
1579   return t.m_impl;
1580 }
1581 
1582 inline
1583 NdbLogfileGroupImpl &
getImpl(NdbDictionary::LogfileGroup & t)1584 NdbLogfileGroupImpl::getImpl(NdbDictionary::LogfileGroup & t){
1585   return t.m_impl;
1586 }
1587 
1588 inline
1589 const NdbLogfileGroupImpl &
getImpl(const NdbDictionary::LogfileGroup & t)1590 NdbLogfileGroupImpl::getImpl(const NdbDictionary::LogfileGroup & t){
1591   return t.m_impl;
1592 }
1593 
1594 inline
1595 NdbDatafileImpl &
getImpl(NdbDictionary::Datafile & t)1596 NdbDatafileImpl::getImpl(NdbDictionary::Datafile & t){
1597   return t.m_impl;
1598 }
1599 
1600 inline
1601 const NdbDatafileImpl &
getImpl(const NdbDictionary::Datafile & t)1602 NdbDatafileImpl::getImpl(const NdbDictionary::Datafile & t){
1603   return t.m_impl;
1604 }
1605 
1606 inline
1607 NdbUndofileImpl &
getImpl(NdbDictionary::Undofile & t)1608 NdbUndofileImpl::getImpl(NdbDictionary::Undofile & t){
1609   return t.m_impl;
1610 }
1611 
1612 inline
1613 const NdbUndofileImpl &
getImpl(const NdbDictionary::Undofile & t)1614 NdbUndofileImpl::getImpl(const NdbDictionary::Undofile & t){
1615   return t.m_impl;
1616 }
1617 
1618 #endif
1619