1 /* Copyright (c) 2003-2007 MySQL AB
2    Use is subject to license terms
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 as published by
6    the Free Software Foundation; version 2 of the License.
7 
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.
12 
13    You should have received a copy of the GNU General Public License
14    along with this program; if not, write to the Free Software
15    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA */
16 
17 #ifndef NdbDictionaryImpl_H
18 #define NdbDictionaryImpl_H
19 
20 #include <ndb_types.h>
21 #include <kernel_types.h>
22 #include <NdbError.hpp>
23 #include <BaseString.hpp>
24 #include <Vector.hpp>
25 #include <UtilBuffer.hpp>
26 #include <NdbDictionary.hpp>
27 #include <Bitmask.hpp>
28 #include <AttributeList.hpp>
29 #include <Ndb.hpp>
30 #include "NdbWaiter.hpp"
31 #include "DictCache.hpp"
32 
33 bool
34 is_ndb_blob_table(const char* name, Uint32* ptab_id = 0, Uint32* pcol_no = 0);
35 bool
36 is_ndb_blob_table(const class NdbTableImpl* t);
37 
38 extern int ndb_dictionary_is_mysqld;
39 #define ASSERT_NOT_MYSQLD assert(ndb_dictionary_is_mysqld == 0)
40 
41 class NdbDictObjectImpl {
42 public:
43   int m_id;
44   Uint32 m_version;
45   NdbDictionary::Object::Type m_type;
46   NdbDictionary::Object::Status m_status;
47 
48   bool change();
49 
getImpl(NdbDictionary::ObjectId & t)50   static NdbDictObjectImpl & getImpl(NdbDictionary::ObjectId & t) {
51     return t.m_impl;
52   }
getImpl(const NdbDictionary::ObjectId & t)53   static const NdbDictObjectImpl & getImpl(const NdbDictionary::ObjectId & t){
54     return t.m_impl;
55   }
56 
57 protected:
58   friend class NdbDictionary::ObjectId;
59 
NdbDictObjectImpl(NdbDictionary::Object::Type type)60   NdbDictObjectImpl(NdbDictionary::Object::Type type) :
61     m_type(type),
62     m_status(NdbDictionary::Object::New) {
63     m_id = -1;
64   }
65 };
66 
67 /**
68  * Column
69  */
70 class NdbColumnImpl : public NdbDictionary::Column {
71 public:
72   NdbColumnImpl();
73   NdbColumnImpl(NdbDictionary::Column &); // This is not a copy constructor
74   ~NdbColumnImpl();
75   NdbColumnImpl& operator=(const NdbColumnImpl&);
76   void init(Type t = Unsigned);
77 
78   int m_attrId;
79   BaseString m_name;
80   NdbDictionary::Column::Type m_type;
81   int m_precision;
82   int m_scale;
83   int m_length;
84   int m_column_no;
85   CHARSET_INFO * m_cs;          // not const in MySQL
86 
87   bool m_pk;
88   bool m_distributionKey;
89   bool m_nullable;
90   bool m_autoIncrement;
91   Uint64 m_autoIncrementInitialValue;
92   BaseString m_defaultValue;
93   NdbTableImpl * m_blobTable;
94 
95   /**
96    * Internal types and sizes, and aggregates
97    */
98   Uint32 m_attrSize;            // element size (size when arraySize==1)
99   Uint32 m_arraySize;           // length or maxlength+1/2 for Var* types
100   Uint32 m_arrayType;           // NDB_ARRAYTYPE_FIXED or _VAR
101   Uint32 m_storageType;         // NDB_STORAGETYPE_MEMORY or _DISK
102   /*
103    * NdbTableImpl: if m_pk, 0-based index of key in m_attrId order
104    * NdbIndexImpl: m_column_no of primary table column
105    */
106   Uint32 m_keyInfoPos;
107   // TODO: use bits in attr desc 2
108   bool getInterpretableType() const ;
109   bool getCharType() const;
110   bool getStringType() const;
111   bool getBlobType() const;
112 
113   /**
114    * Equality/assign
115    */
116   bool equal(const NdbColumnImpl&) const;
117 
118   static NdbColumnImpl & getImpl(NdbDictionary::Column & t);
119   static const NdbColumnImpl & getImpl(const NdbDictionary::Column & t);
120   NdbDictionary::Column * m_facade;
121 
122   static NdbDictionary::Column * create_pseudo(const char *);
123 
124   // Get total length in bytes, used by NdbOperation
125   bool get_var_length(const void* value, Uint32& len) const;
126 };
127 
128 class NdbTableImpl : public NdbDictionary::Table, public NdbDictObjectImpl {
129 public:
130   NdbTableImpl();
131   NdbTableImpl(NdbDictionary::Table &);
132   ~NdbTableImpl();
133 
134   void init();
135   int setName(const char * name);
136   const char * getName() const;
137   void setFragmentCount(Uint32 count);
138   Uint32 getFragmentCount() const;
139   int setFrm(const void* data, Uint32 len);
140   const void * getFrmData() const;
141   Uint32 getFrmLength() const;
142   int setFragmentData(const void* data, Uint32 len);
143   const void * getFragmentData() const;
144   Uint32 getFragmentDataLen() const;
145   int setTablespaceNames(const void* data, Uint32 len);
146   Uint32 getTablespaceNamesLen() const;
147   const void * getTablespaceNames() const;
148   int setTablespaceData(const void* data, Uint32 len);
149   const void * getTablespaceData() const;
150   Uint32 getTablespaceDataLen() const;
151   int setRangeListData(const void* data, Uint32 len);
152   const void * getRangeListData() const;
153   Uint32 getRangeListDataLen() const;
154 
155   const char * getMysqlName() const;
156   int updateMysqlName();
157 
158   int aggregate(NdbError& error);
159   int validate(NdbError& error);
160 
161   Uint32 m_changeMask;
162   Uint32 m_primaryTableId;
163   BaseString m_internalName;
164   BaseString m_externalName;
165   BaseString m_mysqlName;
166   BaseString m_newExternalName; // Used for alter table
167   UtilBuffer m_frm;
168   UtilBuffer m_newFrm;       // Used for alter table
169   UtilBuffer m_ts_name;      //Tablespace Names
170   UtilBuffer m_new_ts_name;  //Tablespace Names
171   UtilBuffer m_ts;           //TablespaceData
172   UtilBuffer m_new_ts;       //TablespaceData
173   UtilBuffer m_fd;           //FragmentData
174   UtilBuffer m_new_fd;       //FragmentData
175   UtilBuffer m_range;        //Range Or List Array
176   UtilBuffer m_new_range;    //Range Or List Array
177   NdbDictionary::Object::FragmentType m_fragmentType;
178 
179   /**
180    *
181    */
182   Uint32 m_columnHashMask;
183   Vector<Uint32> m_columnHash;
184   Vector<NdbColumnImpl *> m_columns;
185   void computeAggregates();
186   int buildColumnHash();
187 
188   /**
189    * Fragment info
190    */
191   Uint32 m_hashValueMask;
192   Uint32 m_hashpointerValue;
193   Vector<Uint16> m_fragments;
194 
195   Uint64 m_max_rows;
196   Uint64 m_min_rows;
197   Uint32 m_default_no_part_flag;
198   bool m_linear_flag;
199   bool m_logging;
200   bool m_temporary;
201   bool m_row_gci;
202   bool m_row_checksum;
203   bool m_force_var_part;
204   int m_kvalue;
205   int m_minLoadFactor;
206   int m_maxLoadFactor;
207   Uint16 m_keyLenInWords;
208   Uint16 m_fragmentCount;
209   Uint8 m_single_user_mode;
210 
211   NdbIndexImpl * m_index;
212   NdbColumnImpl * getColumn(unsigned attrId);
213   NdbColumnImpl * getColumn(const char * name);
214   const NdbColumnImpl * getColumn(unsigned attrId) const;
215   const NdbColumnImpl * getColumn(const char * name) const;
216 
217   /**
218    * Index only stuff
219    */
220   BaseString m_primaryTable;
221   NdbDictionary::Object::Type m_indexType;
222 
223   /**
224    * Aggregates
225    */
226   Uint8 m_noOfKeys;
227   // if all pk = dk then this is zero!
228   Uint8 m_noOfDistributionKeys;
229   Uint8 m_noOfBlobs;
230   Uint8 m_noOfDiskColumns;
231   Uint8 m_replicaCount;
232 
233   /**
234    * Equality/assign
235    */
236   bool equal(const NdbTableImpl&) const;
237   int assign(const NdbTableImpl&);
238 
239   static NdbTableImpl & getImpl(NdbDictionary::Table & t);
240   static NdbTableImpl & getImpl(const NdbDictionary::Table & t);
241   NdbDictionary::Table * m_facade;
242 
243   /**
244    * Return count
245    */
246   Uint32 get_nodes(Uint32 hashValue, const Uint16** nodes) const ;
247 
248   /**
249    * Disk stuff
250    */
251   BaseString m_tablespace_name;
252   Uint32 m_tablespace_id;
253   Uint32 m_tablespace_version;
254 };
255 
256 class NdbIndexImpl : public NdbDictionary::Index, public NdbDictObjectImpl {
257 public:
258   NdbIndexImpl();
259   NdbIndexImpl(NdbDictionary::Index &);
260   ~NdbIndexImpl();
261 
262   void init();
263   int setName(const char * name);
264   const char * getName() const;
265   int setTable(const char * table);
266   const char * getTable() const;
267   const NdbTableImpl * getIndexTable() const;
268 
269   BaseString m_internalName;
270   BaseString m_externalName;
271   BaseString m_tableName;
272   Uint32 m_table_id;
273   Uint32 m_table_version;
274   Vector<NdbColumnImpl *> m_columns;
275   Vector<int> m_key_ids;
276 
277   bool m_logging;
278   bool m_temporary;
279 
280   NdbTableImpl * m_table;
281 
282   static NdbIndexImpl & getImpl(NdbDictionary::Index & t);
283   static NdbIndexImpl & getImpl(const NdbDictionary::Index & t);
284   NdbDictionary::Index * m_facade;
285 };
286 
287 class NdbEventImpl : public NdbDictionary::Event, public NdbDictObjectImpl {
288   friend class NdbDictInterface;
289   friend class NdbDictionaryImpl;
290   friend class NdbEventOperation;
291   friend class NdbEventOperationImpl;
292   friend class NdbEventBuffer;
293   friend class EventBufData_hash;
294   friend class NdbBlob;
295 public:
296   NdbEventImpl();
297   NdbEventImpl(NdbDictionary::Event &);
298   ~NdbEventImpl();
299 
300   void init();
301   int setName(const char * name);
302   const char * getName() const;
303   int setTable(const NdbDictionary::Table& table);
304   const NdbDictionary::Table * getTable() const;
305   int setTable(const char * table);
306   const char * getTableName() const;
307   void addTableEvent(const NdbDictionary::Event::TableEvent t);
308   bool getTableEvent(const NdbDictionary::Event::TableEvent t) const;
309   void setDurability(NdbDictionary::Event::EventDurability d);
310   NdbDictionary::Event::EventDurability  getDurability() const;
311   void setReport(NdbDictionary::Event::EventReport r);
312   NdbDictionary::Event::EventReport  getReport() const;
313   int getNoOfEventColumns() const;
314   const NdbDictionary::Column * getEventColumn(unsigned no) const;
315 
print()316   void print() {
317     ndbout_c("NdbEventImpl: id=%d, key=%d",
318 	     m_eventId,
319 	     m_eventKey);
320   };
321 
322   Uint32 m_eventId;
323   Uint32 m_eventKey;
324   AttributeMask m_attrListBitmask;
325   Uint32 m_table_id;
326   Uint32 m_table_version;
327   BaseString m_name;
328   Uint32 mi_type;
329   NdbDictionary::Event::EventDurability m_dur;
330   NdbDictionary::Event::EventReport m_rep;
331   bool m_mergeEvents;
332 
333   BaseString m_tableName;
334   Vector<NdbColumnImpl *> m_columns;
335   Vector<unsigned> m_attrIds;
336 
337   static NdbEventImpl & getImpl(NdbDictionary::Event & t);
338   static NdbEventImpl & getImpl(const NdbDictionary::Event & t);
339   NdbDictionary::Event * m_facade;
340 private:
341   NdbTableImpl *m_tableImpl;
342   void setTable(NdbTableImpl *tableImpl);
343 };
344 
345 struct NdbFilegroupImpl : public NdbDictObjectImpl {
346   NdbFilegroupImpl(NdbDictionary::Object::Type t);
347 
348   BaseString m_name;
349   NdbDictionary::AutoGrowSpecification m_grow_spec;
350 
351   union {
352     Uint32 m_extent_size;
353     Uint32 m_undo_buffer_size;
354   };
355 
356   BaseString m_logfile_group_name;
357   Uint32 m_logfile_group_id;
358   Uint32 m_logfile_group_version;
359   Uint64 m_undo_free_words;
360 };
361 
362 class NdbTablespaceImpl : public NdbDictionary::Tablespace,
363 			  public NdbFilegroupImpl {
364 public:
365   NdbTablespaceImpl();
366   NdbTablespaceImpl(NdbDictionary::Tablespace &);
367   ~NdbTablespaceImpl();
368 
369   int assign(const NdbTablespaceImpl&);
370 
371   static NdbTablespaceImpl & getImpl(NdbDictionary::Tablespace & t);
372   static const NdbTablespaceImpl & getImpl(const NdbDictionary::Tablespace &);
373   NdbDictionary::Tablespace * m_facade;
374 };
375 
376 class NdbLogfileGroupImpl : public NdbDictionary::LogfileGroup,
377 			    public NdbFilegroupImpl {
378 public:
379   NdbLogfileGroupImpl();
380   NdbLogfileGroupImpl(NdbDictionary::LogfileGroup &);
381   ~NdbLogfileGroupImpl();
382 
383   int assign(const NdbLogfileGroupImpl&);
384 
385   static NdbLogfileGroupImpl & getImpl(NdbDictionary::LogfileGroup & t);
386   static const NdbLogfileGroupImpl& getImpl(const
387 					    NdbDictionary::LogfileGroup&);
388   NdbDictionary::LogfileGroup * m_facade;
389 };
390 
391 struct NdbFileImpl : public NdbDictObjectImpl {
392   NdbFileImpl(NdbDictionary::Object::Type t);
393 
394   Uint64 m_size;
395   Uint64 m_free;
396   BaseString m_path;
397   BaseString m_filegroup_name;
398   Uint32 m_filegroup_id;
399   Uint32 m_filegroup_version;
400 };
401 
402 class NdbDatafileImpl : public NdbDictionary::Datafile, public NdbFileImpl {
403 public:
404   NdbDatafileImpl();
405   NdbDatafileImpl(NdbDictionary::Datafile &);
406   ~NdbDatafileImpl();
407 
408   int assign(const NdbDatafileImpl&);
409 
410   static NdbDatafileImpl & getImpl(NdbDictionary::Datafile & t);
411   static const NdbDatafileImpl & getImpl(const NdbDictionary::Datafile & t);
412   NdbDictionary::Datafile * m_facade;
413 };
414 
415 class NdbUndofileImpl : public NdbDictionary::Undofile, public NdbFileImpl {
416 public:
417   NdbUndofileImpl();
418   NdbUndofileImpl(NdbDictionary::Undofile &);
419   ~NdbUndofileImpl();
420 
421   int assign(const NdbUndofileImpl&);
422 
423   static NdbUndofileImpl & getImpl(NdbDictionary::Undofile & t);
424   static const NdbUndofileImpl & getImpl(const NdbDictionary::Undofile & t);
425   NdbDictionary::Undofile * m_facade;
426 };
427 
428 class NdbDictInterface {
429 public:
NdbDictInterface(NdbError & err)430   NdbDictInterface(NdbError& err) : m_error(err) {
431     m_reference = 0;
432     m_masterNodeId = 0;
433     m_transporter= NULL;
434   }
435   ~NdbDictInterface();
436 
437   bool setTransporter(class Ndb * ndb, class TransporterFacade * tf);
438   bool setTransporter(class TransporterFacade * tf);
439 
440   // To abstract the stuff thats made in all create/drop/lists below
441   int dictSignal(NdbApiSignal* signal, LinearSectionPtr ptr[3], int secs,
442 		 int nodeId, // -1 any, 0 = master, >1 = specified
443 		 WaitSignalType wst,
444 		 int timeout, Uint32 RETRIES,
445 		 const int *errcodes = 0, int temporaryMask = 0);
446 
447   int createOrAlterTable(class Ndb & ndb, NdbTableImpl &, bool alter);
448 
449   int createTable(class Ndb & ndb, NdbTableImpl &);
450   int alterTable(class Ndb & ndb, NdbTableImpl &);
451   int dropTable(const NdbTableImpl &);
452 
453   int createIndex(class Ndb & ndb, const NdbIndexImpl &, const NdbTableImpl &);
454   int dropIndex(const NdbIndexImpl &, const NdbTableImpl &);
455 
456   int createEvent(class Ndb & ndb, NdbEventImpl &, int getFlag);
457   int dropEvent(const NdbEventImpl &);
458   int dropEvent(NdbApiSignal* signal, LinearSectionPtr ptr[3], int noLSP);
459 
460   int executeSubscribeEvent(class Ndb & ndb, NdbEventOperationImpl &);
461   int stopSubscribeEvent(class Ndb & ndb, NdbEventOperationImpl &);
462 
463   int listObjects(NdbDictionary::Dictionary::List& list, Uint32 requestData, bool fullyQualifiedNames);
464   int listObjects(NdbApiSignal* signal);
465 
466   NdbTableImpl * getTable(int tableId, bool fullyQualifiedNames);
467   NdbTableImpl * getTable(const BaseString& name, bool fullyQualifiedNames);
468   NdbTableImpl * getTable(class NdbApiSignal * signal,
469 			  LinearSectionPtr ptr[3],
470 			  Uint32 noOfSections, bool fullyQualifiedNames);
471 
472   int forceGCPWait();
473 
474   static int parseTableInfo(NdbTableImpl ** dst,
475 			    const Uint32 * data, Uint32 len,
476 			    bool fullyQualifiedNames,
477                             Uint32 version= 0xFFFFFFFF);
478 
479   static int parseFileInfo(NdbFileImpl &dst,
480 			   const Uint32 * data, Uint32 len);
481 
482   static int parseFilegroupInfo(NdbFilegroupImpl &dst,
483 				const Uint32 * data, Uint32 len);
484 
485   int create_file(const NdbFileImpl &, const NdbFilegroupImpl&,
486 		  bool overwrite, NdbDictObjectImpl*);
487   int drop_file(const NdbFileImpl &);
488   int create_filegroup(const NdbFilegroupImpl &, NdbDictObjectImpl*);
489   int drop_filegroup(const NdbFilegroupImpl &);
490 
491   int get_filegroup(NdbFilegroupImpl&, NdbDictionary::Object::Type, Uint32);
492   int get_filegroup(NdbFilegroupImpl&,NdbDictionary::Object::Type,const char*);
493   int get_file(NdbFileImpl&, NdbDictionary::Object::Type, int, int);
494   int get_file(NdbFileImpl&, NdbDictionary::Object::Type, int, const char *);
495 
496   static int create_index_obj_from_table(NdbIndexImpl ** dst,
497 					 NdbTableImpl* index_table,
498 					 const NdbTableImpl* primary_table);
499 
500   const NdbError &getNdbError() const;
501   NdbError & m_error;
502 private:
503   Uint32 m_reference;
504   Uint32 m_masterNodeId;
505 
506   NdbWaiter m_waiter;
507   class TransporterFacade * m_transporter;
508 
509   friend class Ndb;
510   friend class NdbDictionaryImpl;
511   static void execSignal(void* dictImpl,
512 			 class NdbApiSignal* signal,
513 			 struct LinearSectionPtr ptr[3]);
514 
515   static void execNodeStatus(void* dictImpl, Uint32,
516 			     bool alive, bool nfCompleted);
517 
518   void execGET_TABINFO_REF(NdbApiSignal *, LinearSectionPtr ptr[3]);
519   void execGET_TABINFO_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]);
520   void execCREATE_TABLE_REF(NdbApiSignal *, LinearSectionPtr ptr[3]);
521   void execCREATE_TABLE_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]);
522   void execALTER_TABLE_REF(NdbApiSignal *, LinearSectionPtr ptr[3]);
523   void execALTER_TABLE_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]);
524 
525   void execCREATE_INDX_REF(NdbApiSignal *, LinearSectionPtr ptr[3]);
526   void execCREATE_INDX_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]);
527   void execDROP_INDX_REF(NdbApiSignal *, LinearSectionPtr ptr[3]);
528   void execDROP_INDX_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]);
529 
530   void execCREATE_EVNT_REF(NdbApiSignal *, LinearSectionPtr ptr[3]);
531   void execCREATE_EVNT_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]);
532   void execSUB_START_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]);
533   void execSUB_START_REF(NdbApiSignal *, LinearSectionPtr ptr[3]);
534   void execSUB_STOP_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]);
535   void execSUB_STOP_REF(NdbApiSignal *, LinearSectionPtr ptr[3]);
536   void execDROP_EVNT_REF(NdbApiSignal *, LinearSectionPtr ptr[3]);
537   void execDROP_EVNT_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]);
538 
539   void execDROP_TABLE_REF(NdbApiSignal *, LinearSectionPtr ptr[3]);
540   void execDROP_TABLE_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]);
541   void execLIST_TABLES_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]);
542 
543   void execCREATE_FILE_REF(NdbApiSignal *, LinearSectionPtr ptr[3]);
544   void execCREATE_FILE_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]);
545 
546   void execCREATE_FILEGROUP_REF(NdbApiSignal *, LinearSectionPtr ptr[3]);
547   void execCREATE_FILEGROUP_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]);
548 
549   void execDROP_FILE_REF(NdbApiSignal *, LinearSectionPtr ptr[3]);
550   void execDROP_FILE_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]);
551 
552   void execDROP_FILEGROUP_REF(NdbApiSignal *, LinearSectionPtr ptr[3]);
553   void execDROP_FILEGROUP_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]);
554 
555   void execWAIT_GCP_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]);
556   void execWAIT_GCP_REF(NdbApiSignal *, LinearSectionPtr ptr[3]);
557 
558   Uint32 m_fragmentId;
559   UtilBuffer m_buffer;
560 };
561 
562 class NdbDictionaryImpl;
563 class GlobalCacheInitObject
564 {
565 public:
566   NdbDictionaryImpl *m_dict;
567   const BaseString &m_name;
GlobalCacheInitObject(NdbDictionaryImpl * dict,const BaseString & name)568   GlobalCacheInitObject(NdbDictionaryImpl *dict,
569                         const BaseString &name) :
570     m_dict(dict),
571     m_name(name)
572   {}
~GlobalCacheInitObject()573   virtual ~GlobalCacheInitObject() {}
574   virtual int init(NdbTableImpl &tab) const = 0;
575 };
576 
577 class NdbDictionaryImpl : public NdbDictionary::Dictionary {
578 public:
579   NdbDictionaryImpl(Ndb &ndb);
580   NdbDictionaryImpl(Ndb &ndb, NdbDictionary::Dictionary & f);
581   ~NdbDictionaryImpl();
582 
583   bool setTransporter(class Ndb * ndb, class TransporterFacade * tf);
584   bool setTransporter(class TransporterFacade * tf);
585 
586   int createTable(NdbTableImpl &t);
587   int createBlobTables(NdbTableImpl& org, NdbTableImpl& created);
588   int alterTable(NdbTableImpl &t);
589   int dropTable(const char * name);
590   int dropTable(NdbTableImpl &);
591   int dropBlobTables(NdbTableImpl &);
592   int invalidateObject(NdbTableImpl &);
593   int removeCachedObject(NdbTableImpl &);
594 
595   int createIndex(NdbIndexImpl &ix);
596   int createIndex(NdbIndexImpl &ix, NdbTableImpl & tab);
597   int dropIndex(const char * indexName,
598 		const char * tableName);
599   int dropIndex(NdbIndexImpl &, const char * tableName);
600   NdbTableImpl * getIndexTable(NdbIndexImpl * index,
601 			       NdbTableImpl * table);
602 
603   int createEvent(NdbEventImpl &);
604   int createBlobEvents(NdbEventImpl &);
605   int dropEvent(const char * eventName);
606   int dropEvent(const NdbEventImpl &);
607   int dropBlobEvents(const NdbEventImpl &);
608 
609   int executeSubscribeEvent(NdbEventOperationImpl &);
610   int stopSubscribeEvent(NdbEventOperationImpl &);
611 
612   int forceGCPWait();
613 
614   int listObjects(List& list, NdbDictionary::Object::Type type);
615   int listIndexes(List& list, Uint32 indexId);
616 
617   NdbTableImpl * getTableGlobal(const char * tableName);
618   NdbIndexImpl * getIndexGlobal(const char * indexName,
619                                 NdbTableImpl &ndbtab);
620   int alterTableGlobal(NdbTableImpl &orig_impl, NdbTableImpl &impl);
621   int dropTableGlobal(NdbTableImpl &);
622   int dropIndexGlobal(NdbIndexImpl & impl);
623   int releaseTableGlobal(NdbTableImpl & impl, int invalidate);
624   int releaseIndexGlobal(NdbIndexImpl & impl, int invalidate);
625 
626   NdbTableImpl * getTable(const char * tableName, void **data= 0);
627   NdbTableImpl * getBlobTable(const NdbTableImpl&, uint col_no);
628   NdbTableImpl * getBlobTable(uint tab_id, uint col_no);
629   void putTable(NdbTableImpl *impl);
630   int getBlobTables(NdbTableImpl &);
631   Ndb_local_table_info*
632     get_local_table_info(const BaseString& internalTableName);
633   NdbIndexImpl * getIndex(const char * indexName,
634 			  const char * tableName);
635   NdbIndexImpl * getIndex(const char * indexName, const NdbTableImpl& prim);
636   NdbEventImpl * getEvent(const char * eventName, NdbTableImpl* = NULL);
637   NdbEventImpl * getBlobEvent(const NdbEventImpl& ev, uint col_no);
638   NdbEventImpl * getEventImpl(const char * internalName);
639 
640   int createDatafile(const NdbDatafileImpl &, bool force, NdbDictObjectImpl*);
641   int dropDatafile(const NdbDatafileImpl &);
642   int createUndofile(const NdbUndofileImpl &, bool force, NdbDictObjectImpl*);
643   int dropUndofile(const NdbUndofileImpl &);
644 
645   int createTablespace(const NdbTablespaceImpl &, NdbDictObjectImpl*);
646   int dropTablespace(const NdbTablespaceImpl &);
647 
648   int createLogfileGroup(const NdbLogfileGroupImpl &, NdbDictObjectImpl*);
649   int dropLogfileGroup(const NdbLogfileGroupImpl &);
650 
651   const NdbError & getNdbError() const;
652   NdbError m_error;
653   Uint32 m_local_table_data_size;
654 
655   LocalDictCache m_localHash;
656   GlobalDictCache * m_globalHash;
657 
658   static NdbDictionaryImpl & getImpl(NdbDictionary::Dictionary & t);
659   static const NdbDictionaryImpl & getImpl(const NdbDictionary::Dictionary &t);
660   NdbDictionary::Dictionary * m_facade;
661 
662   NdbDictInterface m_receiver;
663   Ndb & m_ndb;
664 
665   NdbIndexImpl* getIndexImpl(const char * externalName,
666                              const BaseString& internalName,
667                              NdbTableImpl &tab,
668                              NdbTableImpl &prim);
669   NdbIndexImpl * getIndexImpl(const char * name,
670                               const BaseString& internalName);
671 private:
672   NdbTableImpl * fetchGlobalTableImplRef(const GlobalCacheInitObject &obj);
673 };
674 
675 inline
676 NdbEventImpl &
getImpl(const NdbDictionary::Event & t)677 NdbEventImpl::getImpl(const NdbDictionary::Event & t){
678   return t.m_impl;
679 }
680 
681 inline
682 NdbEventImpl &
getImpl(NdbDictionary::Event & t)683 NdbEventImpl::getImpl(NdbDictionary::Event & t){
684   return t.m_impl;
685 }
686 
687 inline
688 NdbColumnImpl &
getImpl(NdbDictionary::Column & t)689 NdbColumnImpl::getImpl(NdbDictionary::Column & t){
690   return t.m_impl;
691 }
692 
693 inline
694 const NdbColumnImpl &
getImpl(const NdbDictionary::Column & t)695 NdbColumnImpl::getImpl(const NdbDictionary::Column & t){
696   return t.m_impl;
697 }
698 
699 inline
700 bool
getInterpretableType() const701 NdbColumnImpl::getInterpretableType() const {
702   return (m_type == NdbDictionary::Column::Unsigned ||
703 	  m_type == NdbDictionary::Column::Bigunsigned);
704 }
705 
706 inline
707 bool
getCharType() const708 NdbColumnImpl::getCharType() const {
709   return (m_type == NdbDictionary::Column::Char ||
710           m_type == NdbDictionary::Column::Varchar ||
711           m_type == NdbDictionary::Column::Text ||
712           m_type == NdbDictionary::Column::Longvarchar);
713 }
714 
715 inline
716 bool
getStringType() const717 NdbColumnImpl::getStringType() const {
718   return (m_type == NdbDictionary::Column::Char ||
719           m_type == NdbDictionary::Column::Varchar ||
720           m_type == NdbDictionary::Column::Longvarchar ||
721           m_type == NdbDictionary::Column::Binary ||
722           m_type == NdbDictionary::Column::Varbinary ||
723           m_type == NdbDictionary::Column::Longvarbinary);
724 }
725 
726 inline
727 bool
getBlobType() const728 NdbColumnImpl::getBlobType() const {
729   return (m_type == NdbDictionary::Column::Blob ||
730 	  m_type == NdbDictionary::Column::Text);
731 }
732 
733 inline
734 bool
get_var_length(const void * value,Uint32 & len) const735 NdbColumnImpl::get_var_length(const void* value, Uint32& len) const
736 {
737   Uint32 max_len = m_attrSize * m_arraySize;
738   switch (m_arrayType) {
739   case NDB_ARRAYTYPE_SHORT_VAR:
740     len = 1 + *((Uint8*)value);
741     break;
742   case NDB_ARRAYTYPE_MEDIUM_VAR:
743     len = 2 + uint2korr((char*)value);
744     break;
745   default:
746     len = max_len;
747     return true;
748   }
749   return (len <= max_len);
750 }
751 
752 inline
753 NdbTableImpl &
getImpl(NdbDictionary::Table & t)754 NdbTableImpl::getImpl(NdbDictionary::Table & t){
755   return t.m_impl;
756 }
757 
758 inline
759 NdbTableImpl &
getImpl(const NdbDictionary::Table & t)760 NdbTableImpl::getImpl(const NdbDictionary::Table & t){
761   return t.m_impl;
762 }
763 
764 inline
765 NdbColumnImpl *
getColumn(unsigned attrId)766 NdbTableImpl::getColumn(unsigned attrId){
767   if(m_columns.size() > attrId){
768     return m_columns[attrId];
769   }
770   return 0;
771 }
772 
773 inline
774 const char *
getMysqlName() const775 NdbTableImpl::getMysqlName() const
776 {
777   return m_mysqlName.c_str();
778 }
779 
780 inline
781 Uint32
Hash(const char * str)782 Hash( const char* str ){
783   Uint32 h = 0;
784   Uint32 len = strlen(str);
785   while(len >= 4){
786     h = (h << 5) + h + str[0];
787     h = (h << 5) + h + str[1];
788     h = (h << 5) + h + str[2];
789     h = (h << 5) + h + str[3];
790     len -= 4;
791     str += 4;
792   }
793 
794   switch(len){
795   case 3:
796     h = (h << 5) + h + *str++;
797   case 2:
798     h = (h << 5) + h + *str++;
799   case 1:
800     h = (h << 5) + h + *str++;
801   }
802   return h + h;
803 }
804 
805 
806 inline
807 NdbColumnImpl *
getColumn(const char * name)808 NdbTableImpl::getColumn(const char * name){
809 
810   Uint32 sz = m_columns.size();
811   NdbColumnImpl** cols = m_columns.getBase();
812   const Uint32 * hashtable = m_columnHash.getBase();
813 
814   if(sz > 5 && false){
815     Uint32 hashValue = Hash(name) & 0xFFFE;
816     Uint32 bucket = hashValue & m_columnHashMask;
817     bucket = (bucket < sz ? bucket : bucket - sz);
818     hashtable += bucket;
819     Uint32 tmp = * hashtable;
820     if((tmp & 1) == 1 ){ // No chaining
821       sz = 1;
822     } else {
823       sz = (tmp >> 16);
824       hashtable += (tmp & 0xFFFE) >> 1;
825       tmp = * hashtable;
826     }
827     do {
828       if(hashValue == (tmp & 0xFFFE)){
829 	NdbColumnImpl* col = cols[tmp >> 16];
830 	if(strncmp(name, col->m_name.c_str(), col->m_name.length()) == 0){
831 	  return col;
832 	}
833       }
834       hashtable++;
835       tmp = * hashtable;
836     } while(--sz > 0);
837 #if 0
838     Uint32 dir = m_columnHash[bucket];
839     Uint32 pos = bucket + ((dir & 0xFFFE) >> 1);
840     Uint32 cnt = dir >> 16;
841     ndbout_c("col: %s hv: %x bucket: %d dir: %x pos: %d cnt: %d tmp: %d -> 0",
842 	     name, hashValue, bucket, dir, pos, cnt, tmp);
843 #endif
844     return 0;
845   } else {
846     for(Uint32 i = 0; i<sz; i++){
847       NdbColumnImpl* col = * cols++;
848       if(col != 0 && strcmp(name, col->m_name.c_str()) == 0)
849 	return col;
850     }
851   }
852   return 0;
853 }
854 
855 inline
856 const NdbColumnImpl *
getColumn(unsigned attrId) const857 NdbTableImpl::getColumn(unsigned attrId) const {
858   if(m_columns.size() > attrId){
859     return m_columns[attrId];
860   }
861   return 0;
862 }
863 
864 inline
865 const NdbColumnImpl *
getColumn(const char * name) const866 NdbTableImpl::getColumn(const char * name) const {
867   Uint32 sz = m_columns.size();
868   NdbColumnImpl* const * cols = m_columns.getBase();
869   for(Uint32 i = 0; i<sz; i++, cols++){
870     NdbColumnImpl* col = * cols;
871     if(col != 0 && strcmp(name, col->m_name.c_str()) == 0)
872       return col;
873   }
874   return 0;
875 }
876 
877 inline
878 NdbIndexImpl &
getImpl(NdbDictionary::Index & t)879 NdbIndexImpl::getImpl(NdbDictionary::Index & t){
880   return t.m_impl;
881 }
882 
883 inline
884 NdbIndexImpl &
getImpl(const NdbDictionary::Index & t)885 NdbIndexImpl::getImpl(const NdbDictionary::Index & t){
886   return t.m_impl;
887 }
888 
889 inline
890 NdbDictionaryImpl &
getImpl(NdbDictionary::Dictionary & t)891 NdbDictionaryImpl::getImpl(NdbDictionary::Dictionary & t){
892   return t.m_impl;
893 }
894 
895 inline
896 const NdbDictionaryImpl &
getImpl(const NdbDictionary::Dictionary & t)897 NdbDictionaryImpl::getImpl(const NdbDictionary::Dictionary & t){
898   return t.m_impl;
899 }
900 
901 /*****************************************************************
902  * Inline:d getters
903  */
904 
905 class InitTable : public GlobalCacheInitObject
906 {
907 public:
InitTable(NdbDictionaryImpl * dict,const BaseString & name)908   InitTable(NdbDictionaryImpl *dict,
909             const BaseString &name) :
910     GlobalCacheInitObject(dict, name)
911   {}
init(NdbTableImpl & tab) const912   int init(NdbTableImpl &tab) const
913   {
914     return m_dict->getBlobTables(tab);
915   }
916 };
917 
918 inline
919 NdbTableImpl *
getTableGlobal(const char * table_name)920 NdbDictionaryImpl::getTableGlobal(const char * table_name)
921 {
922   const BaseString internal_tabname(m_ndb.internalize_table_name(table_name));
923   return fetchGlobalTableImplRef(InitTable(this, internal_tabname));
924 }
925 
926 inline
927 NdbTableImpl *
getTable(const char * table_name,void ** data)928 NdbDictionaryImpl::getTable(const char * table_name, void **data)
929 {
930   DBUG_ENTER("NdbDictionaryImpl::getTable");
931   DBUG_PRINT("enter", ("table: %s", table_name));
932 
933   if (unlikely(strchr(table_name, '$') != 0)) {
934     Uint32 tab_id, col_no;
935     if (is_ndb_blob_table(table_name, &tab_id, &col_no)) {
936       NdbTableImpl* t = getBlobTable(tab_id, col_no);
937       DBUG_RETURN(t);
938     }
939   }
940 
941   const BaseString internal_tabname(m_ndb.internalize_table_name(table_name));
942   Ndb_local_table_info *info=
943     get_local_table_info(internal_tabname);
944   if (info == 0)
945     DBUG_RETURN(0);
946   if (data)
947     *data= info->m_local_data;
948   DBUG_RETURN(info->m_table_impl);
949 }
950 
951 inline
952 Ndb_local_table_info *
get_local_table_info(const BaseString & internalTableName)953 NdbDictionaryImpl::get_local_table_info(const BaseString& internalTableName)
954 {
955   DBUG_ENTER("NdbDictionaryImpl::get_local_table_info");
956   DBUG_PRINT("enter", ("table: %s", internalTableName.c_str()));
957 
958   Ndb_local_table_info *info= m_localHash.get(internalTableName.c_str());
959   if (info == 0)
960   {
961     NdbTableImpl *tab=
962       fetchGlobalTableImplRef(InitTable(this, internalTableName));
963     if (tab)
964     {
965       info= Ndb_local_table_info::create(tab, m_local_table_data_size);
966       if (info)
967       {
968         m_localHash.put(internalTableName.c_str(), info);
969       }
970     }
971   }
972   DBUG_RETURN(info); // autoincrement already initialized
973 }
974 
975 class InitIndex : public GlobalCacheInitObject
976 {
977 public:
978   const char *m_index_name;
979   const NdbTableImpl &m_prim;
980 
InitIndex(const BaseString & internal_indexname,const char * index_name,const NdbTableImpl & prim)981   InitIndex(const BaseString &internal_indexname,
982 	    const char *index_name,
983 	    const NdbTableImpl &prim) :
984     GlobalCacheInitObject(0, internal_indexname),
985     m_index_name(index_name),
986     m_prim(prim)
987     {}
988 
init(NdbTableImpl & tab) const989   int init(NdbTableImpl &tab) const {
990     DBUG_ENTER("InitIndex::init");
991     DBUG_ASSERT(tab.m_indexType != NdbDictionary::Object::TypeUndefined);
992     /**
993      * Create index impl
994      */
995     NdbIndexImpl* idx;
996     if(NdbDictInterface::create_index_obj_from_table(&idx, &tab, &m_prim) == 0)
997     {
998       idx->m_table = &tab;
999       if (!idx->m_externalName.assign(m_index_name) ||
1000           !idx->m_internalName.assign(m_name))
1001         DBUG_RETURN(4000);
1002       tab.m_index = idx;
1003       DBUG_RETURN(0);
1004     }
1005     DBUG_RETURN(1);
1006   }
1007 };
1008 
1009 inline
1010 NdbIndexImpl *
getIndexGlobal(const char * index_name,NdbTableImpl & ndbtab)1011 NdbDictionaryImpl::getIndexGlobal(const char * index_name,
1012                                   NdbTableImpl &ndbtab)
1013 {
1014   DBUG_ENTER("NdbDictionaryImpl::getIndexGlobal");
1015   const BaseString
1016     internal_indexname(m_ndb.internalize_index_name(&ndbtab, index_name));
1017   int retry= 2;
1018 
1019   while (retry)
1020   {
1021     NdbTableImpl *tab=
1022       fetchGlobalTableImplRef(InitIndex(internal_indexname,
1023 					index_name, ndbtab));
1024     if (tab)
1025     {
1026       // tab->m_index sould be set. otherwise tab == 0
1027       NdbIndexImpl *idx= tab->m_index;
1028       if (idx->m_table_id != (unsigned)ndbtab.getObjectId() ||
1029           idx->m_table_version != (unsigned)ndbtab.getObjectVersion())
1030       {
1031         releaseIndexGlobal(*idx, 1);
1032         retry--;
1033         continue;
1034       }
1035       DBUG_RETURN(idx);
1036     }
1037     break;
1038   }
1039   {
1040     // Index not found, try old format
1041     const BaseString
1042       old_internal_indexname(m_ndb.old_internalize_index_name(&ndbtab,
1043 							      index_name));
1044     retry= 2;
1045     while (retry)
1046     {
1047       NdbTableImpl *tab=
1048 	fetchGlobalTableImplRef(InitIndex(old_internal_indexname,
1049 					  index_name, ndbtab));
1050       if (tab)
1051       {
1052 	// tab->m_index sould be set. otherwise tab == 0
1053 	NdbIndexImpl *idx= tab->m_index;
1054 	if (idx->m_table_id != (unsigned)ndbtab.getObjectId() ||
1055 	    idx->m_table_version != (unsigned)ndbtab.getObjectVersion())
1056 	{
1057 	  releaseIndexGlobal(*idx, 1);
1058 	  retry--;
1059 	  continue;
1060 	}
1061 	DBUG_RETURN(idx);
1062       }
1063       break;
1064     }
1065   }
1066   m_error.code= 4243;
1067   DBUG_RETURN(0);
1068 }
1069 
1070 inline int
releaseTableGlobal(NdbTableImpl & impl,int invalidate)1071 NdbDictionaryImpl::releaseTableGlobal(NdbTableImpl & impl, int invalidate)
1072 {
1073   DBUG_ENTER("NdbDictionaryImpl::releaseTableGlobal");
1074   DBUG_PRINT("enter", ("internal_name: %s", impl.m_internalName.c_str()));
1075   m_globalHash->lock();
1076   m_globalHash->release(&impl, invalidate);
1077   m_globalHash->unlock();
1078   DBUG_RETURN(0);
1079 }
1080 
1081 inline int
releaseIndexGlobal(NdbIndexImpl & impl,int invalidate)1082 NdbDictionaryImpl::releaseIndexGlobal(NdbIndexImpl & impl, int invalidate)
1083 {
1084   DBUG_ENTER("NdbDictionaryImpl::releaseIndexGlobal");
1085   DBUG_PRINT("enter", ("internal_name: %s", impl.m_internalName.c_str()));
1086   m_globalHash->lock();
1087   m_globalHash->release(impl.m_table, invalidate);
1088   m_globalHash->unlock();
1089   DBUG_RETURN(0);
1090 }
1091 
1092 inline
1093 NdbIndexImpl *
getIndex(const char * index_name,const char * table_name)1094 NdbDictionaryImpl::getIndex(const char * index_name,
1095 			    const char * table_name)
1096 {
1097   if (table_name == 0)
1098   {
1099     assert(0);
1100     m_error.code= 4243;
1101     return 0;
1102   }
1103 
1104 
1105   NdbTableImpl* prim = getTable(table_name);
1106   if (prim == 0)
1107   {
1108     m_error.code= 4243;
1109     return 0;
1110   }
1111 
1112   return getIndex(index_name, *prim);
1113 }
1114 
1115 inline
1116 NdbIndexImpl *
getIndex(const char * index_name,const NdbTableImpl & prim)1117 NdbDictionaryImpl::getIndex(const char* index_name,
1118 			    const NdbTableImpl& prim)
1119 {
1120 
1121   const BaseString
1122     internal_indexname(m_ndb.internalize_index_name(&prim, index_name));
1123 
1124   Ndb_local_table_info *info= m_localHash.get(internal_indexname.c_str());
1125   NdbTableImpl *tab;
1126   if (info == 0)
1127   {
1128     tab= fetchGlobalTableImplRef(InitIndex(internal_indexname,
1129 					   index_name,
1130 					   prim));
1131     if (!tab)
1132       goto retry;
1133 
1134     info= Ndb_local_table_info::create(tab, 0);
1135     if (!info)
1136       goto retry;
1137     m_localHash.put(internal_indexname.c_str(), info);
1138   }
1139   else
1140     tab= info->m_table_impl;
1141 
1142   return tab->m_index;
1143 
1144 retry:
1145   // Index not found, try fetching it from current database
1146   const BaseString
1147     old_internal_indexname(m_ndb.old_internalize_index_name(&prim, index_name));
1148 
1149   info= m_localHash.get(old_internal_indexname.c_str());
1150   if (info == 0)
1151   {
1152     tab= fetchGlobalTableImplRef(InitIndex(old_internal_indexname,
1153 					   index_name,
1154 					   prim));
1155     if (!tab)
1156       goto err;
1157 
1158     info= Ndb_local_table_info::create(tab, 0);
1159     if (!info)
1160       goto err;
1161     m_localHash.put(old_internal_indexname.c_str(), info);
1162   }
1163   else
1164     tab= info->m_table_impl;
1165 
1166   return tab->m_index;
1167 
1168 err:
1169   m_error.code= 4243;
1170   return 0;
1171 }
1172 
1173 inline
1174 NdbTablespaceImpl &
getImpl(NdbDictionary::Tablespace & t)1175 NdbTablespaceImpl::getImpl(NdbDictionary::Tablespace & t){
1176   return t.m_impl;
1177 }
1178 
1179 inline
1180 const NdbTablespaceImpl &
getImpl(const NdbDictionary::Tablespace & t)1181 NdbTablespaceImpl::getImpl(const NdbDictionary::Tablespace & t){
1182   return t.m_impl;
1183 }
1184 
1185 inline
1186 NdbLogfileGroupImpl &
getImpl(NdbDictionary::LogfileGroup & t)1187 NdbLogfileGroupImpl::getImpl(NdbDictionary::LogfileGroup & t){
1188   return t.m_impl;
1189 }
1190 
1191 inline
1192 const NdbLogfileGroupImpl &
getImpl(const NdbDictionary::LogfileGroup & t)1193 NdbLogfileGroupImpl::getImpl(const NdbDictionary::LogfileGroup & t){
1194   return t.m_impl;
1195 }
1196 
1197 inline
1198 NdbDatafileImpl &
getImpl(NdbDictionary::Datafile & t)1199 NdbDatafileImpl::getImpl(NdbDictionary::Datafile & t){
1200   return t.m_impl;
1201 }
1202 
1203 inline
1204 const NdbDatafileImpl &
getImpl(const NdbDictionary::Datafile & t)1205 NdbDatafileImpl::getImpl(const NdbDictionary::Datafile & t){
1206   return t.m_impl;
1207 }
1208 
1209 inline
1210 NdbUndofileImpl &
getImpl(NdbDictionary::Undofile & t)1211 NdbUndofileImpl::getImpl(NdbDictionary::Undofile & t){
1212   return t.m_impl;
1213 }
1214 
1215 inline
1216 const NdbUndofileImpl &
getImpl(const NdbDictionary::Undofile & t)1217 NdbUndofileImpl::getImpl(const NdbDictionary::Undofile & t){
1218   return t.m_impl;
1219 }
1220 
1221 #endif
1222