1 /* Copyright (c) 2003-2008 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 #include "NdbDictionaryImpl.hpp"
18 #include "API.hpp"
19 #include <NdbOut.hpp>
20 #include "NdbApiSignal.hpp"
21 #include "TransporterFacade.hpp"
22 #include <signaldata/GetTabInfo.hpp>
23 #include <signaldata/DictTabInfo.hpp>
24 #include <signaldata/CreateTable.hpp>
25 #include <signaldata/CreateIndx.hpp>
26 #include <signaldata/CreateEvnt.hpp>
27 #include <signaldata/SumaImpl.hpp>
28 #include <signaldata/DropTable.hpp>
29 #include <signaldata/AlterTable.hpp>
30 #include <signaldata/DropIndx.hpp>
31 #include <signaldata/ListTables.hpp>
32 #include <signaldata/DropFilegroup.hpp>
33 #include <signaldata/CreateFilegroup.hpp>
34 #include <signaldata/WaitGCP.hpp>
35 #include <SimpleProperties.hpp>
36 #include <Bitmask.hpp>
37 #include <AttributeList.hpp>
38 #include <NdbEventOperation.hpp>
39 #include "NdbEventOperationImpl.hpp"
40 #include <NdbBlob.hpp>
41 #include "NdbBlobImpl.hpp"
42 #include <AttributeHeader.hpp>
43 #include <my_sys.h>
44 #include <NdbEnv.h>
45 #include <NdbMem.h>
46 #include <util/version.h>
47 #include <NdbSleep.h>
48 
49 #define DEBUG_PRINT 0
50 #define INCOMPATIBLE_VERSION -2
51 
52 #define DICT_WAITFOR_TIMEOUT (7*24*60*60*1000)
53 
54 #define ERR_RETURN(a,b) \
55 {\
56    DBUG_PRINT("exit", ("error %d  return %d", (a).code, b));\
57    DBUG_RETURN(b);\
58 }
59 
60 int ndb_dictionary_is_mysqld = 0;
61 
62 bool
is_ndb_blob_table(const char * name,Uint32 * ptab_id,Uint32 * pcol_no)63 is_ndb_blob_table(const char* name, Uint32* ptab_id, Uint32* pcol_no)
64 {
65   return DictTabInfo::isBlobTableName(name, ptab_id, pcol_no);
66 }
67 
68 bool
is_ndb_blob_table(const NdbTableImpl * t)69 is_ndb_blob_table(const NdbTableImpl* t)
70 {
71   return is_ndb_blob_table(t->m_internalName.c_str());
72 }
73 
74 //#define EVENT_DEBUG
75 
76 /**
77  * Column
78  */
NdbColumnImpl()79 NdbColumnImpl::NdbColumnImpl()
80   : NdbDictionary::Column(* this), m_attrId(-1), m_facade(this)
81 {
82   DBUG_ENTER("NdbColumnImpl::NdbColumnImpl");
83   DBUG_PRINT("info", ("this: %p", this));
84   init();
85   DBUG_VOID_RETURN;
86 }
87 
NdbColumnImpl(NdbDictionary::Column & f)88 NdbColumnImpl::NdbColumnImpl(NdbDictionary::Column & f)
89   : NdbDictionary::Column(* this), m_attrId(-1), m_facade(&f)
90 {
91   DBUG_ENTER("NdbColumnImpl::NdbColumnImpl");
92   DBUG_PRINT("info", ("this: %p", this));
93   init();
94   DBUG_VOID_RETURN;
95 }
96 
97 NdbColumnImpl&
operator =(const NdbColumnImpl & col)98 NdbColumnImpl::operator=(const NdbColumnImpl& col)
99 {
100   DBUG_ENTER("NdbColumnImpl::operator=");
101   DBUG_PRINT("info", ("this: %p  &col: %p", this, &col));
102   m_attrId = col.m_attrId;
103   m_name = col.m_name;
104   m_type = col.m_type;
105   m_precision = col.m_precision;
106   m_cs = col.m_cs;
107   m_scale = col.m_scale;
108   m_length = col.m_length;
109   m_pk = col.m_pk;
110   m_distributionKey = col.m_distributionKey;
111   m_nullable = col.m_nullable;
112   m_autoIncrement = col.m_autoIncrement;
113   m_autoIncrementInitialValue = col.m_autoIncrementInitialValue;
114   m_defaultValue = col.m_defaultValue;
115   m_attrSize = col.m_attrSize;
116   m_arraySize = col.m_arraySize;
117   m_arrayType = col.m_arrayType;
118   m_storageType = col.m_storageType;
119   m_keyInfoPos = col.m_keyInfoPos;
120   if (col.m_blobTable == NULL)
121     m_blobTable = NULL;
122   else {
123     if (m_blobTable == NULL)
124       m_blobTable = new NdbTableImpl();
125     m_blobTable->assign(*col.m_blobTable);
126   }
127   m_column_no = col.m_column_no;
128   // Do not copy m_facade !!
129 
130   DBUG_RETURN(*this);
131 }
132 
133 void
init(Type t)134 NdbColumnImpl::init(Type t)
135 {
136   // do not use default_charset_info as it may not be initialized yet
137   // use binary collation until NDB tests can handle charsets
138   CHARSET_INFO* default_cs = &my_charset_bin;
139   m_type = t;
140   switch (m_type) {
141   case Tinyint:
142   case Tinyunsigned:
143   case Smallint:
144   case Smallunsigned:
145   case Mediumint:
146   case Mediumunsigned:
147   case Int:
148   case Unsigned:
149   case Bigint:
150   case Bigunsigned:
151   case Float:
152   case Double:
153     m_precision = 0;
154     m_scale = 0;
155     m_length = 1;
156     m_cs = NULL;
157     m_arrayType = NDB_ARRAYTYPE_FIXED;
158     break;
159   case Olddecimal:
160   case Olddecimalunsigned:
161   case Decimal:
162   case Decimalunsigned:
163     m_precision = 10;
164     m_scale = 0;
165     m_length = 1;
166     m_cs = NULL;
167     m_arrayType = NDB_ARRAYTYPE_FIXED;
168     break;
169   case Char:
170     m_precision = 0;
171     m_scale = 0;
172     m_length = 1;
173     m_cs = default_cs;
174     m_arrayType = NDB_ARRAYTYPE_FIXED;
175     break;
176   case Varchar:
177     m_precision = 0;
178     m_scale = 0;
179     m_length = 1;
180     m_cs = default_cs;
181     m_arrayType = NDB_ARRAYTYPE_SHORT_VAR;
182     break;
183   case Binary:
184     m_precision = 0;
185     m_scale = 0;
186     m_length = 1;
187     m_cs = NULL;
188     m_arrayType = NDB_ARRAYTYPE_FIXED;
189     break;
190   case Varbinary:
191     m_precision = 0;
192     m_scale = 0;
193     m_length = 1;
194     m_cs = NULL;
195     m_arrayType = NDB_ARRAYTYPE_SHORT_VAR;
196     break;
197   case Datetime:
198   case Date:
199     m_precision = 0;
200     m_scale = 0;
201     m_length = 1;
202     m_cs = NULL;
203     m_arrayType = NDB_ARRAYTYPE_FIXED;
204     break;
205   case Blob:
206     m_precision = 256;
207     m_scale = 8000;
208     m_length = 4;
209     m_cs = NULL;
210     m_arrayType = NDB_ARRAYTYPE_FIXED;
211     break;
212   case Text:
213     m_precision = 256;
214     m_scale = 8000;
215     m_length = 4;
216     m_cs = default_cs;
217     m_arrayType = NDB_ARRAYTYPE_FIXED;
218     break;
219   case Time:
220   case Year:
221   case Timestamp:
222     m_precision = 0;
223     m_scale = 0;
224     m_length = 1;
225     m_cs = NULL;
226     m_arrayType = NDB_ARRAYTYPE_FIXED;
227     break;
228   case Bit:
229     m_precision = 0;
230     m_scale = 0;
231     m_length = 1;
232     m_cs = NULL;
233     m_arrayType = NDB_ARRAYTYPE_FIXED;
234     break;
235   case Longvarchar:
236     m_precision = 0;
237     m_scale = 0;
238     m_length = 1; // legal
239     m_cs = default_cs;
240     m_arrayType = NDB_ARRAYTYPE_MEDIUM_VAR;
241     break;
242   case Longvarbinary:
243     m_precision = 0;
244     m_scale = 0;
245     m_length = 1; // legal
246     m_cs = NULL;
247     m_arrayType = NDB_ARRAYTYPE_MEDIUM_VAR;
248     break;
249   default:
250   case Undefined:
251     assert(false);
252     break;
253   }
254   m_pk = false;
255   m_nullable = false;
256   m_distributionKey = false;
257   m_keyInfoPos = 0;
258   // next 2 are set at run time
259   m_attrSize = 0;
260   m_arraySize = 0;
261   m_autoIncrement = false;
262   m_autoIncrementInitialValue = 1;
263   m_blobTable = NULL;
264   m_storageType = NDB_STORAGETYPE_MEMORY;
265 #ifdef VM_TRACE
266   if(NdbEnv_GetEnv("NDB_DEFAULT_DISK", (char *)0, 0))
267     m_storageType = NDB_STORAGETYPE_DISK;
268 #endif
269 }
270 
~NdbColumnImpl()271 NdbColumnImpl::~NdbColumnImpl()
272 {
273   DBUG_ENTER("NdbColumnImpl::~NdbColumnImpl");
274   DBUG_PRINT("info", ("this: %p", this));
275   if (m_blobTable != NULL)
276     delete m_blobTable;
277   m_blobTable = NULL;
278   DBUG_VOID_RETURN;
279 }
280 
281 bool
equal(const NdbColumnImpl & col) const282 NdbColumnImpl::equal(const NdbColumnImpl& col) const
283 {
284   DBUG_ENTER("NdbColumnImpl::equal");
285   DBUG_PRINT("info", ("this: %p  &col: %p", this, &col));
286   if(strcmp(m_name.c_str(), col.m_name.c_str()) != 0){
287     DBUG_RETURN(false);
288   }
289   if(m_type != col.m_type){
290     DBUG_RETURN(false);
291   }
292   if(m_pk != col.m_pk){
293     DBUG_RETURN(false);
294   }
295   if(m_nullable != col.m_nullable){
296     DBUG_RETURN(false);
297   }
298   if (m_pk) {
299     if (m_distributionKey != col.m_distributionKey) {
300       DBUG_RETURN(false);
301     }
302   }
303   if (m_precision != col.m_precision ||
304       m_scale != col.m_scale ||
305       m_length != col.m_length ||
306       m_cs != col.m_cs) {
307     DBUG_RETURN(false);
308   }
309   if (m_autoIncrement != col.m_autoIncrement){
310     DBUG_RETURN(false);
311   }
312   if(strcmp(m_defaultValue.c_str(), col.m_defaultValue.c_str()) != 0){
313     DBUG_RETURN(false);
314   }
315 
316   if (m_arrayType != col.m_arrayType || m_storageType != col.m_storageType){
317     DBUG_RETURN(false);
318   }
319 
320   DBUG_RETURN(true);
321 }
322 
323 NdbDictionary::Column *
create_pseudo(const char * name)324 NdbColumnImpl::create_pseudo(const char * name){
325   NdbDictionary::Column * col = new NdbDictionary::Column();
326   col->setName(name);
327   if(!strcmp(name, "NDB$FRAGMENT")){
328     col->setType(NdbDictionary::Column::Unsigned);
329     col->m_impl.m_attrId = AttributeHeader::FRAGMENT;
330     col->m_impl.m_attrSize = 4;
331     col->m_impl.m_arraySize = 1;
332   } else if(!strcmp(name, "NDB$FRAGMENT_FIXED_MEMORY")){
333     col->setType(NdbDictionary::Column::Bigunsigned);
334     col->m_impl.m_attrId = AttributeHeader::FRAGMENT_FIXED_MEMORY;
335     col->m_impl.m_attrSize = 8;
336     col->m_impl.m_arraySize = 1;
337   } else if(!strcmp(name, "NDB$FRAGMENT_VARSIZED_MEMORY")){
338     col->setType(NdbDictionary::Column::Bigunsigned);
339     col->m_impl.m_attrId = AttributeHeader::FRAGMENT_VARSIZED_MEMORY;
340     col->m_impl.m_attrSize = 8;
341     col->m_impl.m_arraySize = 1;
342   } else if(!strcmp(name, "NDB$ROW_COUNT")){
343     col->setType(NdbDictionary::Column::Bigunsigned);
344     col->m_impl.m_attrId = AttributeHeader::ROW_COUNT;
345     col->m_impl.m_attrSize = 8;
346     col->m_impl.m_arraySize = 1;
347   } else if(!strcmp(name, "NDB$COMMIT_COUNT")){
348     col->setType(NdbDictionary::Column::Bigunsigned);
349     col->m_impl.m_attrId = AttributeHeader::COMMIT_COUNT;
350     col->m_impl.m_attrSize = 8;
351     col->m_impl.m_arraySize = 1;
352   } else if(!strcmp(name, "NDB$ROW_SIZE")){
353     col->setType(NdbDictionary::Column::Unsigned);
354     col->m_impl.m_attrId = AttributeHeader::ROW_SIZE;
355     col->m_impl.m_attrSize = 4;
356     col->m_impl.m_arraySize = 1;
357   } else if(!strcmp(name, "NDB$RANGE_NO")){
358     col->setType(NdbDictionary::Column::Unsigned);
359     col->m_impl.m_attrId = AttributeHeader::RANGE_NO;
360     col->m_impl.m_attrSize = 4;
361     col->m_impl.m_arraySize = 1;
362   } else if(!strcmp(name, "NDB$DISK_REF")){
363     col->setType(NdbDictionary::Column::Bigunsigned);
364     col->m_impl.m_attrId = AttributeHeader::DISK_REF;
365     col->m_impl.m_attrSize = 8;
366     col->m_impl.m_arraySize = 1;
367   } else if(!strcmp(name, "NDB$RECORDS_IN_RANGE")){
368     col->setType(NdbDictionary::Column::Unsigned);
369     col->m_impl.m_attrId = AttributeHeader::RECORDS_IN_RANGE;
370     col->m_impl.m_attrSize = 4;
371     col->m_impl.m_arraySize = 4;
372   } else if(!strcmp(name, "NDB$ROWID")){
373     col->setType(NdbDictionary::Column::Bigunsigned);
374     col->m_impl.m_attrId = AttributeHeader::ROWID;
375     col->m_impl.m_attrSize = 4;
376     col->m_impl.m_arraySize = 2;
377   } else if(!strcmp(name, "NDB$ROW_GCI")){
378     col->setType(NdbDictionary::Column::Bigunsigned);
379     col->m_impl.m_attrId = AttributeHeader::ROW_GCI;
380     col->m_impl.m_attrSize = 8;
381     col->m_impl.m_arraySize = 1;
382     col->m_impl.m_nullable = true;
383   } else if(!strcmp(name, "NDB$ANY_VALUE")){
384     col->setType(NdbDictionary::Column::Unsigned);
385     col->m_impl.m_attrId = AttributeHeader::ANY_VALUE;
386     col->m_impl.m_attrSize = 4;
387     col->m_impl.m_arraySize = 1;
388   } else if(!strcmp(name, "NDB$COPY_ROWID")){
389     col->setType(NdbDictionary::Column::Bigunsigned);
390     col->m_impl.m_attrId = AttributeHeader::COPY_ROWID;
391     col->m_impl.m_attrSize = 4;
392     col->m_impl.m_arraySize = 2;
393   } else {
394     abort();
395   }
396   col->m_impl.m_storageType = NDB_STORAGETYPE_MEMORY;
397   return col;
398 }
399 
400 /**
401  * NdbTableImpl
402  */
403 
NdbTableImpl()404 NdbTableImpl::NdbTableImpl()
405   : NdbDictionary::Table(* this),
406     NdbDictObjectImpl(NdbDictionary::Object::UserTable), m_facade(this)
407 {
408   DBUG_ENTER("NdbTableImpl::NdbTableImpl");
409   DBUG_PRINT("info", ("this: %p", this));
410   init();
411   DBUG_VOID_RETURN;
412 }
413 
NdbTableImpl(NdbDictionary::Table & f)414 NdbTableImpl::NdbTableImpl(NdbDictionary::Table & f)
415   : NdbDictionary::Table(* this),
416     NdbDictObjectImpl(NdbDictionary::Object::UserTable), m_facade(&f)
417 {
418   DBUG_ENTER("NdbTableImpl::NdbTableImpl");
419   DBUG_PRINT("info", ("this: %p", this));
420   init();
421   DBUG_VOID_RETURN;
422 }
423 
~NdbTableImpl()424 NdbTableImpl::~NdbTableImpl()
425 {
426   DBUG_ENTER("NdbTableImpl::~NdbTableImpl");
427   DBUG_PRINT("info", ("this: %p", this));
428   if (m_index != 0) {
429     delete m_index;
430     m_index = 0;
431   }
432   for (unsigned i = 0; i < m_columns.size(); i++)
433     delete m_columns[i];
434   DBUG_VOID_RETURN;
435 }
436 
437 void
init()438 NdbTableImpl::init(){
439   m_changeMask= 0;
440   m_id= RNIL;
441   m_version = ~0;
442   m_status = NdbDictionary::Object::Invalid;
443   m_type = NdbDictionary::Object::TypeUndefined;
444   m_primaryTableId= RNIL;
445   m_internalName.clear();
446   m_externalName.clear();
447   m_newExternalName.clear();
448   m_mysqlName.clear();
449   m_frm.clear();
450   m_newFrm.clear();
451   m_ts_name.clear();
452   m_new_ts_name.clear();
453   m_ts.clear();
454   m_new_ts.clear();
455   m_fd.clear();
456   m_new_fd.clear();
457   m_range.clear();
458   m_new_range.clear();
459   m_fragmentType= NdbDictionary::Object::FragAllSmall;
460   m_hashValueMask= 0;
461   m_hashpointerValue= 0;
462   m_linear_flag= true;
463   m_primaryTable.clear();
464   m_default_no_part_flag = 1;
465   m_logging= true;
466   m_temporary = false;
467   m_row_gci = true;
468   m_row_checksum = true;
469   m_force_var_part = false;
470   m_kvalue= 6;
471   m_minLoadFactor= 78;
472   m_maxLoadFactor= 80;
473   m_keyLenInWords= 0;
474   m_fragmentCount= 0;
475   m_index= NULL;
476   m_indexType= NdbDictionary::Object::TypeUndefined;
477   m_noOfKeys= 0;
478   m_noOfDistributionKeys= 0;
479   m_noOfBlobs= 0;
480   m_replicaCount= 0;
481   m_min_rows = 0;
482   m_max_rows = 0;
483   m_tablespace_name.clear();
484   m_tablespace_id = ~0;
485   m_tablespace_version = ~0;
486   m_single_user_mode = 0;
487 }
488 
489 bool
equal(const NdbTableImpl & obj) const490 NdbTableImpl::equal(const NdbTableImpl& obj) const
491 {
492   DBUG_ENTER("NdbTableImpl::equal");
493   if ((m_internalName.c_str() == NULL) ||
494       (strcmp(m_internalName.c_str(), "") == 0) ||
495       (obj.m_internalName.c_str() == NULL) ||
496       (strcmp(obj.m_internalName.c_str(), "") == 0))
497   {
498     // Shallow equal
499     if(strcmp(getName(), obj.getName()) != 0)
500     {
501       DBUG_PRINT("info",("name %s != %s",getName(),obj.getName()));
502       DBUG_RETURN(false);
503     }
504   }
505   else
506   {
507     // Deep equal
508     if(strcmp(m_internalName.c_str(), obj.m_internalName.c_str()) != 0)
509     {
510       DBUG_PRINT("info",("m_internalName %s != %s",
511 			 m_internalName.c_str(),obj.m_internalName.c_str()));
512       DBUG_RETURN(false);
513     }
514   }
515   if (m_frm.length() != obj.m_frm.length() ||
516       (memcmp(m_frm.get_data(), obj.m_frm.get_data(), m_frm.length())))
517   {
518     DBUG_PRINT("info",("m_frm not equal"));
519     DBUG_RETURN(false);
520   }
521   if (m_fd.length() != obj.m_fd.length() ||
522       (memcmp(m_fd.get_data(), obj.m_fd.get_data(), m_fd.length())))
523   {
524     DBUG_PRINT("info",("m_fd not equal"));
525     DBUG_RETURN(false);
526   }
527   if (m_ts.length() != obj.m_ts.length() ||
528       (memcmp(m_ts.get_data(), obj.m_ts.get_data(), m_ts.length())))
529   {
530     DBUG_PRINT("info",("m_ts not equal"));
531     DBUG_RETURN(false);
532   }
533   if (m_range.length() != obj.m_range.length() ||
534       (memcmp(m_range.get_data(), obj.m_range.get_data(), m_range.length())))
535   {
536     DBUG_PRINT("info",("m_range not equal"));
537     DBUG_RETURN(false);
538   }
539   if(m_fragmentType != obj.m_fragmentType)
540   {
541     DBUG_PRINT("info",("m_fragmentType %d != %d",m_fragmentType,
542                         obj.m_fragmentType));
543     DBUG_RETURN(false);
544   }
545   if(m_columns.size() != obj.m_columns.size())
546   {
547     DBUG_PRINT("info",("m_columns.size %d != %d",m_columns.size(),
548                        obj.m_columns.size()));
549     DBUG_RETURN(false);
550   }
551 
552   for(unsigned i = 0; i<obj.m_columns.size(); i++)
553   {
554     if(!m_columns[i]->equal(* obj.m_columns[i]))
555     {
556       DBUG_PRINT("info",("m_columns [%d] != [%d]",i,i));
557       DBUG_RETURN(false);
558     }
559   }
560 
561   if(m_linear_flag != obj.m_linear_flag)
562   {
563     DBUG_PRINT("info",("m_linear_flag %d != %d",m_linear_flag,
564                         obj.m_linear_flag));
565     DBUG_RETURN(false);
566   }
567 
568   if(m_max_rows != obj.m_max_rows)
569   {
570     DBUG_PRINT("info",("m_max_rows %d != %d",(int32)m_max_rows,
571                        (int32)obj.m_max_rows));
572     DBUG_RETURN(false);
573   }
574 
575   if(m_default_no_part_flag != obj.m_default_no_part_flag)
576   {
577     DBUG_PRINT("info",("m_default_no_part_flag %d != %d",m_default_no_part_flag,
578                         obj.m_default_no_part_flag));
579     DBUG_RETURN(false);
580   }
581 
582   if(m_logging != obj.m_logging)
583   {
584     DBUG_PRINT("info",("m_logging %d != %d",m_logging,obj.m_logging));
585     DBUG_RETURN(false);
586   }
587 
588   if(m_temporary != obj.m_temporary)
589   {
590     DBUG_PRINT("info",("m_temporary %d != %d",m_temporary,obj.m_temporary));
591     DBUG_RETURN(false);
592   }
593 
594   if(m_row_gci != obj.m_row_gci)
595   {
596     DBUG_PRINT("info",("m_row_gci %d != %d",m_row_gci,obj.m_row_gci));
597     DBUG_RETURN(false);
598   }
599 
600   if(m_row_checksum != obj.m_row_checksum)
601   {
602     DBUG_PRINT("info",("m_row_checksum %d != %d",m_row_checksum,
603                         obj.m_row_checksum));
604     DBUG_RETURN(false);
605   }
606 
607   if(m_kvalue != obj.m_kvalue)
608   {
609     DBUG_PRINT("info",("m_kvalue %d != %d",m_kvalue,obj.m_kvalue));
610     DBUG_RETURN(false);
611   }
612 
613   if(m_minLoadFactor != obj.m_minLoadFactor)
614   {
615     DBUG_PRINT("info",("m_minLoadFactor %d != %d",m_minLoadFactor,
616                         obj.m_minLoadFactor));
617     DBUG_RETURN(false);
618   }
619 
620   if(m_maxLoadFactor != obj.m_maxLoadFactor)
621   {
622     DBUG_PRINT("info",("m_maxLoadFactor %d != %d",m_maxLoadFactor,
623                         obj.m_maxLoadFactor));
624     DBUG_RETURN(false);
625   }
626 
627   if(m_tablespace_id != obj.m_tablespace_id)
628   {
629     DBUG_PRINT("info",("m_tablespace_id %d != %d",m_tablespace_id,
630                         obj.m_tablespace_id));
631     DBUG_RETURN(false);
632   }
633 
634   if(m_tablespace_version != obj.m_tablespace_version)
635   {
636     DBUG_PRINT("info",("m_tablespace_version %d != %d",m_tablespace_version,
637                         obj.m_tablespace_version));
638     DBUG_RETURN(false);
639   }
640 
641   if(m_id != obj.m_id)
642   {
643     DBUG_PRINT("info",("m_id %d != %d",m_id,obj.m_id));
644     DBUG_RETURN(false);
645   }
646 
647   if(m_version != obj.m_version)
648   {
649     DBUG_PRINT("info",("m_version %d != %d",m_version,obj.m_version));
650     DBUG_RETURN(false);
651   }
652 
653   if(m_type != obj.m_type)
654   {
655     DBUG_PRINT("info",("m_type %d != %d",m_type,obj.m_type));
656     DBUG_RETURN(false);
657   }
658 
659   if (m_type == NdbDictionary::Object::UniqueHashIndex ||
660       m_type == NdbDictionary::Object::OrderedIndex)
661   {
662     if(m_primaryTableId != obj.m_primaryTableId)
663     {
664       DBUG_PRINT("info",("m_primaryTableId %d != %d",m_primaryTableId,
665                  obj.m_primaryTableId));
666       DBUG_RETURN(false);
667     }
668     if (m_indexType != obj.m_indexType)
669     {
670       DBUG_PRINT("info",("m_indexType %d != %d",m_indexType,obj.m_indexType));
671       DBUG_RETURN(false);
672     }
673     if(strcmp(m_primaryTable.c_str(), obj.m_primaryTable.c_str()) != 0)
674     {
675       DBUG_PRINT("info",("m_primaryTable %s != %s",
676 			 m_primaryTable.c_str(),obj.m_primaryTable.c_str()));
677       DBUG_RETURN(false);
678     }
679   }
680 
681   if(m_single_user_mode != obj.m_single_user_mode)
682   {
683     DBUG_PRINT("info",("m_single_user_mode %d != %d",
684                        (int32)m_single_user_mode,
685                        (int32)obj.m_single_user_mode));
686     DBUG_RETURN(false);
687   }
688 
689   DBUG_RETURN(true);
690 }
691 
692 int
assign(const NdbTableImpl & org)693 NdbTableImpl::assign(const NdbTableImpl& org)
694 {
695   DBUG_ENTER("NdbColumnImpl::assign");
696   DBUG_PRINT("info", ("this: %p  &org: %p", this, &org));
697   /* m_changeMask intentionally not copied */
698   m_primaryTableId = org.m_primaryTableId;
699   if (!m_internalName.assign(org.m_internalName) ||
700       updateMysqlName())
701   {
702     return -1;
703   }
704   // If the name has been explicitly set, use that name
705   // otherwise use the fetched name
706   if (!org.m_newExternalName.empty())
707     m_externalName.assign(org.m_newExternalName);
708   else
709     m_externalName.assign(org.m_externalName);
710   m_frm.assign(org.m_frm.get_data(), org.m_frm.length());
711   m_ts_name.assign(org.m_ts_name.get_data(), org.m_ts_name.length());
712   m_new_ts_name.assign(org.m_new_ts_name.get_data(),
713                        org.m_new_ts_name.length());
714   m_ts.assign(org.m_ts.get_data(), org.m_ts.length());
715   m_new_ts.assign(org.m_new_ts.get_data(), org.m_new_ts.length());
716   m_fd.assign(org.m_fd.get_data(), org.m_fd.length());
717   m_new_fd.assign(org.m_new_fd.get_data(), org.m_new_fd.length());
718   m_range.assign(org.m_range.get_data(), org.m_range.length());
719   m_new_range.assign(org.m_new_range.get_data(), org.m_new_range.length());
720 
721   m_fragmentType = org.m_fragmentType;
722   /*
723     m_columnHashMask, m_columnHash, m_hashValueMask, m_hashpointerValue
724     is state calculated by computeAggregates and buildColumnHash
725   */
726   unsigned i;
727   for(i = 0; i < m_columns.size(); i++)
728   {
729     delete m_columns[i];
730   }
731   m_columns.clear();
732   for(i = 0; i < org.m_columns.size(); i++)
733   {
734     NdbColumnImpl * col = new NdbColumnImpl();
735     if (col == NULL)
736     {
737       errno = ENOMEM;
738       return -1;
739     }
740     const NdbColumnImpl * iorg = org.m_columns[i];
741     (* col) = (* iorg);
742     if (m_columns.push_back(col))
743     {
744       delete col;
745       return -1;
746     }
747   }
748 
749   m_fragments = org.m_fragments;
750 
751   m_linear_flag = org.m_linear_flag;
752   m_max_rows = org.m_max_rows;
753   m_default_no_part_flag = org.m_default_no_part_flag;
754   m_logging = org.m_logging;
755   m_temporary = org.m_temporary;
756   m_row_gci = org.m_row_gci;
757   m_row_checksum = org.m_row_checksum;
758   m_force_var_part = org.m_force_var_part;
759   m_kvalue = org.m_kvalue;
760   m_minLoadFactor = org.m_minLoadFactor;
761   m_maxLoadFactor = org.m_maxLoadFactor;
762   m_keyLenInWords = org.m_keyLenInWords;
763   m_fragmentCount = org.m_fragmentCount;
764 
765   m_single_user_mode = org.m_single_user_mode;
766 
767   if (m_index != 0)
768     delete m_index;
769   m_index = org.m_index;
770 
771   m_primaryTable = org.m_primaryTable;
772   m_indexType = org.m_indexType;
773 
774   m_noOfKeys = org.m_noOfKeys;
775   m_noOfDistributionKeys = org.m_noOfDistributionKeys;
776   m_noOfBlobs = org.m_noOfBlobs;
777   m_replicaCount = org.m_replicaCount;
778 
779   m_id = org.m_id;
780   m_version = org.m_version;
781   m_status = org.m_status;
782 
783   m_max_rows = org.m_max_rows;
784   m_min_rows = org.m_min_rows;
785 
786   m_tablespace_name = org.m_tablespace_name;
787   m_tablespace_id= org.m_tablespace_id;
788   m_tablespace_version = org.m_tablespace_version;
789   DBUG_RETURN(0);
790 }
791 
setName(const char * name)792 int NdbTableImpl::setName(const char * name)
793 {
794   return !m_newExternalName.assign(name);
795 }
796 
797 const char *
getName() const798 NdbTableImpl::getName() const
799 {
800   if (m_newExternalName.empty())
801     return m_externalName.c_str();
802   else
803     return m_newExternalName.c_str();
804 }
805 
806 void
computeAggregates()807 NdbTableImpl::computeAggregates()
808 {
809   m_noOfKeys = 0;
810   m_keyLenInWords = 0;
811   m_noOfDistributionKeys = 0;
812   m_noOfBlobs = 0;
813   m_noOfDiskColumns = 0;
814   Uint32 i, n;
815   for (i = 0; i < m_columns.size(); i++) {
816     NdbColumnImpl* col = m_columns[i];
817     if (col->m_pk) {
818       m_noOfKeys++;
819       m_keyLenInWords += (col->m_attrSize * col->m_arraySize + 3) / 4;
820     }
821     if (col->m_distributionKey)
822       m_noOfDistributionKeys++; // XXX check PK
823 
824     if (col->getBlobType())
825       m_noOfBlobs++;
826 
827     if (col->getStorageType() == NdbDictionary::Column::StorageTypeDisk)
828       m_noOfDiskColumns++;
829 
830     col->m_keyInfoPos = ~0;
831   }
832   if (m_noOfDistributionKeys == m_noOfKeys) {
833     // all is none!
834     m_noOfDistributionKeys = 0;
835   }
836 
837   if (m_noOfDistributionKeys == 0)
838   {
839     // none is all!
840     for (i = 0, n = m_noOfKeys; n != 0; i++) {
841       NdbColumnImpl* col = m_columns[i];
842       if (col->m_pk) {
843         col->m_distributionKey = true;
844         n--;
845       }
846     }
847   }
848 
849   Uint32 keyInfoPos = 0;
850   for (i = 0, n = m_noOfKeys; n != 0; i++) {
851     NdbColumnImpl* col = m_columns[i];
852     if (col->m_pk) {
853       col->m_keyInfoPos = keyInfoPos++;
854       n--;
855     }
856   }
857 }
858 
859 // TODO add error checks
860 // TODO use these internally at create and retrieve
861 int
aggregate(NdbError & error)862 NdbTableImpl::aggregate(NdbError& error)
863 {
864   computeAggregates();
865   return 0;
866 }
867 int
validate(NdbError & error)868 NdbTableImpl::validate(NdbError& error)
869 {
870   if (aggregate(error) == -1)
871     return -1;
872   return 0;
873 }
874 
875 const void*
getTablespaceNames() const876 NdbTableImpl::getTablespaceNames() const
877 {
878   if (m_new_ts_name.empty())
879     return m_ts_name.get_data();
880   else
881     return m_new_ts_name.get_data();
882 }
883 
884 Uint32
getTablespaceNamesLen() const885 NdbTableImpl::getTablespaceNamesLen() const
886 {
887   if (m_new_ts_name.empty())
888     return m_ts_name.length();
889   else
890     return m_new_ts_name.length();
891 }
892 
setTablespaceNames(const void * data,Uint32 len)893 int NdbTableImpl::setTablespaceNames(const void *data, Uint32 len)
894 {
895   return !m_new_ts_name.assign(data, len);
896 }
897 
setFragmentCount(Uint32 count)898 void NdbTableImpl::setFragmentCount(Uint32 count)
899 {
900   m_fragmentCount= count;
901 }
902 
getFragmentCount() const903 Uint32 NdbTableImpl::getFragmentCount() const
904 {
905   return m_fragmentCount;
906 }
907 
setFrm(const void * data,Uint32 len)908 int NdbTableImpl::setFrm(const void* data, Uint32 len)
909 {
910   return m_newFrm.assign(data, len);
911 }
912 
913 const void *
getFrmData() const914 NdbTableImpl::getFrmData() const
915 {
916   if (m_newFrm.empty())
917     return m_frm.get_data();
918   else
919     return m_newFrm.get_data();
920 }
921 
922 Uint32
getFrmLength() const923 NdbTableImpl::getFrmLength() const
924 {
925   if (m_newFrm.empty())
926     return m_frm.length();
927   else
928     return m_newFrm.length();
929 }
930 
setFragmentData(const void * data,Uint32 len)931 int NdbTableImpl::setFragmentData(const void* data, Uint32 len)
932 {
933   return m_new_fd.assign(data, len);
934 }
935 
936 const void *
getFragmentData() const937 NdbTableImpl::getFragmentData() const
938 {
939   if (m_new_fd.empty())
940     return m_fd.get_data();
941   else
942     return m_new_fd.get_data();
943 }
944 
945 Uint32
getFragmentDataLen() const946 NdbTableImpl::getFragmentDataLen() const
947 {
948   if (m_new_fd.empty())
949     return m_fd.length();
950   else
951     return m_new_fd.length();
952 }
953 
setTablespaceData(const void * data,Uint32 len)954 int NdbTableImpl::setTablespaceData(const void* data, Uint32 len)
955 {
956   return !m_new_ts.assign(data, len);
957 }
958 
959 const void *
getTablespaceData() const960 NdbTableImpl::getTablespaceData() const
961 {
962   if (m_new_ts.empty())
963     return m_ts.get_data();
964   else
965     return m_new_ts.get_data();
966 }
967 
968 Uint32
getTablespaceDataLen() const969 NdbTableImpl::getTablespaceDataLen() const
970 {
971   if (m_new_ts.empty())
972     return m_ts.length();
973   else
974     return m_new_ts.length();
975 }
976 
setRangeListData(const void * data,Uint32 len)977 int NdbTableImpl::setRangeListData(const void* data, Uint32 len)
978 {
979   return m_new_range.assign(data, len);
980 }
981 
982 const void *
getRangeListData() const983 NdbTableImpl::getRangeListData() const
984 {
985   if (m_new_range.empty())
986     return m_range.get_data();
987   else
988     return m_new_range.get_data();
989 }
990 
991 Uint32
getRangeListDataLen() const992 NdbTableImpl::getRangeListDataLen() const
993 {
994   if (m_new_range.empty())
995     return m_range.length();
996   else
997     return m_new_range.length();
998 }
999 
1000 int
updateMysqlName()1001 NdbTableImpl::updateMysqlName()
1002 {
1003   Vector<BaseString> v;
1004   if (m_internalName.split(v,"/") == 3)
1005   {
1006     return !m_mysqlName.assfmt("%s/%s",v[0].c_str(),v[2].c_str());
1007   }
1008   return !m_mysqlName.assign("");
1009 }
1010 
1011 int
buildColumnHash()1012 NdbTableImpl::buildColumnHash(){
1013   const Uint32 size = m_columns.size();
1014   int i;
1015   for(i = 31; i >= 0; i--){
1016     if(((1 << i) & size) != 0){
1017       m_columnHashMask = (1 << (i + 1)) - 1;
1018       break;
1019     }
1020   }
1021 
1022   Vector<Uint32> hashValues;
1023   Vector<Vector<Uint32> > chains;
1024   if (chains.fill(size, hashValues))
1025   {
1026     return -1;
1027   }
1028   for(i = 0; i< (int) size; i++){
1029     Uint32 hv = Hash(m_columns[i]->getName()) & 0xFFFE;
1030     Uint32 bucket = hv & m_columnHashMask;
1031     bucket = (bucket < size ? bucket : bucket - size);
1032     assert(bucket < size);
1033     if (hashValues.push_back(hv) ||
1034         chains[bucket].push_back(i))
1035     {
1036       return -1;
1037     }
1038   }
1039 
1040   m_columnHash.clear();
1041   Uint32 tmp = 1;
1042   if (m_columnHash.fill((unsigned)size-1, tmp))   // Default no chaining
1043   {
1044     return -1;
1045   }
1046 
1047   Uint32 pos = 0; // In overflow vector
1048   for(i = 0; i< (int) size; i++){
1049     Uint32 sz = chains[i].size();
1050     if(sz == 1){
1051       Uint32 col = chains[i][0];
1052       Uint32 hv = hashValues[col];
1053       Uint32 bucket = hv & m_columnHashMask;
1054       bucket = (bucket < size ? bucket : bucket - size);
1055       m_columnHash[bucket] = (col << 16) | hv | 1;
1056     } else if(sz > 1){
1057       Uint32 col = chains[i][0];
1058       Uint32 hv = hashValues[col];
1059       Uint32 bucket = hv & m_columnHashMask;
1060       bucket = (bucket < size ? bucket : bucket - size);
1061       m_columnHash[bucket] = (sz << 16) | (((size - bucket) + pos) << 1);
1062       for(size_t j = 0; j<sz; j++, pos++){
1063 	Uint32 col = chains[i][j];
1064 	Uint32 hv = hashValues[col];
1065 	if (m_columnHash.push_back((col << 16) | hv))
1066         {
1067           return -1;
1068         }
1069       }
1070     }
1071   }
1072 
1073   if (m_columnHash.push_back(0)) // Overflow when looping in end of array
1074   {
1075     return -1;
1076   }
1077 
1078 #if 0
1079   for(size_t i = 0; i<m_columnHash.size(); i++){
1080     Uint32 tmp = m_columnHash[i];
1081     int col = -1;
1082     if(i < size && (tmp & 1) == 1){
1083       col = (tmp >> 16);
1084     } else if(i >= size){
1085       col = (tmp >> 16);
1086     }
1087     ndbout_c("m_columnHash[%d] %s = %x",
1088 	     i, col > 0 ? m_columns[col]->getName() : "" , m_columnHash[i]);
1089   }
1090 #endif
1091   return 0;
1092 }
1093 
1094 Uint32
get_nodes(Uint32 hashValue,const Uint16 ** nodes) const1095 NdbTableImpl::get_nodes(Uint32 hashValue, const Uint16 ** nodes) const
1096 {
1097   Uint32 fragmentId;
1098   if(m_replicaCount == 0)
1099     return 0;
1100   switch (m_fragmentType)
1101   {
1102     case NdbDictionary::Object::FragAllSmall:
1103     case NdbDictionary::Object::FragAllMedium:
1104     case NdbDictionary::Object::FragAllLarge:
1105     case NdbDictionary::Object::FragSingle:
1106     case NdbDictionary::Object::DistrKeyLin:
1107     {
1108       fragmentId = hashValue & m_hashValueMask;
1109       if(fragmentId < m_hashpointerValue)
1110         fragmentId = hashValue & ((m_hashValueMask << 1) + 1);
1111       break;
1112     }
1113     case NdbDictionary::Object::DistrKeyHash:
1114     {
1115       fragmentId = hashValue % m_fragmentCount;
1116       break;
1117     }
1118     default:
1119       return 0;
1120   }
1121   Uint32 pos = fragmentId * m_replicaCount;
1122   if (pos + m_replicaCount <= m_fragments.size())
1123   {
1124     *nodes = m_fragments.getBase()+pos;
1125     return m_replicaCount;
1126   }
1127   return 0;
1128 }
1129 
1130 int
checkColumns(const Uint32 * map,Uint32 len) const1131 NdbDictionary::Table::checkColumns(const Uint32* map, Uint32 len) const
1132 {
1133   int ret = 0;
1134   Uint32 colCnt = m_impl.m_columns.size();
1135   if (map == 0)
1136   {
1137     ret |= 1;
1138     ret |= (m_impl.m_noOfDiskColumns) ? 2 : 0;
1139     ret |= (colCnt > m_impl.m_noOfDiskColumns) ? 4 : 0;
1140     return ret;
1141   }
1142 
1143   NdbColumnImpl** cols = m_impl.m_columns.getBase();
1144   const char * ptr = reinterpret_cast<const char*>(map);
1145   const char * end = ptr + len;
1146   Uint32 no = 0;
1147   while (ptr < end)
1148   {
1149     Uint32 val = (Uint32)* ptr;
1150     Uint32 idx = 1;
1151     for (Uint32 i = 0; i<8; i++)
1152     {
1153       if (val & idx)
1154       {
1155 	if (cols[no]->getPrimaryKey())
1156 	  ret |= 1;
1157 	else
1158 	{
1159 	  if (cols[no]->getStorageType() == NdbDictionary::Column::StorageTypeDisk)
1160 	    ret |= 2;
1161 	  else
1162 	    ret |= 4;
1163 	}
1164       }
1165       no ++;
1166       idx *= 2;
1167       if (no == colCnt)
1168 	return ret;
1169     }
1170 
1171     ptr++;
1172   }
1173   return ret;
1174 }
1175 
1176 
1177 
1178 /**
1179  * NdbIndexImpl
1180  */
1181 
NdbIndexImpl()1182 NdbIndexImpl::NdbIndexImpl() :
1183   NdbDictionary::Index(* this),
1184   NdbDictObjectImpl(NdbDictionary::Object::OrderedIndex), m_facade(this)
1185 {
1186   init();
1187 }
1188 
NdbIndexImpl(NdbDictionary::Index & f)1189 NdbIndexImpl::NdbIndexImpl(NdbDictionary::Index & f) :
1190   NdbDictionary::Index(* this),
1191   NdbDictObjectImpl(NdbDictionary::Object::OrderedIndex), m_facade(&f)
1192 {
1193   init();
1194 }
1195 
init()1196 void NdbIndexImpl::init()
1197 {
1198   m_id= RNIL;
1199   m_type= NdbDictionary::Object::TypeUndefined;
1200   m_logging= true;
1201   m_temporary= false;
1202   m_table= NULL;
1203 }
1204 
~NdbIndexImpl()1205 NdbIndexImpl::~NdbIndexImpl(){
1206   for (unsigned i = 0; i < m_columns.size(); i++)
1207     delete m_columns[i];
1208 }
1209 
setName(const char * name)1210 int NdbIndexImpl::setName(const char * name)
1211 {
1212   return !m_externalName.assign(name);
1213 }
1214 
1215 const char *
getName() const1216 NdbIndexImpl::getName() const
1217 {
1218   return m_externalName.c_str();
1219 }
1220 
1221 int
setTable(const char * table)1222 NdbIndexImpl::setTable(const char * table)
1223 {
1224   return !m_tableName.assign(table);
1225 }
1226 
1227 const char *
getTable() const1228 NdbIndexImpl::getTable() const
1229 {
1230   return m_tableName.c_str();
1231 }
1232 
1233 const NdbTableImpl *
getIndexTable() const1234 NdbIndexImpl::getIndexTable() const
1235 {
1236   return m_table;
1237 }
1238 
1239 /**
1240  * NdbEventImpl
1241  */
1242 
NdbEventImpl()1243 NdbEventImpl::NdbEventImpl() :
1244   NdbDictionary::Event(* this),
1245   NdbDictObjectImpl(NdbDictionary::Object::TypeUndefined), m_facade(this)
1246 {
1247   DBUG_ENTER("NdbEventImpl::NdbEventImpl");
1248   DBUG_PRINT("info", ("this: %p", this));
1249   init();
1250   DBUG_VOID_RETURN;
1251 }
1252 
NdbEventImpl(NdbDictionary::Event & f)1253 NdbEventImpl::NdbEventImpl(NdbDictionary::Event & f) :
1254   NdbDictionary::Event(* this),
1255   NdbDictObjectImpl(NdbDictionary::Object::TypeUndefined), m_facade(&f)
1256 {
1257   DBUG_ENTER("NdbEventImpl::NdbEventImpl");
1258   DBUG_PRINT("info", ("this: %p", this));
1259   init();
1260   DBUG_VOID_RETURN;
1261 }
1262 
init()1263 void NdbEventImpl::init()
1264 {
1265   m_eventId= RNIL;
1266   m_eventKey= RNIL;
1267   mi_type= 0;
1268   m_dur= NdbDictionary::Event::ED_UNDEFINED;
1269   m_mergeEvents = false;
1270   m_tableImpl= NULL;
1271   m_rep= NdbDictionary::Event::ER_UPDATED;
1272 }
1273 
~NdbEventImpl()1274 NdbEventImpl::~NdbEventImpl()
1275 {
1276   DBUG_ENTER("NdbEventImpl::~NdbEventImpl");
1277   DBUG_PRINT("info", ("this: %p", this));
1278   for (unsigned i = 0; i < m_columns.size(); i++)
1279     delete  m_columns[i];
1280   if (m_tableImpl)
1281     delete m_tableImpl;
1282   DBUG_VOID_RETURN;
1283 }
1284 
setName(const char * name)1285 int NdbEventImpl::setName(const char * name)
1286 {
1287   return !m_name.assign(name);
1288 }
1289 
getName() const1290 const char *NdbEventImpl::getName() const
1291 {
1292   return m_name.c_str();
1293 }
1294 
1295 int
setTable(const NdbDictionary::Table & table)1296 NdbEventImpl::setTable(const NdbDictionary::Table& table)
1297 {
1298   setTable(&NdbTableImpl::getImpl(table));
1299   return !m_tableName.assign(m_tableImpl->getName());
1300 }
1301 
1302 void
setTable(NdbTableImpl * tableImpl)1303 NdbEventImpl::setTable(NdbTableImpl *tableImpl)
1304 {
1305   DBUG_ENTER("NdbEventImpl::setTable");
1306   DBUG_PRINT("info", ("this: %p  tableImpl: %p", this, tableImpl));
1307   DBUG_ASSERT(tableImpl->m_status != NdbDictionary::Object::Invalid);
1308   if (!m_tableImpl)
1309     m_tableImpl = new NdbTableImpl();
1310   // Copy table, since event might be accessed from different threads
1311   m_tableImpl->assign(*tableImpl);
1312   DBUG_VOID_RETURN;
1313 }
1314 
1315 const NdbDictionary::Table *
getTable() const1316 NdbEventImpl::getTable() const
1317 {
1318   if (m_tableImpl)
1319     return m_tableImpl->m_facade;
1320   else
1321     return NULL;
1322 }
1323 
1324 int
setTable(const char * table)1325 NdbEventImpl::setTable(const char * table)
1326 {
1327   return !m_tableName.assign(table);
1328 }
1329 
1330 const char *
getTableName() const1331 NdbEventImpl::getTableName() const
1332 {
1333   return m_tableName.c_str();
1334 }
1335 
1336 void
addTableEvent(const NdbDictionary::Event::TableEvent t=NdbDictionary::Event::TE_ALL)1337 NdbEventImpl::addTableEvent(const NdbDictionary::Event::TableEvent t =  NdbDictionary::Event::TE_ALL)
1338 {
1339   mi_type |= (unsigned)t;
1340 }
1341 
1342 bool
getTableEvent(const NdbDictionary::Event::TableEvent t) const1343 NdbEventImpl::getTableEvent(const NdbDictionary::Event::TableEvent t) const
1344 {
1345   return (mi_type & (unsigned)t) == (unsigned)t;
1346 }
1347 
1348 void
setDurability(NdbDictionary::Event::EventDurability d)1349 NdbEventImpl::setDurability(NdbDictionary::Event::EventDurability d)
1350 {
1351   m_dur = d;
1352 }
1353 
1354 NdbDictionary::Event::EventDurability
getDurability() const1355 NdbEventImpl::getDurability() const
1356 {
1357   return m_dur;
1358 }
1359 
1360 void
setReport(NdbDictionary::Event::EventReport r)1361 NdbEventImpl::setReport(NdbDictionary::Event::EventReport r)
1362 {
1363   m_rep = r;
1364 }
1365 
1366 NdbDictionary::Event::EventReport
getReport() const1367 NdbEventImpl::getReport() const
1368 {
1369   return m_rep;
1370 }
1371 
getNoOfEventColumns() const1372 int NdbEventImpl::getNoOfEventColumns() const
1373 {
1374   return m_attrIds.size() + m_columns.size();
1375 }
1376 
1377 const NdbDictionary::Column *
getEventColumn(unsigned no) const1378 NdbEventImpl::getEventColumn(unsigned no) const
1379 {
1380   if (m_columns.size())
1381   {
1382     if (no < m_columns.size())
1383     {
1384       return m_columns[no];
1385     }
1386   }
1387   else if (m_attrIds.size())
1388   {
1389     if (no < m_attrIds.size())
1390     {
1391       NdbTableImpl* tab= m_tableImpl;
1392       if (tab == 0)
1393         return 0;
1394       return tab->getColumn(m_attrIds[no]);
1395     }
1396   }
1397   return 0;
1398 }
1399 
1400 /**
1401  * NdbDictionaryImpl
1402  */
1403 
NdbDictionaryImpl(Ndb & ndb)1404 NdbDictionaryImpl::NdbDictionaryImpl(Ndb &ndb)
1405   : NdbDictionary::Dictionary(* this),
1406     m_facade(this),
1407     m_receiver(m_error),
1408     m_ndb(ndb)
1409 {
1410   m_globalHash = 0;
1411   m_local_table_data_size= 0;
1412 }
1413 
NdbDictionaryImpl(Ndb & ndb,NdbDictionary::Dictionary & f)1414 NdbDictionaryImpl::NdbDictionaryImpl(Ndb &ndb,
1415 				     NdbDictionary::Dictionary & f)
1416   : NdbDictionary::Dictionary(* this),
1417     m_facade(&f),
1418     m_receiver(m_error),
1419     m_ndb(ndb)
1420 {
1421   m_globalHash = 0;
1422   m_local_table_data_size= 0;
1423 }
1424 
~NdbDictionaryImpl()1425 NdbDictionaryImpl::~NdbDictionaryImpl()
1426 {
1427   NdbElement_t<Ndb_local_table_info> * curr = m_localHash.m_tableHash.getNext(0);
1428   if(m_globalHash){
1429     while(curr != 0){
1430       m_globalHash->lock();
1431       m_globalHash->release(curr->theData->m_table_impl);
1432       Ndb_local_table_info::destroy(curr->theData);
1433       m_globalHash->unlock();
1434 
1435       curr = m_localHash.m_tableHash.getNext(curr);
1436     }
1437   } else {
1438     assert(curr == 0);
1439   }
1440 }
1441 
1442 NdbTableImpl *
fetchGlobalTableImplRef(const GlobalCacheInitObject & obj)1443 NdbDictionaryImpl::fetchGlobalTableImplRef(const GlobalCacheInitObject &obj)
1444 {
1445   DBUG_ENTER("fetchGlobalTableImplRef");
1446   NdbTableImpl *impl;
1447   int error= 0;
1448 
1449   m_globalHash->lock();
1450   impl = m_globalHash->get(obj.m_name.c_str(), &error);
1451   m_globalHash->unlock();
1452 
1453   if (impl == 0){
1454     if (error == 0)
1455       impl = m_receiver.getTable(obj.m_name.c_str(),
1456                                  m_ndb.usingFullyQualifiedNames());
1457     else
1458       m_error.code = 4000;
1459     if (impl != 0 && obj.init(*impl))
1460     {
1461       delete impl;
1462       impl = 0;
1463     }
1464     m_globalHash->lock();
1465     m_globalHash->put(obj.m_name.c_str(), impl);
1466     m_globalHash->unlock();
1467   }
1468 
1469   DBUG_RETURN(impl);
1470 }
1471 
1472 void
putTable(NdbTableImpl * impl)1473 NdbDictionaryImpl::putTable(NdbTableImpl *impl)
1474 {
1475   NdbTableImpl *old;
1476 
1477   int ret = getBlobTables(*impl);
1478   int error = 0;
1479   assert(ret == 0);
1480 
1481   m_globalHash->lock();
1482   if ((old= m_globalHash->get(impl->m_internalName.c_str(), &error)))
1483   {
1484     m_globalHash->alter_table_rep(old->m_internalName.c_str(),
1485                                   impl->m_id,
1486                                   impl->m_version,
1487                                   FALSE);
1488   }
1489   m_globalHash->put(impl->m_internalName.c_str(), impl);
1490   m_globalHash->unlock();
1491   Ndb_local_table_info *info=
1492     Ndb_local_table_info::create(impl, m_local_table_data_size);
1493 
1494   m_localHash.put(impl->m_internalName.c_str(), info);
1495 }
1496 
1497 int
getBlobTables(NdbTableImpl & t)1498 NdbDictionaryImpl::getBlobTables(NdbTableImpl &t)
1499 {
1500   unsigned n= t.m_noOfBlobs;
1501   DBUG_ENTER("NdbDictionaryImpl::addBlobTables");
1502   // optimized for blob column being the last one
1503   // and not looking for more than one if not neccessary
1504   for (unsigned i = t.m_columns.size(); i > 0 && n > 0;) {
1505     i--;
1506     NdbColumnImpl & c = *t.m_columns[i];
1507     if (! c.getBlobType() || c.getPartSize() == 0)
1508       continue;
1509     n--;
1510     // retrieve blob table def from DICT - by-pass cache
1511     char btname[NdbBlobImpl::BlobTableNameSize];
1512     NdbBlob::getBlobTableName(btname, &t, &c);
1513     BaseString btname_internal = m_ndb.internalize_table_name(btname);
1514     NdbTableImpl* bt =
1515       m_receiver.getTable(btname_internal, m_ndb.usingFullyQualifiedNames());
1516     if (bt == NULL)
1517       DBUG_RETURN(-1);
1518 
1519     // TODO check primary id/version when returned by DICT
1520 
1521     // the blob column owns the blob table
1522     assert(c.m_blobTable == NULL);
1523     c.m_blobTable = bt;
1524   }
1525   DBUG_RETURN(0);
1526 }
1527 
1528 NdbTableImpl*
getBlobTable(const NdbTableImpl & tab,uint col_no)1529 NdbDictionaryImpl::getBlobTable(const NdbTableImpl& tab, uint col_no)
1530 {
1531   if (col_no < tab.m_columns.size()) {
1532     NdbColumnImpl* col = tab.m_columns[col_no];
1533     if (col != NULL) {
1534       NdbTableImpl* bt = col->m_blobTable;
1535       if (bt != NULL)
1536         return bt;
1537       else
1538         m_error.code = 4273; // No blob table..
1539     } else
1540       m_error.code = 4249; // Invalid table..
1541   } else
1542     m_error.code = 4318; // Invalid attribute..
1543   return NULL;
1544 }
1545 
1546 NdbTableImpl*
getBlobTable(uint tab_id,uint col_no)1547 NdbDictionaryImpl::getBlobTable(uint tab_id, uint col_no)
1548 {
1549   DBUG_ENTER("NdbDictionaryImpl::getBlobTable");
1550   DBUG_PRINT("enter", ("tab_id: %u col_no %u", tab_id, col_no));
1551 
1552   NdbTableImpl* tab = m_receiver.getTable(tab_id,
1553                                           m_ndb.usingFullyQualifiedNames());
1554   if (tab == NULL)
1555     DBUG_RETURN(NULL);
1556   Ndb_local_table_info* info =
1557     get_local_table_info(tab->m_internalName);
1558   delete tab;
1559   if (info == NULL)
1560     DBUG_RETURN(NULL);
1561   NdbTableImpl* bt = getBlobTable(*info->m_table_impl, col_no);
1562   DBUG_RETURN(bt);
1563 }
1564 
1565 #if 0
1566 bool
1567 NdbDictionaryImpl::setTransporter(class TransporterFacade * tf)
1568 {
1569   if(tf != 0){
1570     m_globalHash = &tf->m_globalDictCache;
1571     return m_receiver.setTransporter(tf);
1572   }
1573 
1574   return false;
1575 }
1576 #endif
1577 
1578 bool
setTransporter(class Ndb * ndb,class TransporterFacade * tf)1579 NdbDictionaryImpl::setTransporter(class Ndb* ndb,
1580 				  class TransporterFacade * tf)
1581 {
1582   m_globalHash = &tf->m_globalDictCache;
1583   if(m_receiver.setTransporter(ndb, tf)){
1584     return true;
1585   }
1586   return false;
1587 }
1588 
1589 NdbTableImpl *
getIndexTable(NdbIndexImpl * index,NdbTableImpl * table)1590 NdbDictionaryImpl::getIndexTable(NdbIndexImpl * index,
1591 				 NdbTableImpl * table)
1592 {
1593   const char *current_db= m_ndb.getDatabaseName();
1594   NdbTableImpl *index_table;
1595   const BaseString internalName(
1596     m_ndb.internalize_index_name(table, index->getName()));
1597   // Get index table in system database
1598   m_ndb.setDatabaseName(NDB_SYSTEM_DATABASE);
1599   index_table= getTable(m_ndb.externalizeTableName(internalName.c_str()));
1600   m_ndb.setDatabaseName(current_db);
1601   if (!index_table)
1602   {
1603     // Index table not found
1604     // Try geting index table in current database (old format)
1605     index_table= getTable(m_ndb.externalizeTableName(internalName.c_str()));
1606   }
1607   return index_table;
1608 }
1609 
1610 #if 0
1611 bool
1612 NdbDictInterface::setTransporter(class TransporterFacade * tf)
1613 {
1614   if(tf == 0)
1615     return false;
1616 
1617   Guard g(tf->theMutexPtr);
1618 
1619   m_blockNumber = tf->open(this,
1620 			   execSignal,
1621 			   execNodeStatus);
1622 
1623   if ( m_blockNumber == -1 ) {
1624     m_error.code= 4105;
1625     return false; // no more free blocknumbers
1626   }//if
1627   Uint32 theNode = tf->ownId();
1628   m_reference = numberToRef(m_blockNumber, theNode);
1629   m_transporter = tf;
1630   m_waiter.m_mutex = tf->theMutexPtr;
1631 
1632   return true;
1633 }
1634 #endif
1635 
1636 bool
setTransporter(class Ndb * ndb,class TransporterFacade * tf)1637 NdbDictInterface::setTransporter(class Ndb* ndb, class TransporterFacade * tf)
1638 {
1639   m_reference = ndb->getReference();
1640   m_transporter = tf;
1641   m_waiter.m_mutex = tf->theMutexPtr;
1642 
1643   return true;
1644 }
1645 
~NdbDictInterface()1646 NdbDictInterface::~NdbDictInterface()
1647 {
1648 }
1649 
1650 void
execSignal(void * dictImpl,class NdbApiSignal * signal,class LinearSectionPtr ptr[3])1651 NdbDictInterface::execSignal(void* dictImpl,
1652 			     class NdbApiSignal* signal,
1653 			     class LinearSectionPtr ptr[3])
1654 {
1655   NdbDictInterface * tmp = (NdbDictInterface*)dictImpl;
1656 
1657   const Uint32 gsn = signal->readSignalNumber();
1658   switch(gsn){
1659   case GSN_GET_TABINFOREF:
1660     tmp->execGET_TABINFO_REF(signal, ptr);
1661     break;
1662   case GSN_GET_TABINFO_CONF:
1663     tmp->execGET_TABINFO_CONF(signal, ptr);
1664     break;
1665   case GSN_CREATE_TABLE_REF:
1666     tmp->execCREATE_TABLE_REF(signal, ptr);
1667     break;
1668   case GSN_CREATE_TABLE_CONF:
1669     tmp->execCREATE_TABLE_CONF(signal, ptr);
1670     break;
1671   case GSN_DROP_TABLE_REF:
1672     tmp->execDROP_TABLE_REF(signal, ptr);
1673     break;
1674   case GSN_DROP_TABLE_CONF:
1675     tmp->execDROP_TABLE_CONF(signal, ptr);
1676     break;
1677   case GSN_ALTER_TABLE_REF:
1678     tmp->execALTER_TABLE_REF(signal, ptr);
1679     break;
1680   case GSN_ALTER_TABLE_CONF:
1681     tmp->execALTER_TABLE_CONF(signal, ptr);
1682     break;
1683   case GSN_CREATE_INDX_REF:
1684     tmp->execCREATE_INDX_REF(signal, ptr);
1685     break;
1686   case GSN_CREATE_INDX_CONF:
1687     tmp->execCREATE_INDX_CONF(signal, ptr);
1688     break;
1689   case GSN_DROP_INDX_REF:
1690     tmp->execDROP_INDX_REF(signal, ptr);
1691     break;
1692   case GSN_DROP_INDX_CONF:
1693     tmp->execDROP_INDX_CONF(signal, ptr);
1694     break;
1695   case GSN_CREATE_EVNT_REF:
1696     tmp->execCREATE_EVNT_REF(signal, ptr);
1697     break;
1698   case GSN_CREATE_EVNT_CONF:
1699     tmp->execCREATE_EVNT_CONF(signal, ptr);
1700     break;
1701   case GSN_SUB_START_CONF:
1702     tmp->execSUB_START_CONF(signal, ptr);
1703     break;
1704   case GSN_SUB_START_REF:
1705     tmp->execSUB_START_REF(signal, ptr);
1706     break;
1707   case GSN_SUB_STOP_CONF:
1708     tmp->execSUB_STOP_CONF(signal, ptr);
1709     break;
1710   case GSN_SUB_STOP_REF:
1711     tmp->execSUB_STOP_REF(signal, ptr);
1712     break;
1713   case GSN_DROP_EVNT_REF:
1714     tmp->execDROP_EVNT_REF(signal, ptr);
1715     break;
1716   case GSN_DROP_EVNT_CONF:
1717     tmp->execDROP_EVNT_CONF(signal, ptr);
1718     break;
1719   case GSN_LIST_TABLES_CONF:
1720     tmp->execLIST_TABLES_CONF(signal, ptr);
1721     break;
1722   case GSN_CREATE_FILEGROUP_REF:
1723     tmp->execCREATE_FILEGROUP_REF(signal, ptr);
1724     break;
1725   case GSN_CREATE_FILEGROUP_CONF:
1726     tmp->execCREATE_FILEGROUP_CONF(signal, ptr);
1727     break;
1728   case GSN_CREATE_FILE_REF:
1729     tmp->execCREATE_FILE_REF(signal, ptr);
1730     break;
1731   case GSN_CREATE_FILE_CONF:
1732     tmp->execCREATE_FILE_CONF(signal, ptr);
1733     break;
1734   case GSN_DROP_FILEGROUP_REF:
1735     tmp->execDROP_FILEGROUP_REF(signal, ptr);
1736     break;
1737   case GSN_DROP_FILEGROUP_CONF:
1738     tmp->execDROP_FILEGROUP_CONF(signal, ptr);
1739     break;
1740   case GSN_DROP_FILE_REF:
1741     tmp->execDROP_FILE_REF(signal, ptr);
1742     break;
1743   case GSN_DROP_FILE_CONF:
1744     tmp->execDROP_FILE_CONF(signal, ptr);
1745     break;
1746   case GSN_WAIT_GCP_CONF:
1747     tmp->execWAIT_GCP_CONF(signal, ptr);
1748     break;
1749   case GSN_WAIT_GCP_REF:
1750     tmp->execWAIT_GCP_REF(signal, ptr);
1751     break;
1752   default:
1753     abort();
1754   }
1755 }
1756 
1757 void
execNodeStatus(void * dictImpl,Uint32 aNode,bool alive,bool nfCompleted)1758 NdbDictInterface::execNodeStatus(void* dictImpl, Uint32 aNode,
1759 				 bool alive, bool nfCompleted)
1760 {
1761   NdbDictInterface * tmp = (NdbDictInterface*)dictImpl;
1762 
1763   if(!alive && !nfCompleted){
1764     return;
1765   }
1766 
1767   if (!alive && nfCompleted){
1768     tmp->m_waiter.nodeFail(aNode);
1769   }
1770 }
1771 
1772 int
dictSignal(NdbApiSignal * sig,LinearSectionPtr ptr[3],int secs,int node_specification,WaitSignalType wst,int timeout,Uint32 RETRIES,const int * errcodes,int temporaryMask)1773 NdbDictInterface::dictSignal(NdbApiSignal* sig,
1774 			     LinearSectionPtr ptr[3], int secs,
1775 			     int node_specification,
1776 			     WaitSignalType wst,
1777 			     int timeout, Uint32 RETRIES,
1778 			     const int *errcodes, int temporaryMask)
1779 {
1780   DBUG_ENTER("NdbDictInterface::dictSignal");
1781   DBUG_PRINT("enter", ("useMasterNodeId: %d", node_specification));
1782 
1783   int sleep = 50;
1784   int mod = 5;
1785 
1786   for(Uint32 i = 0; i<RETRIES; i++)
1787   {
1788     if (i > 0)
1789       NdbSleep_MilliSleep(sleep + 10 * (rand() % mod));
1790     if (i == RETRIES / 2)
1791     {
1792       mod = 10;
1793     }
1794     if (i == 3*RETRIES/4)
1795     {
1796       sleep = 100;
1797     }
1798 
1799     m_buffer.clear();
1800 
1801     // Protected area
1802     /*
1803       The PollGuard has an implicit call of unlock_and_signal through the
1804       ~PollGuard method. This method is called implicitly by the compiler
1805       in all places where the object is out of context due to a return,
1806       break, continue or simply end of statement block
1807     */
1808     PollGuard poll_guard(m_transporter, &m_waiter, refToBlock(m_reference));
1809     Uint32 node;
1810     switch(node_specification){
1811     case 0:
1812       node = (m_transporter->get_node_alive(m_masterNodeId) ? m_masterNodeId :
1813 	      (m_masterNodeId = m_transporter->get_an_alive_node()));
1814       break;
1815     case -1:
1816       node = m_transporter->get_an_alive_node();
1817       break;
1818     default:
1819       node = node_specification;
1820     }
1821     DBUG_PRINT("info", ("node %d", node));
1822     if(node == 0){
1823       m_error.code= 4009;
1824       DBUG_RETURN(-1);
1825     }
1826     int res = (ptr ?
1827 	       m_transporter->sendFragmentedSignal(sig, node, ptr, secs):
1828 	       m_transporter->sendSignal(sig, node));
1829     if(res != 0){
1830       DBUG_PRINT("info", ("dictSignal failed to send signal"));
1831       m_error.code = 4007;
1832       continue;
1833     }
1834 
1835     m_error.code= 0;
1836     int ret_val= poll_guard.wait_n_unlock(timeout, node, wst);
1837     // End of Protected area
1838 
1839     if(ret_val == 0 && m_error.code == 0){
1840       // Normal return
1841       DBUG_RETURN(0);
1842     }
1843 
1844     /**
1845      * Handle error codes
1846      */
1847     if(ret_val == -2) //WAIT_NODE_FAILURE
1848     {
1849       m_error.code = 4013;
1850       continue;
1851     }
1852     if(m_waiter.m_state == WST_WAIT_TIMEOUT)
1853     {
1854       DBUG_PRINT("info", ("dictSignal caught time-out"));
1855       m_error.code = 4008;
1856       DBUG_RETURN(-1);
1857     }
1858 
1859     if ( temporaryMask == -1)
1860     {
1861       const NdbError &error= getNdbError();
1862       if (error.status ==  NdbError::TemporaryError)
1863 	continue;
1864     }
1865     else if ( (temporaryMask & m_error.code) != 0 ) {
1866       continue;
1867     }
1868     DBUG_PRINT("info", ("dictSignal caught error= %d", m_error.code));
1869 
1870     if(m_error.code && errcodes)
1871     {
1872       int j;
1873       for(j = 0; errcodes[j] ; j++){
1874 	if(m_error.code == errcodes[j]){
1875 	  break;
1876 	}
1877       }
1878       if(errcodes[j]) // Accepted error code
1879 	continue;
1880     }
1881     break;
1882   }
1883   DBUG_RETURN(-1);
1884 }
1885 
1886 /*
1887   Get dictionary information for a table using table id as reference
1888 
1889   DESCRIPTION
1890     Sends a GET_TABINFOREQ signal containing the table id
1891  */
1892 NdbTableImpl *
getTable(int tableId,bool fullyQualifiedNames)1893 NdbDictInterface::getTable(int tableId, bool fullyQualifiedNames)
1894 {
1895   NdbApiSignal tSignal(m_reference);
1896   GetTabInfoReq * req = CAST_PTR(GetTabInfoReq, tSignal.getDataPtrSend());
1897 
1898   req->senderRef = m_reference;
1899   req->senderData = 0;
1900   req->requestType =
1901     GetTabInfoReq::RequestById | GetTabInfoReq::LongSignalConf;
1902   req->tableId = tableId;
1903   tSignal.theReceiversBlockNumber = DBDICT;
1904   tSignal.theVerId_signalNumber   = GSN_GET_TABINFOREQ;
1905   tSignal.theLength = GetTabInfoReq::SignalLength;
1906 
1907   return getTable(&tSignal, 0, 0, fullyQualifiedNames);
1908 }
1909 
1910 /*
1911   Get dictionary information for a table using table name as the reference
1912 
1913   DESCRIPTION
1914     Send GET_TABINFOREQ signal with the table name in the first
1915     long section part
1916 */
1917 
1918 NdbTableImpl *
getTable(const BaseString & name,bool fullyQualifiedNames)1919 NdbDictInterface::getTable(const BaseString& name, bool fullyQualifiedNames)
1920 {
1921   NdbApiSignal tSignal(m_reference);
1922   GetTabInfoReq* const req = CAST_PTR(GetTabInfoReq, tSignal.getDataPtrSend());
1923 
1924   const Uint32 namelen= name.length() + 1; // NULL terminated
1925   const Uint32 namelen_words= (namelen + 3) >> 2; // Size in words
1926 
1927   req->senderRef= m_reference;
1928   req->senderData= 0;
1929   req->requestType=
1930     GetTabInfoReq::RequestByName | GetTabInfoReq::LongSignalConf;
1931   req->tableNameLen= namelen;
1932   tSignal.theReceiversBlockNumber= DBDICT;
1933   tSignal.theVerId_signalNumber= GSN_GET_TABINFOREQ;
1934   tSignal.theLength= GetTabInfoReq::SignalLength;
1935 
1936   // Copy name to m_buffer to get a word sized buffer
1937   m_buffer.clear();
1938   if (m_buffer.grow(namelen_words*4+4) ||
1939       m_buffer.append(name.c_str(), namelen))
1940   {
1941     m_error.code= 4000;
1942     return NULL;
1943   }
1944 
1945 #ifndef IGNORE_VALGRIND_WARNINGS
1946   Uint32 pad = 0;
1947   if (m_buffer.append(&pad, 4))
1948   {
1949     m_error.code= 4000;
1950     return NULL;
1951   }
1952 #endif
1953 
1954   LinearSectionPtr ptr[1];
1955   ptr[0].p= (Uint32*)m_buffer.get_data();
1956   ptr[0].sz= namelen_words;
1957 
1958   return getTable(&tSignal, ptr, 1, fullyQualifiedNames);
1959 }
1960 
1961 
1962 NdbTableImpl *
getTable(class NdbApiSignal * signal,LinearSectionPtr ptr[3],Uint32 noOfSections,bool fullyQualifiedNames)1963 NdbDictInterface::getTable(class NdbApiSignal * signal,
1964 			   LinearSectionPtr ptr[3],
1965 			   Uint32 noOfSections, bool fullyQualifiedNames)
1966 {
1967   int errCodes[] = {GetTabInfoRef::Busy, 0 };
1968   int r = dictSignal(signal, ptr, noOfSections,
1969 		     -1, // any node
1970 		     WAIT_GET_TAB_INFO_REQ,
1971 		     DICT_WAITFOR_TIMEOUT, 100, errCodes);
1972 
1973   if (r)
1974     return 0;
1975 
1976   NdbTableImpl * rt = 0;
1977   m_error.code = parseTableInfo(&rt,
1978 				(Uint32*)m_buffer.get_data(),
1979   				m_buffer.length() / 4,
1980 				fullyQualifiedNames);
1981   if(rt)
1982   {
1983     if (rt->buildColumnHash())
1984     {
1985       m_error.code = 4000;
1986       delete rt;
1987       return NULL;
1988      }
1989   }
1990 
1991   return rt;
1992 }
1993 
1994 void
execGET_TABINFO_CONF(NdbApiSignal * signal,LinearSectionPtr ptr[3])1995 NdbDictInterface::execGET_TABINFO_CONF(NdbApiSignal * signal,
1996 				       LinearSectionPtr ptr[3])
1997 {
1998   const GetTabInfoConf* conf = CAST_CONSTPTR(GetTabInfoConf, signal->getDataPtr());
1999   const Uint32 i = GetTabInfoConf::DICT_TAB_INFO;
2000   if(signal->isFirstFragment()){
2001     m_fragmentId = signal->getFragmentId();
2002     if (m_buffer.grow(4 * conf->totalLen))
2003     {
2004       m_error.code= 4000;
2005       goto end;
2006     }
2007   } else {
2008     if(m_fragmentId != signal->getFragmentId()){
2009       abort();
2010     }
2011   }
2012 
2013   if (m_buffer.append(ptr[i].p, 4 * ptr[i].sz))
2014   {
2015     m_error.code= 4000;
2016   }
2017 end:
2018   if(!signal->isLastFragment()){
2019     return;
2020   }
2021 
2022   m_waiter.signal(NO_WAIT);
2023 }
2024 
2025 void
execGET_TABINFO_REF(NdbApiSignal * signal,LinearSectionPtr ptr[3])2026 NdbDictInterface::execGET_TABINFO_REF(NdbApiSignal * signal,
2027 				      LinearSectionPtr ptr[3])
2028 {
2029   const GetTabInfoRef* ref = CAST_CONSTPTR(GetTabInfoRef,
2030 					   signal->getDataPtr());
2031 
2032   m_error.code= ref->errorCode;
2033   m_waiter.signal(NO_WAIT);
2034 }
2035 
2036 /*****************************************************************
2037  * Pack/Unpack tables
2038  */
2039 struct ApiKernelMapping {
2040   Int32 kernelConstant;
2041   Int32 apiConstant;
2042 };
2043 
2044 Uint32
getApiConstant(Int32 kernelConstant,const ApiKernelMapping map[],Uint32 def)2045 getApiConstant(Int32 kernelConstant, const ApiKernelMapping map[], Uint32 def)
2046 {
2047   int i = 0;
2048   while(map[i].kernelConstant != kernelConstant){
2049     if(map[i].kernelConstant == -1 &&
2050        map[i].apiConstant == -1){
2051       return def;
2052     }
2053     i++;
2054   }
2055   return map[i].apiConstant;
2056 }
2057 
2058 Uint32
getKernelConstant(Int32 apiConstant,const ApiKernelMapping map[],Uint32 def)2059 getKernelConstant(Int32 apiConstant, const ApiKernelMapping map[], Uint32 def)
2060 {
2061   int i = 0;
2062   while(map[i].apiConstant != apiConstant){
2063     if(map[i].kernelConstant == -1 &&
2064        map[i].apiConstant == -1){
2065       return def;
2066     }
2067     i++;
2068   }
2069   return map[i].kernelConstant;
2070 }
2071 
2072 static const
2073 ApiKernelMapping
2074 fragmentTypeMapping[] = {
2075   { DictTabInfo::AllNodesSmallTable,  NdbDictionary::Object::FragAllSmall },
2076   { DictTabInfo::AllNodesMediumTable, NdbDictionary::Object::FragAllMedium },
2077   { DictTabInfo::AllNodesLargeTable,  NdbDictionary::Object::FragAllLarge },
2078   { DictTabInfo::SingleFragment,      NdbDictionary::Object::FragSingle },
2079   { DictTabInfo::DistrKeyHash,      NdbDictionary::Object::DistrKeyHash },
2080   { DictTabInfo::DistrKeyLin,      NdbDictionary::Object::DistrKeyLin },
2081   { DictTabInfo::UserDefined,      NdbDictionary::Object::UserDefined },
2082   { -1, -1 }
2083 };
2084 
2085 static const
2086 ApiKernelMapping
2087 objectTypeMapping[] = {
2088   { DictTabInfo::SystemTable,        NdbDictionary::Object::SystemTable },
2089   { DictTabInfo::UserTable,          NdbDictionary::Object::UserTable },
2090   { DictTabInfo::UniqueHashIndex,    NdbDictionary::Object::UniqueHashIndex },
2091   { DictTabInfo::OrderedIndex,       NdbDictionary::Object::OrderedIndex },
2092   { DictTabInfo::HashIndexTrigger,   NdbDictionary::Object::HashIndexTrigger },
2093   { DictTabInfo::IndexTrigger,       NdbDictionary::Object::IndexTrigger },
2094   { DictTabInfo::SubscriptionTrigger,NdbDictionary::Object::SubscriptionTrigger },
2095   { DictTabInfo::ReadOnlyConstraint ,NdbDictionary::Object::ReadOnlyConstraint },
2096   { DictTabInfo::Tablespace,         NdbDictionary::Object::Tablespace },
2097   { DictTabInfo::LogfileGroup,       NdbDictionary::Object::LogfileGroup },
2098   { DictTabInfo::Datafile,           NdbDictionary::Object::Datafile },
2099   { DictTabInfo::Undofile,           NdbDictionary::Object::Undofile },
2100   { -1, -1 }
2101 };
2102 
2103 static const
2104 ApiKernelMapping
2105 objectStateMapping[] = {
2106   { DictTabInfo::StateOffline,       NdbDictionary::Object::StateOffline },
2107   { DictTabInfo::StateBuilding,      NdbDictionary::Object::StateBuilding },
2108   { DictTabInfo::StateDropping,      NdbDictionary::Object::StateDropping },
2109   { DictTabInfo::StateOnline,        NdbDictionary::Object::StateOnline },
2110   { DictTabInfo::StateBackup,        NdbDictionary::Object::StateBackup },
2111   { DictTabInfo::StateBroken,        NdbDictionary::Object::StateBroken },
2112   { -1, -1 }
2113 };
2114 
2115 static const
2116 ApiKernelMapping
2117 objectStoreMapping[] = {
2118   { DictTabInfo::StoreNotLogged,     NdbDictionary::Object::StoreNotLogged },
2119   { DictTabInfo::StorePermanent,     NdbDictionary::Object::StorePermanent },
2120   { -1, -1 }
2121 };
2122 
2123 static const
2124 ApiKernelMapping
2125 indexTypeMapping[] = {
2126   { DictTabInfo::UniqueHashIndex,    NdbDictionary::Index::UniqueHashIndex },
2127   { DictTabInfo::OrderedIndex,       NdbDictionary::Index::OrderedIndex },
2128   { -1, -1 }
2129 };
2130 
2131 int
parseTableInfo(NdbTableImpl ** ret,const Uint32 * data,Uint32 len,bool fullyQualifiedNames,Uint32 version)2132 NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
2133 				 const Uint32 * data, Uint32 len,
2134 				 bool fullyQualifiedNames,
2135                                  Uint32 version)
2136 {
2137   SimplePropertiesLinearReader it(data, len);
2138   DictTabInfo::Table *tableDesc;
2139   SimpleProperties::UnpackStatus s;
2140   DBUG_ENTER("NdbDictInterface::parseTableInfo");
2141 
2142   tableDesc = (DictTabInfo::Table*)NdbMem_Allocate(sizeof(DictTabInfo::Table));
2143   if (!tableDesc)
2144   {
2145     DBUG_RETURN(4000);
2146   }
2147   tableDesc->init();
2148   s = SimpleProperties::unpack(it, tableDesc,
2149 			       DictTabInfo::TableMapping,
2150 			       DictTabInfo::TableMappingSize,
2151 			       true, true);
2152 
2153   if(s != SimpleProperties::Break){
2154     NdbMem_Free((void*)tableDesc);
2155     DBUG_RETURN(703);
2156   }
2157   const char * internalName = tableDesc->TableName;
2158   const char * externalName = Ndb::externalizeTableName(internalName, fullyQualifiedNames);
2159 
2160   NdbTableImpl * impl = new NdbTableImpl();
2161   impl->m_id = tableDesc->TableId;
2162   impl->m_version = tableDesc->TableVersion;
2163   impl->m_status = NdbDictionary::Object::Retrieved;
2164   if (!impl->m_internalName.assign(internalName) ||
2165       impl->updateMysqlName() ||
2166       !impl->m_externalName.assign(externalName) ||
2167       impl->m_frm.assign(tableDesc->FrmData, tableDesc->FrmLen) ||
2168       impl->m_fd.assign(tableDesc->FragmentData, tableDesc->FragmentDataLen) ||
2169       impl->m_range.assign(tableDesc->RangeListData, tableDesc->RangeListDataLen))
2170   {
2171     DBUG_RETURN(4000);
2172   }
2173   impl->m_fragmentCount = tableDesc->FragmentCount;
2174 
2175   /*
2176     We specifically don't get tablespace data and range/list arrays here
2177     since those are known by the MySQL Server through analysing the
2178     frm file.
2179     Fragment Data contains the real node group mapping and the fragment
2180     identities used for each fragment. At the moment we have no need for
2181     this.
2182     Frm file is needed for autodiscovery.
2183   */
2184 
2185   impl->m_fragmentType = (NdbDictionary::Object::FragmentType)
2186     getApiConstant(tableDesc->FragmentType,
2187 		   fragmentTypeMapping,
2188 		   (Uint32)NdbDictionary::Object::FragUndefined);
2189 
2190   Uint64 max_rows = ((Uint64)tableDesc->MaxRowsHigh) << 32;
2191   max_rows += tableDesc->MaxRowsLow;
2192   impl->m_max_rows = max_rows;
2193   Uint64 min_rows = ((Uint64)tableDesc->MinRowsHigh) << 32;
2194   min_rows += tableDesc->MinRowsLow;
2195   impl->m_min_rows = min_rows;
2196   impl->m_default_no_part_flag = tableDesc->DefaultNoPartFlag;
2197   impl->m_linear_flag = tableDesc->LinearHashFlag;
2198   impl->m_logging = tableDesc->TableLoggedFlag;
2199   impl->m_temporary = tableDesc->TableTemporaryFlag;
2200   impl->m_row_gci = tableDesc->RowGCIFlag;
2201   impl->m_row_checksum = tableDesc->RowChecksumFlag;
2202   impl->m_force_var_part = tableDesc->ForceVarPartFlag;
2203   impl->m_kvalue = tableDesc->TableKValue;
2204   impl->m_minLoadFactor = tableDesc->MinLoadFactor;
2205   impl->m_maxLoadFactor = tableDesc->MaxLoadFactor;
2206   impl->m_single_user_mode = tableDesc->SingleUserMode;
2207 
2208   impl->m_indexType = (NdbDictionary::Object::Type)
2209     getApiConstant(tableDesc->TableType,
2210 		   indexTypeMapping,
2211 		   NdbDictionary::Object::TypeUndefined);
2212 
2213   if(impl->m_indexType == NdbDictionary::Object::TypeUndefined){
2214   } else {
2215     const char * externalPrimary =
2216       Ndb::externalizeTableName(tableDesc->PrimaryTable, fullyQualifiedNames);
2217     if (!impl->m_primaryTable.assign(externalPrimary))
2218     {
2219       DBUG_RETURN(4000);
2220     }
2221   }
2222 
2223   Uint32 i;
2224   for(i = 0; i < tableDesc->NoOfAttributes; i++) {
2225     DictTabInfo::Attribute attrDesc; attrDesc.init();
2226     s = SimpleProperties::unpack(it,
2227 				 &attrDesc,
2228 				 DictTabInfo::AttributeMapping,
2229 				 DictTabInfo::AttributeMappingSize,
2230 				 true, true);
2231     if(s != SimpleProperties::Break){
2232       delete impl;
2233       NdbMem_Free((void*)tableDesc);
2234       DBUG_RETURN(703);
2235     }
2236 
2237     NdbColumnImpl * col = new NdbColumnImpl();
2238     col->m_attrId = attrDesc.AttributeId;
2239     col->setName(attrDesc.AttributeName);
2240 
2241     // check type and compute attribute size and array size
2242     if (! attrDesc.translateExtType()) {
2243       delete col;
2244       delete impl;
2245       NdbMem_Free((void*)tableDesc);
2246       DBUG_RETURN(703);
2247     }
2248     col->m_type = (NdbDictionary::Column::Type)attrDesc.AttributeExtType;
2249     col->m_precision = (attrDesc.AttributeExtPrecision & 0xFFFF);
2250     col->m_scale = attrDesc.AttributeExtScale;
2251     col->m_length = attrDesc.AttributeExtLength;
2252     // charset in upper half of precision
2253     unsigned cs_number = (attrDesc.AttributeExtPrecision >> 16);
2254     // charset is defined exactly for char types
2255     if (col->getCharType() != (cs_number != 0)) {
2256       delete col;
2257       delete impl;
2258       NdbMem_Free((void*)tableDesc);
2259       DBUG_RETURN(703);
2260     }
2261     if (col->getCharType()) {
2262       col->m_cs = get_charset(cs_number, MYF(0));
2263       if (col->m_cs == NULL) {
2264         delete col;
2265         delete impl;
2266         NdbMem_Free((void*)tableDesc);
2267         DBUG_RETURN(743);
2268       }
2269     }
2270     col->m_attrSize = (1 << attrDesc.AttributeSize) / 8;
2271     col->m_arraySize = attrDesc.AttributeArraySize;
2272     col->m_arrayType = attrDesc.AttributeArrayType;
2273     if(attrDesc.AttributeSize == 0)
2274     {
2275       col->m_attrSize = 4;
2276       col->m_arraySize = (attrDesc.AttributeArraySize + 31) >> 5;
2277     }
2278     col->m_storageType = attrDesc.AttributeStorageType;
2279 
2280     col->m_pk = attrDesc.AttributeKeyFlag;
2281     col->m_distributionKey = (attrDesc.AttributeDKey != 0);
2282     col->m_nullable = attrDesc.AttributeNullableFlag;
2283     col->m_autoIncrement = (attrDesc.AttributeAutoIncrement != 0);
2284     col->m_autoIncrementInitialValue = ~0;
2285     if (!col->m_defaultValue.assign(attrDesc.AttributeDefaultValue))
2286     {
2287       delete col;
2288       delete impl;
2289       DBUG_RETURN(4000);
2290     }
2291 
2292     col->m_column_no = impl->m_columns.size();
2293     impl->m_columns.push_back(col);
2294     it.next();
2295   }
2296 
2297   impl->computeAggregates();
2298 
2299   if(tableDesc->ReplicaDataLen > 0)
2300   {
2301     Uint16 replicaCount = ntohs(tableDesc->ReplicaData[0]);
2302     Uint16 fragCount = ntohs(tableDesc->ReplicaData[1]);
2303 
2304     impl->m_replicaCount = replicaCount;
2305     impl->m_fragmentCount = fragCount;
2306     DBUG_PRINT("info", ("replicaCount=%x , fragCount=%x",replicaCount,fragCount));
2307     Uint32 pos = 2;
2308     for(i = 0; i < (Uint32) fragCount;i++)
2309     {
2310       pos++; // skip logpart
2311       for (Uint32 j = 0; j<(Uint32)replicaCount; j++)
2312       {
2313 	if (impl->m_fragments.push_back(ntohs(tableDesc->ReplicaData[pos++])))
2314 	{
2315           delete impl;
2316           DBUG_RETURN(4000);
2317         }
2318       }
2319     }
2320 
2321     Uint32 topBit = (1 << 31);
2322     for(; topBit && !(fragCount & topBit); ){
2323       topBit >>= 1;
2324     }
2325     impl->m_hashValueMask = topBit - 1;
2326     impl->m_hashpointerValue = fragCount - (impl->m_hashValueMask + 1);
2327   }
2328   else
2329   {
2330     impl->m_fragmentCount = tableDesc->FragmentCount;
2331     impl->m_replicaCount = 0;
2332     impl->m_hashValueMask = 0;
2333     impl->m_hashpointerValue = 0;
2334   }
2335 
2336   impl->m_tablespace_id = tableDesc->TablespaceId;
2337   impl->m_tablespace_version = tableDesc->TablespaceVersion;
2338 
2339   * ret = impl;
2340 
2341   NdbMem_Free((void*)tableDesc);
2342   if (version < MAKE_VERSION(5,1,3))
2343   {
2344     ;
2345   }
2346   else
2347   {
2348     DBUG_ASSERT(impl->m_fragmentCount > 0);
2349   }
2350   DBUG_RETURN(0);
2351 }
2352 
2353 /*****************************************************************
2354  * Create table and alter table
2355  */
2356 int
createTable(NdbTableImpl & t)2357 NdbDictionaryImpl::createTable(NdbTableImpl &t)
2358 {
2359   DBUG_ENTER("NdbDictionaryImpl::createTable");
2360 
2361 
2362   bool autoIncrement = false;
2363   Uint64 initialValue = 0;
2364   for (Uint32 i = 0; i < t.m_columns.size(); i++) {
2365     const NdbColumnImpl* c = t.m_columns[i];
2366     assert(c != NULL);
2367     if (c->m_autoIncrement) {
2368       if (autoIncrement) {
2369         m_error.code = 4335;
2370         DBUG_RETURN(-1);
2371       }
2372       autoIncrement = true;
2373       initialValue = c->m_autoIncrementInitialValue;
2374     }
2375   }
2376 
2377   // if the new name has not been set, use the copied name
2378   if (t.m_newExternalName.empty())
2379   {
2380     if (!t.m_newExternalName.assign(t.m_externalName))
2381     {
2382       m_error.code= 4000;
2383       DBUG_RETURN(-1);
2384     }
2385   }
2386   // create table
2387   if (m_receiver.createTable(m_ndb, t) != 0)
2388     DBUG_RETURN(-1);
2389   Uint32* data = (Uint32*)m_receiver.m_buffer.get_data();
2390   t.m_id = data[0];
2391   t.m_version = data[1];
2392 
2393   // update table def from DICT - by-pass cache
2394   NdbTableImpl* t2 =
2395     m_receiver.getTable(t.m_internalName, m_ndb.usingFullyQualifiedNames());
2396 
2397   // check if we got back same table
2398   if (t2 == NULL) {
2399     DBUG_PRINT("info", ("table %s dropped by another thread",
2400                         t.m_internalName.c_str()));
2401     m_error.code = 283;
2402     DBUG_RETURN(-1);
2403   }
2404   if (t.m_id != t2->m_id || t.m_version != t2->m_version) {
2405     DBUG_PRINT("info", ("table %s re-created by another thread",
2406                         t.m_internalName.c_str()));
2407     m_error.code = 283;
2408     delete t2;
2409     DBUG_RETURN(-1);
2410   }
2411 
2412   // auto-increment - use "t" because initial value is not in DICT
2413   {
2414     if (autoIncrement) {
2415       // XXX unlikely race condition - t.m_id may no longer be same table
2416       // the tuple id range is not used on input
2417       Ndb::TupleIdRange range;
2418       if (m_ndb.setTupleIdInNdb(&t, range, initialValue, false) == -1) {
2419         assert(m_ndb.theError.code != 0);
2420         m_error.code = m_ndb.theError.code;
2421         delete t2;
2422         DBUG_RETURN(-1);
2423       }
2424     }
2425   }
2426 
2427   // blob tables - use "t2" to get values set by kernel
2428   if (t2->m_noOfBlobs != 0 && createBlobTables(t, *t2) != 0) {
2429     int save_code = m_error.code;
2430     (void)dropTableGlobal(*t2);
2431     m_error.code = save_code;
2432     delete t2;
2433     DBUG_RETURN(-1);
2434   }
2435 
2436   // not entered in cache
2437   delete t2;
2438   DBUG_RETURN(0);
2439 }
2440 
2441 int
createBlobTables(NdbTableImpl & orig,NdbTableImpl & t)2442 NdbDictionaryImpl::createBlobTables(NdbTableImpl& orig, NdbTableImpl &t)
2443 {
2444   DBUG_ENTER("NdbDictionaryImpl::createBlobTables");
2445   for (unsigned i = 0; i < t.m_columns.size(); i++) {
2446     NdbColumnImpl & c = *t.m_columns[i];
2447     if (! c.getBlobType() || c.getPartSize() == 0)
2448       continue;
2449     NdbTableImpl bt;
2450     NdbBlob::getBlobTable(bt, &t, &c);
2451     NdbDictionary::Column::StorageType
2452       d = NdbDictionary::Column::StorageTypeDisk;
2453     if (orig.m_columns[i]->getStorageType() == d)
2454       bt.getColumn("DATA")->setStorageType(d);
2455     if (createTable(bt) != 0) {
2456       DBUG_RETURN(-1);
2457     }
2458   }
2459   DBUG_RETURN(0);
2460 }
2461 
2462 int
createTable(Ndb & ndb,NdbTableImpl & impl)2463 NdbDictInterface::createTable(Ndb & ndb,
2464 			      NdbTableImpl & impl)
2465 {
2466   DBUG_ENTER("NdbDictInterface::createTable");
2467   DBUG_RETURN(createOrAlterTable(ndb, impl, false));
2468 }
2469 
alterTable(NdbTableImpl & impl)2470 int NdbDictionaryImpl::alterTable(NdbTableImpl &impl)
2471 {
2472   BaseString internalName(impl.m_internalName);
2473   const char * originalInternalName = internalName.c_str();
2474 
2475   DBUG_ENTER("NdbDictionaryImpl::alterTable");
2476   Ndb_local_table_info * local = 0;
2477   if((local= get_local_table_info(originalInternalName)) == 0)
2478   {
2479     m_error.code = 709;
2480     DBUG_RETURN(-1);
2481   }
2482 
2483   // Alter the table
2484   int ret = alterTableGlobal(*local->m_table_impl, impl);
2485   if(ret == 0)
2486   {
2487     m_globalHash->lock();
2488     m_globalHash->release(local->m_table_impl, 1);
2489     m_globalHash->unlock();
2490     m_localHash.drop(originalInternalName);
2491   }
2492   DBUG_RETURN(ret);
2493 }
2494 
alterTableGlobal(NdbTableImpl & old_impl,NdbTableImpl & impl)2495 int NdbDictionaryImpl::alterTableGlobal(NdbTableImpl &old_impl,
2496                                         NdbTableImpl &impl)
2497 {
2498   DBUG_ENTER("NdbDictionaryImpl::alterTableGlobal");
2499   // Alter the table
2500   int ret = m_receiver.alterTable(m_ndb, impl);
2501   old_impl.m_status = NdbDictionary::Object::Invalid;
2502   if(ret == 0){
2503     DBUG_RETURN(ret);
2504   }
2505   ERR_RETURN(getNdbError(), ret);
2506 }
2507 
2508 int
alterTable(Ndb & ndb,NdbTableImpl & impl)2509 NdbDictInterface::alterTable(Ndb & ndb,
2510 			      NdbTableImpl & impl)
2511 {
2512   DBUG_ENTER("NdbDictInterface::alterTable");
2513   DBUG_RETURN(createOrAlterTable(ndb, impl, true));
2514 }
2515 
2516 int
createOrAlterTable(Ndb & ndb,NdbTableImpl & impl,bool alter)2517 NdbDictInterface::createOrAlterTable(Ndb & ndb,
2518 				     NdbTableImpl & impl,
2519 				     bool alter)
2520 {
2521   unsigned i, err;
2522   char *ts_names[MAX_NDB_PARTITIONS];
2523   DBUG_ENTER("NdbDictInterface::createOrAlterTable");
2524 
2525   impl.computeAggregates();
2526 
2527   if((unsigned)impl.getNoOfPrimaryKeys() > NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY){
2528     m_error.code= 4317;
2529     DBUG_RETURN(-1);
2530   }
2531   unsigned sz = impl.m_columns.size();
2532   if (sz > NDB_MAX_ATTRIBUTES_IN_TABLE){
2533     m_error.code= 4318;
2534     DBUG_RETURN(-1);
2535   }
2536 
2537   // Check if any changes for alter table
2538 
2539   // Name change
2540   if (!impl.m_newExternalName.empty()) {
2541     if (alter)
2542     {
2543       AlterTableReq::setNameFlag(impl.m_changeMask, true);
2544     }
2545     if (!impl.m_externalName.assign(impl.m_newExternalName))
2546     {
2547       m_error.code= 4000;
2548       DBUG_RETURN(-1);
2549     }
2550     impl.m_newExternalName.clear();
2551   }
2552   // Definition change (frm)
2553   if (!impl.m_newFrm.empty())
2554   {
2555     if (alter)
2556     {
2557       AlterTableReq::setFrmFlag(impl.m_changeMask, true);
2558     }
2559     if (impl.m_frm.assign(impl.m_newFrm.get_data(), impl.m_newFrm.length()))
2560     {
2561       m_error.code= 4000;
2562       DBUG_RETURN(-1);
2563     }
2564     impl.m_newFrm.clear();
2565   }
2566   // Change FragmentData (fragment identity, state, tablespace id)
2567   if (!impl.m_new_fd.empty())
2568   {
2569     if (alter)
2570     {
2571       AlterTableReq::setFragDataFlag(impl.m_changeMask, true);
2572     }
2573     if (impl.m_fd.assign(impl.m_new_fd.get_data(), impl.m_new_fd.length()))
2574     {
2575       m_error.code= 4000;
2576       DBUG_RETURN(-1);
2577     }
2578     impl.m_new_fd.clear();
2579   }
2580   // Change Tablespace Name Data
2581   if (!impl.m_new_ts_name.empty())
2582   {
2583     if (alter)
2584     {
2585       AlterTableReq::setTsNameFlag(impl.m_changeMask, true);
2586     }
2587     if (impl.m_ts_name.assign(impl.m_new_ts_name.get_data(),
2588                               impl.m_new_ts_name.length()))
2589     {
2590       m_error.code= 4000;
2591       DBUG_RETURN(-1);
2592     }
2593     impl.m_new_ts_name.clear();
2594   }
2595   // Change Range/List Data
2596   if (!impl.m_new_range.empty())
2597   {
2598     if (alter)
2599     {
2600       AlterTableReq::setRangeListFlag(impl.m_changeMask, true);
2601     }
2602     if (impl.m_range.assign(impl.m_new_range.get_data(),
2603                             impl.m_new_range.length()))
2604     {
2605       m_error.code= 4000;
2606       DBUG_RETURN(-1);
2607     }
2608     impl.m_new_range.clear();
2609   }
2610   // Change Tablespace Data
2611   if (!impl.m_new_ts.empty())
2612   {
2613     if (alter)
2614     {
2615       AlterTableReq::setTsFlag(impl.m_changeMask, true);
2616     }
2617     if (impl.m_ts.assign(impl.m_new_ts.get_data(),
2618                          impl.m_new_ts.length()))
2619     {
2620       m_error.code= 4000;
2621       DBUG_RETURN(-1);
2622     }
2623     impl.m_new_ts.clear();
2624   }
2625 
2626 
2627   /*
2628      TODO RONM: Here I need to insert checks for fragment array and
2629      range or list array
2630   */
2631 
2632   //validate();
2633   //aggregate();
2634 
2635   const BaseString internalName(
2636     ndb.internalize_table_name(impl.m_externalName.c_str()));
2637   if (!impl.m_internalName.assign(internalName))
2638   {
2639     m_error.code= 4000;
2640     DBUG_RETURN(-1);
2641   }
2642   impl.updateMysqlName();
2643   DictTabInfo::Table *tmpTab;
2644 
2645   tmpTab = (DictTabInfo::Table*)NdbMem_Allocate(sizeof(DictTabInfo::Table));
2646   if (!tmpTab)
2647   {
2648     m_error.code = 4000;
2649     DBUG_RETURN(-1);
2650   }
2651   tmpTab->init();
2652   BaseString::snprintf(tmpTab->TableName,
2653 	   sizeof(tmpTab->TableName),
2654 	   internalName.c_str());
2655 
2656   Uint32 distKeys= 0;
2657   for(i = 0; i<sz; i++) {
2658     const NdbColumnImpl * col = impl.m_columns[i];
2659     if (col == NULL) {
2660       m_error.code = 4272;
2661       NdbMem_Free((void*)tmpTab);
2662       DBUG_RETURN(-1);
2663     }
2664     if (col->m_distributionKey)
2665     {
2666       distKeys++;
2667     }
2668   }
2669   if (distKeys == impl.m_noOfKeys)
2670     distKeys= 0;
2671   impl.m_noOfDistributionKeys= distKeys;
2672 
2673 
2674   // Check max length of frm data
2675   if (impl.m_frm.length() > MAX_FRM_DATA_SIZE){
2676     m_error.code= 1229;
2677     NdbMem_Free((void*)tmpTab);
2678     DBUG_RETURN(-1);
2679   }
2680   /*
2681     TODO RONM: This needs to change to dynamic arrays instead
2682     Frm Data, FragmentData, TablespaceData, RangeListData, TsNameData
2683   */
2684   tmpTab->FrmLen = impl.m_frm.length();
2685   memcpy(tmpTab->FrmData, impl.m_frm.get_data(), impl.m_frm.length());
2686 
2687   tmpTab->FragmentDataLen = impl.m_fd.length();
2688   memcpy(tmpTab->FragmentData, impl.m_fd.get_data(), impl.m_fd.length());
2689 
2690   tmpTab->TablespaceDataLen = impl.m_ts.length();
2691   memcpy(tmpTab->TablespaceData, impl.m_ts.get_data(), impl.m_ts.length());
2692 
2693   tmpTab->RangeListDataLen = impl.m_range.length();
2694   memcpy(tmpTab->RangeListData, impl.m_range.get_data(),
2695          impl.m_range.length());
2696 
2697   memcpy(ts_names, impl.m_ts_name.get_data(),
2698          impl.m_ts_name.length());
2699 
2700   tmpTab->FragmentCount= impl.m_fragmentCount;
2701   tmpTab->TableLoggedFlag = impl.m_logging;
2702   tmpTab->TableTemporaryFlag = impl.m_temporary;
2703   tmpTab->RowGCIFlag = impl.m_row_gci;
2704   tmpTab->RowChecksumFlag = impl.m_row_checksum;
2705   tmpTab->TableKValue = impl.m_kvalue;
2706   tmpTab->MinLoadFactor = impl.m_minLoadFactor;
2707   tmpTab->MaxLoadFactor = impl.m_maxLoadFactor;
2708   tmpTab->TableType = DictTabInfo::UserTable;
2709   tmpTab->PrimaryTableId = impl.m_primaryTableId;
2710   tmpTab->NoOfAttributes = sz;
2711   tmpTab->MaxRowsHigh = (Uint32)(impl.m_max_rows >> 32);
2712   tmpTab->MaxRowsLow = (Uint32)(impl.m_max_rows & 0xFFFFFFFF);
2713   tmpTab->MinRowsHigh = (Uint32)(impl.m_min_rows >> 32);
2714   tmpTab->MinRowsLow = (Uint32)(impl.m_min_rows & 0xFFFFFFFF);
2715   tmpTab->DefaultNoPartFlag = impl.m_default_no_part_flag;
2716   tmpTab->LinearHashFlag = impl.m_linear_flag;
2717   tmpTab->SingleUserMode = impl.m_single_user_mode;
2718   tmpTab->ForceVarPartFlag = impl.m_force_var_part;
2719 
2720   if (impl.m_ts_name.length())
2721   {
2722     char **ts_name_ptr= (char**)ts_names;
2723     i= 0;
2724     do
2725     {
2726       NdbTablespaceImpl tmp;
2727       if (*ts_name_ptr)
2728       {
2729         if(get_filegroup(tmp, NdbDictionary::Object::Tablespace,
2730                          (const char*)*ts_name_ptr) == 0)
2731         {
2732           tmpTab->TablespaceData[2*i] = tmp.m_id;
2733           tmpTab->TablespaceData[2*i + 1] = tmp.m_version;
2734         }
2735         else
2736         {
2737           NdbMem_Free((void*)tmpTab);
2738           DBUG_RETURN(-1);
2739         }
2740       }
2741       else
2742       {
2743         /*
2744           No tablespace used, set tablespace id to NULL
2745         */
2746         tmpTab->TablespaceData[2*i] = RNIL;
2747         tmpTab->TablespaceData[2*i + 1] = 0;
2748       }
2749       ts_name_ptr++;
2750     } while (++i < tmpTab->FragmentCount);
2751     tmpTab->TablespaceDataLen= 4*i;
2752   }
2753 
2754   tmpTab->FragmentType = getKernelConstant(impl.m_fragmentType,
2755  					   fragmentTypeMapping,
2756 					   DictTabInfo::AllNodesSmallTable);
2757   tmpTab->TableVersion = rand();
2758 
2759   const char *tablespace_name= impl.m_tablespace_name.c_str();
2760 loop:
2761   if(impl.m_tablespace_id != ~(Uint32)0)
2762   {
2763     tmpTab->TablespaceId = impl.m_tablespace_id;
2764     tmpTab->TablespaceVersion = impl.m_tablespace_version;
2765   }
2766   else if(strlen(tablespace_name))
2767   {
2768     NdbTablespaceImpl tmp;
2769     if(get_filegroup(tmp, NdbDictionary::Object::Tablespace,
2770 		     tablespace_name) == 0)
2771     {
2772       tmpTab->TablespaceId = tmp.m_id;
2773       tmpTab->TablespaceVersion = tmp.m_version;
2774     }
2775     else
2776     {
2777       // error set by get filegroup
2778       if (m_error.code == 723)
2779 	m_error.code = 755;
2780 
2781       NdbMem_Free((void*)tmpTab);
2782       DBUG_RETURN(-1);
2783     }
2784   }
2785   else
2786   {
2787     for(i = 0; i<sz; i++)
2788     {
2789       if(impl.m_columns[i]->m_storageType == NDB_STORAGETYPE_DISK)
2790       {
2791 	tablespace_name = "DEFAULT-TS";
2792 	goto loop;
2793       }
2794     }
2795   }
2796 
2797   UtilBufferWriter w(m_buffer);
2798   SimpleProperties::UnpackStatus s;
2799   s = SimpleProperties::pack(w,
2800 			     tmpTab,
2801 			     DictTabInfo::TableMapping,
2802 			     DictTabInfo::TableMappingSize, true);
2803 
2804   if(s != SimpleProperties::Eof){
2805     abort();
2806   }
2807   NdbMem_Free((void*)tmpTab);
2808 
2809   DBUG_PRINT("info",("impl.m_noOfDistributionKeys: %d impl.m_noOfKeys: %d distKeys: %d",
2810 		     impl.m_noOfDistributionKeys, impl.m_noOfKeys, distKeys));
2811   if (distKeys == impl.m_noOfKeys)
2812     distKeys= 0;
2813   impl.m_noOfDistributionKeys= distKeys;
2814 
2815   for(i = 0; i<sz; i++){
2816     const NdbColumnImpl * col = impl.m_columns[i];
2817     if(col == 0)
2818       continue;
2819 
2820     DBUG_PRINT("info",("column: %s(%d) col->m_distributionKey: %d",
2821 		       col->m_name.c_str(), i, col->m_distributionKey));
2822     DictTabInfo::Attribute tmpAttr; tmpAttr.init();
2823     BaseString::snprintf(tmpAttr.AttributeName, sizeof(tmpAttr.AttributeName),
2824 	     col->m_name.c_str());
2825     tmpAttr.AttributeId = col->m_attrId;
2826     tmpAttr.AttributeKeyFlag = col->m_pk;
2827     tmpAttr.AttributeNullableFlag = col->m_nullable;
2828     tmpAttr.AttributeDKey = distKeys ? col->m_distributionKey : 0;
2829 
2830     tmpAttr.AttributeExtType = (Uint32)col->m_type;
2831     tmpAttr.AttributeExtPrecision = ((unsigned)col->m_precision & 0xFFFF);
2832     tmpAttr.AttributeExtScale = col->m_scale;
2833     tmpAttr.AttributeExtLength = col->m_length;
2834     if(col->m_storageType == NDB_STORAGETYPE_DISK)
2835       tmpAttr.AttributeArrayType = NDB_ARRAYTYPE_FIXED;
2836     else
2837       tmpAttr.AttributeArrayType = col->m_arrayType;
2838 
2839     if(col->m_pk)
2840       tmpAttr.AttributeStorageType = NDB_STORAGETYPE_MEMORY;
2841     else
2842       tmpAttr.AttributeStorageType = col->m_storageType;
2843 
2844     if(col->getBlobType())
2845       tmpAttr.AttributeStorageType = NDB_STORAGETYPE_MEMORY;
2846 
2847     // check type and compute attribute size and array size
2848     if (! tmpAttr.translateExtType()) {
2849       m_error.code= 703;
2850       DBUG_RETURN(-1);
2851     }
2852     // charset is defined exactly for char types
2853     if (col->getCharType() != (col->m_cs != NULL)) {
2854       m_error.code= 703;
2855       DBUG_RETURN(-1);
2856     }
2857     // primary key type check
2858     if (col->m_pk &&
2859         (err = NdbSqlUtil::check_column_for_pk(col->m_type, col->m_cs)))
2860     {
2861       m_error.code= err;
2862       DBUG_RETURN(-1);
2863     }
2864     // distribution key not supported for Char attribute
2865     if (distKeys && col->m_distributionKey && col->m_cs != NULL) {
2866       // we can allow this for non-var char where strxfrm does nothing
2867       if (col->m_type == NdbDictionary::Column::Char &&
2868           (col->m_cs->state & MY_CS_BINSORT))
2869         ;
2870       else {
2871         m_error.code= 745;
2872         DBUG_RETURN(-1);
2873       }
2874     }
2875     // charset in upper half of precision
2876     if (col->getCharType()) {
2877       tmpAttr.AttributeExtPrecision |= (col->m_cs->number << 16);
2878     }
2879 
2880     tmpAttr.AttributeAutoIncrement = col->m_autoIncrement;
2881     BaseString::snprintf(tmpAttr.AttributeDefaultValue,
2882 	     sizeof(tmpAttr.AttributeDefaultValue),
2883 	     col->m_defaultValue.c_str());
2884     s = SimpleProperties::pack(w,
2885 			       &tmpAttr,
2886 			       DictTabInfo::AttributeMapping,
2887 			       DictTabInfo::AttributeMappingSize, true);
2888     w.add(DictTabInfo::AttributeEnd, 1);
2889   }
2890 
2891   int ret;
2892 
2893   LinearSectionPtr ptr[1];
2894   ptr[0].p = (Uint32*)m_buffer.get_data();
2895   ptr[0].sz = m_buffer.length() / 4;
2896   NdbApiSignal tSignal(m_reference);
2897   tSignal.theReceiversBlockNumber = DBDICT;
2898   if (alter) {
2899     tSignal.theVerId_signalNumber   = GSN_ALTER_TABLE_REQ;
2900     tSignal.theLength = AlterTableReq::SignalLength;
2901 
2902     AlterTableReq * req = CAST_PTR(AlterTableReq, tSignal.getDataPtrSend());
2903 
2904     req->senderRef = m_reference;
2905     req->senderData = 0;
2906     req->changeMask = impl.m_changeMask;
2907     req->tableId = impl.m_id;
2908     req->tableVersion = impl.m_version;;
2909 
2910     int errCodes[] = { AlterTableRef::NotMaster, AlterTableRef::Busy, 0 };
2911     ret = dictSignal(&tSignal, ptr, 1,
2912 		     0, // master
2913 		     WAIT_ALTER_TAB_REQ,
2914 		     DICT_WAITFOR_TIMEOUT, 100,
2915 		     errCodes);
2916 
2917     if(m_error.code == AlterTableRef::InvalidTableVersion) {
2918       // Clear caches and try again
2919       DBUG_RETURN(INCOMPATIBLE_VERSION);
2920     }
2921   } else {
2922     tSignal.theVerId_signalNumber   = GSN_CREATE_TABLE_REQ;
2923     tSignal.theLength = CreateTableReq::SignalLength;
2924 
2925     CreateTableReq * req = CAST_PTR(CreateTableReq, tSignal.getDataPtrSend());
2926     req->senderRef = m_reference;
2927     req->senderData = 0;
2928     int errCodes[] = { CreateTableRef::Busy, CreateTableRef::NotMaster, 0 };
2929     ret = dictSignal(&tSignal, ptr, 1,
2930 		     0, // master node
2931 		     WAIT_CREATE_INDX_REQ,
2932 		     DICT_WAITFOR_TIMEOUT, 100,
2933 		     errCodes);
2934   }
2935 
2936   DBUG_RETURN(ret);
2937 }
2938 
2939 void
execCREATE_TABLE_CONF(NdbApiSignal * signal,LinearSectionPtr ptr[3])2940 NdbDictInterface::execCREATE_TABLE_CONF(NdbApiSignal * signal,
2941 					LinearSectionPtr ptr[3])
2942 {
2943   const CreateTableConf* const conf=
2944     CAST_CONSTPTR(CreateTableConf, signal->getDataPtr());
2945   m_buffer.grow(4 * 2); // 2 words
2946   Uint32* data = (Uint32*)m_buffer.get_data();
2947   data[0] = conf->tableId;
2948   data[1] = conf->tableVersion;
2949   m_waiter.signal(NO_WAIT);
2950 }
2951 
2952 void
execCREATE_TABLE_REF(NdbApiSignal * sig,LinearSectionPtr ptr[3])2953 NdbDictInterface::execCREATE_TABLE_REF(NdbApiSignal * sig,
2954 				       LinearSectionPtr ptr[3])
2955 {
2956   const CreateTableRef* ref = CAST_CONSTPTR(CreateTableRef, sig->getDataPtr());
2957   m_error.code= ref->errorCode;
2958   m_masterNodeId = ref->masterNodeId;
2959   m_waiter.signal(NO_WAIT);
2960 }
2961 
2962 void
execALTER_TABLE_CONF(NdbApiSignal * signal,LinearSectionPtr ptr[3])2963 NdbDictInterface::execALTER_TABLE_CONF(NdbApiSignal * signal,
2964                                        LinearSectionPtr ptr[3])
2965 {
2966   m_waiter.signal(NO_WAIT);
2967 }
2968 
2969 void
execALTER_TABLE_REF(NdbApiSignal * sig,LinearSectionPtr ptr[3])2970 NdbDictInterface::execALTER_TABLE_REF(NdbApiSignal * sig,
2971 				      LinearSectionPtr ptr[3])
2972 {
2973   const AlterTableRef * ref = CAST_CONSTPTR(AlterTableRef, sig->getDataPtr());
2974   m_error.code= ref->errorCode;
2975   m_masterNodeId = ref->masterNodeId;
2976   m_waiter.signal(NO_WAIT);
2977 }
2978 
2979 /*****************************************************************
2980  * Drop table
2981  */
2982 int
dropTable(const char * name)2983 NdbDictionaryImpl::dropTable(const char * name)
2984 {
2985   DBUG_ENTER("NdbDictionaryImpl::dropTable");
2986   DBUG_PRINT("enter",("name: %s", name));
2987   ASSERT_NOT_MYSQLD;
2988   NdbTableImpl * tab = getTable(name);
2989   if(tab == 0){
2990     DBUG_RETURN(-1);
2991   }
2992   int ret = dropTable(* tab);
2993   // If table stored in cache is incompatible with the one in the kernel
2994   // we must clear the cache and try again
2995   if (ret == INCOMPATIBLE_VERSION) {
2996     const BaseString internalTableName(m_ndb.internalize_table_name(name));
2997     DBUG_PRINT("info",("INCOMPATIBLE_VERSION internal_name: %s", internalTableName.c_str()));
2998     m_localHash.drop(internalTableName.c_str());
2999     m_globalHash->lock();
3000     m_globalHash->release(tab, 1);
3001     m_globalHash->unlock();
3002     DBUG_RETURN(dropTable(name));
3003   }
3004 
3005   DBUG_RETURN(ret);
3006 }
3007 
3008 int
dropTable(NdbTableImpl & impl)3009 NdbDictionaryImpl::dropTable(NdbTableImpl & impl)
3010 {
3011   int res;
3012   const char * name = impl.getName();
3013   if(impl.m_status == NdbDictionary::Object::New){
3014     return dropTable(name);
3015   }
3016 
3017   if (impl.m_indexType != NdbDictionary::Object::TypeUndefined)
3018   {
3019     m_receiver.m_error.code= 1228;
3020     return -1;
3021   }
3022 
3023   List list;
3024   if ((res = listIndexes(list, impl.m_id)) == -1){
3025     return -1;
3026   }
3027   for (unsigned i = 0; i < list.count; i++) {
3028     const List::Element& element = list.elements[i];
3029     if ((res = dropIndex(element.name, name)) == -1)
3030     {
3031       return -1;
3032     }
3033   }
3034 
3035   if (impl.m_noOfBlobs != 0) {
3036     if (dropBlobTables(impl) != 0){
3037       return -1;
3038     }
3039   }
3040 
3041   int ret = m_receiver.dropTable(impl);
3042   if(ret == 0 || m_error.code == 709 || m_error.code == 723){
3043     const char * internalTableName = impl.m_internalName.c_str();
3044 
3045 
3046     m_localHash.drop(internalTableName);
3047     m_globalHash->lock();
3048     m_globalHash->release(&impl, 1);
3049     m_globalHash->unlock();
3050 
3051     return 0;
3052   }
3053 
3054   return ret;
3055 }
3056 
3057 int
dropTableGlobal(NdbTableImpl & impl)3058 NdbDictionaryImpl::dropTableGlobal(NdbTableImpl & impl)
3059 {
3060   int res;
3061   DBUG_ENTER("NdbDictionaryImpl::dropTableGlobal");
3062   DBUG_ASSERT(impl.m_status != NdbDictionary::Object::New);
3063   DBUG_ASSERT(impl.m_indexType == NdbDictionary::Object::TypeUndefined);
3064 
3065   List list;
3066   if ((res = listIndexes(list, impl.m_id)) == -1){
3067     ERR_RETURN(getNdbError(), -1);
3068   }
3069   for (unsigned i = 0; i < list.count; i++) {
3070     const List::Element& element = list.elements[i];
3071     NdbIndexImpl *idx= getIndexGlobal(element.name, impl);
3072     if (idx == NULL)
3073     {
3074       ERR_RETURN(getNdbError(), -1);
3075     }
3076     if ((res = dropIndexGlobal(*idx)) == -1)
3077     {
3078       releaseIndexGlobal(*idx, 1);
3079       ERR_RETURN(getNdbError(), -1);
3080     }
3081     releaseIndexGlobal(*idx, 1);
3082   }
3083 
3084   if (impl.m_noOfBlobs != 0) {
3085     if (dropBlobTables(impl) != 0){
3086       ERR_RETURN(getNdbError(), -1);
3087     }
3088   }
3089 
3090   int ret = m_receiver.dropTable(impl);
3091   impl.m_status = NdbDictionary::Object::Invalid;
3092   if(ret == 0 || m_error.code == 709 || m_error.code == 723)
3093   {
3094     DBUG_RETURN(0);
3095   }
3096 
3097   ERR_RETURN(getNdbError(), ret);
3098 }
3099 
3100 int
dropBlobTables(NdbTableImpl & t)3101 NdbDictionaryImpl::dropBlobTables(NdbTableImpl & t)
3102 {
3103   DBUG_ENTER("NdbDictionaryImpl::dropBlobTables");
3104   for (unsigned i = 0; i < t.m_columns.size(); i++) {
3105     NdbColumnImpl & c = *t.m_columns[i];
3106     if (! c.getBlobType() || c.getPartSize() == 0)
3107       continue;
3108     NdbTableImpl* bt = c.m_blobTable;
3109     if (bt == NULL) {
3110       DBUG_PRINT("info", ("col %s: blob table pointer is NULL",
3111                           c.m_name.c_str()));
3112       continue; // "force" mode on
3113     }
3114     // drop directly - by-pass cache
3115     int ret = m_receiver.dropTable(*c.m_blobTable);
3116     if (ret != 0) {
3117       DBUG_PRINT("info", ("col %s: blob table %s: error %d",
3118                  c.m_name.c_str(), bt->m_internalName.c_str(), m_error.code));
3119       if (! (ret == 709 || ret == 723)) // "force" mode on
3120         ERR_RETURN(getNdbError(), -1);
3121     }
3122     // leave c.m_blobTable defined
3123   }
3124   DBUG_RETURN(0);
3125 }
3126 
3127 int
dropTable(const NdbTableImpl & impl)3128 NdbDictInterface::dropTable(const NdbTableImpl & impl)
3129 {
3130   NdbApiSignal tSignal(m_reference);
3131   tSignal.theReceiversBlockNumber = DBDICT;
3132   tSignal.theVerId_signalNumber   = GSN_DROP_TABLE_REQ;
3133   tSignal.theLength = DropTableReq::SignalLength;
3134 
3135   DropTableReq * req = CAST_PTR(DropTableReq, tSignal.getDataPtrSend());
3136   req->senderRef = m_reference;
3137   req->senderData = 0;
3138   req->tableId = impl.m_id;
3139   req->tableVersion = impl.m_version;
3140 
3141   int errCodes[] =
3142     { DropTableRef::NoDropTableRecordAvailable,
3143       DropTableRef::NotMaster,
3144       DropTableRef::Busy, 0 };
3145   int r = dictSignal(&tSignal, 0, 0,
3146 		     0, // master
3147 		     WAIT_DROP_TAB_REQ,
3148 		     DICT_WAITFOR_TIMEOUT, 100,
3149 		     errCodes);
3150   if(m_error.code == DropTableRef::InvalidTableVersion) {
3151     // Clear caches and try again
3152     return INCOMPATIBLE_VERSION;
3153   }
3154   return r;
3155 }
3156 
3157 void
execDROP_TABLE_CONF(NdbApiSignal * signal,LinearSectionPtr ptr[3])3158 NdbDictInterface::execDROP_TABLE_CONF(NdbApiSignal * signal,
3159 				       LinearSectionPtr ptr[3])
3160 {
3161   DBUG_ENTER("NdbDictInterface::execDROP_TABLE_CONF");
3162   //DropTableConf* const conf = CAST_CONSTPTR(DropTableConf, signal->getDataPtr());
3163 
3164   m_waiter.signal(NO_WAIT);
3165   DBUG_VOID_RETURN;
3166 }
3167 
3168 void
execDROP_TABLE_REF(NdbApiSignal * signal,LinearSectionPtr ptr[3])3169 NdbDictInterface::execDROP_TABLE_REF(NdbApiSignal * signal,
3170 				      LinearSectionPtr ptr[3])
3171 {
3172   DBUG_ENTER("NdbDictInterface::execDROP_TABLE_REF");
3173   const DropTableRef* ref = CAST_CONSTPTR(DropTableRef, signal->getDataPtr());
3174   m_error.code= ref->errorCode;
3175   m_masterNodeId = ref->masterNodeId;
3176   m_waiter.signal(NO_WAIT);
3177   DBUG_VOID_RETURN;
3178 }
3179 
3180 int
invalidateObject(NdbTableImpl & impl)3181 NdbDictionaryImpl::invalidateObject(NdbTableImpl & impl)
3182 {
3183   const char * internalTableName = impl.m_internalName.c_str();
3184   DBUG_ENTER("NdbDictionaryImpl::invalidateObject");
3185   DBUG_PRINT("enter", ("internal_name: %s", internalTableName));
3186 
3187   m_localHash.drop(internalTableName);
3188   m_globalHash->lock();
3189   m_globalHash->release(&impl, 1);
3190   m_globalHash->unlock();
3191   DBUG_RETURN(0);
3192 }
3193 
3194 int
removeCachedObject(NdbTableImpl & impl)3195 NdbDictionaryImpl::removeCachedObject(NdbTableImpl & impl)
3196 {
3197   const char * internalTableName = impl.m_internalName.c_str();
3198   DBUG_ENTER("NdbDictionaryImpl::removeCachedObject");
3199   DBUG_PRINT("enter", ("internal_name: %s", internalTableName));
3200 
3201   m_localHash.drop(internalTableName);
3202   m_globalHash->lock();
3203   m_globalHash->release(&impl);
3204   m_globalHash->unlock();
3205   DBUG_RETURN(0);
3206 }
3207 
3208 int
create_index_obj_from_table(NdbIndexImpl ** dst,NdbTableImpl * tab,const NdbTableImpl * prim)3209 NdbDictInterface::create_index_obj_from_table(NdbIndexImpl** dst,
3210 					      NdbTableImpl* tab,
3211 					      const NdbTableImpl* prim)
3212 {
3213   DBUG_ENTER("NdbDictInterface::create_index_obj_from_table");
3214   NdbIndexImpl *idx = new NdbIndexImpl();
3215   if (idx == NULL)
3216   {
3217     errno = ENOMEM;
3218     return -1;
3219   }
3220   idx->m_version = tab->m_version;
3221   idx->m_status = tab->m_status;
3222   idx->m_id = tab->m_id;
3223   if (!idx->m_externalName.assign(tab->getName()) ||
3224       !idx->m_tableName.assign(prim->m_externalName))
3225   {
3226     delete idx;
3227     errno = ENOMEM;
3228     return -1;
3229   }
3230   NdbDictionary::Object::Type type = idx->m_type = tab->m_indexType;
3231   idx->m_logging = tab->m_logging;
3232   idx->m_temporary = tab->m_temporary;
3233   // skip last attribute (NDB$PK or NDB$TNODE)
3234 
3235   const Uint32 distKeys = prim->m_noOfDistributionKeys;
3236   Uint32 keyCount = (distKeys ? distKeys : prim->m_noOfKeys);
3237 
3238   unsigned i;
3239   for(i = 0; i+1<tab->m_columns.size(); i++){
3240     NdbColumnImpl* org = tab->m_columns[i];
3241 
3242     NdbColumnImpl* col = new NdbColumnImpl;
3243     if (col == NULL)
3244     {
3245       errno = ENOMEM;
3246       delete idx;
3247       return -1;
3248     }
3249     // Copy column definition
3250     *col = * org;
3251     if (idx->m_columns.push_back(col))
3252     {
3253       delete col;
3254       delete idx;
3255       return -1;
3256     }
3257 
3258     /**
3259      * reverse map
3260      */
3261     const NdbColumnImpl* primCol = prim->getColumn(col->getName());
3262     int key_id = primCol->getColumnNo();
3263     int fill = -1;
3264     idx->m_key_ids.fill(key_id, fill);
3265     idx->m_key_ids[key_id] = i;
3266     col->m_keyInfoPos = key_id;
3267 
3268     if(type == NdbDictionary::Object::OrderedIndex &&
3269        (primCol->m_distributionKey ||
3270 	(distKeys == 0 && primCol->getPrimaryKey())))
3271     {
3272       keyCount--;
3273       org->m_distributionKey = 1;
3274     }
3275   }
3276 
3277   if(keyCount == 0)
3278   {
3279     tab->m_noOfDistributionKeys = (distKeys ? distKeys : prim->m_noOfKeys);
3280   }
3281   else
3282   {
3283     for(i = 0; i+1<tab->m_columns.size(); i++)
3284       tab->m_columns[i]->m_distributionKey = 0;
3285   }
3286 
3287   idx->m_table_id = prim->getObjectId();
3288   idx->m_table_version = prim->getObjectVersion();
3289 
3290   * dst = idx;
3291   DBUG_PRINT("exit", ("m_id: %d  m_version: %d", idx->m_id, idx->m_version));
3292   DBUG_RETURN(0);
3293 }
3294 
3295 /*****************************************************************
3296  * Create index
3297  */
3298 int
createIndex(NdbIndexImpl & ix)3299 NdbDictionaryImpl::createIndex(NdbIndexImpl &ix)
3300 {
3301   ASSERT_NOT_MYSQLD;
3302   NdbTableImpl* tab = getTable(ix.getTable());
3303   if(tab == 0){
3304     m_error.code = 4249;
3305     return -1;
3306   }
3307 
3308   return m_receiver.createIndex(m_ndb, ix, * tab);
3309 }
3310 
3311 int
createIndex(NdbIndexImpl & ix,NdbTableImpl & tab)3312 NdbDictionaryImpl::createIndex(NdbIndexImpl &ix, NdbTableImpl &tab)
3313 {
3314   return m_receiver.createIndex(m_ndb, ix, tab);
3315 }
3316 
3317 int
createIndex(Ndb & ndb,const NdbIndexImpl & impl,const NdbTableImpl & table)3318 NdbDictInterface::createIndex(Ndb & ndb,
3319 			      const NdbIndexImpl & impl,
3320 			      const NdbTableImpl & table)
3321 {
3322   //validate();
3323   //aggregate();
3324   unsigned i, err;
3325   UtilBufferWriter w(m_buffer);
3326   const size_t len = strlen(impl.m_externalName.c_str()) + 1;
3327   if(len > MAX_TAB_NAME_SIZE) {
3328     m_error.code = 4241;
3329     return -1;
3330   }
3331   const BaseString internalName(
3332     ndb.internalize_index_name(&table, impl.getName()));
3333   w.add(DictTabInfo::TableName, internalName.c_str());
3334   w.add(DictTabInfo::TableLoggedFlag, impl.m_logging);
3335   w.add(DictTabInfo::TableTemporaryFlag, impl.m_temporary);
3336 
3337   NdbApiSignal tSignal(m_reference);
3338   tSignal.theReceiversBlockNumber = DBDICT;
3339   tSignal.theVerId_signalNumber   = GSN_CREATE_INDX_REQ;
3340   tSignal.theLength = CreateIndxReq::SignalLength;
3341 
3342   CreateIndxReq * const req = CAST_PTR(CreateIndxReq, tSignal.getDataPtrSend());
3343 
3344   req->setUserRef(m_reference);
3345   req->setConnectionPtr(0);
3346   req->setRequestType(CreateIndxReq::RT_USER);
3347 
3348   Uint32 it = getKernelConstant(impl.m_type,
3349 				indexTypeMapping,
3350 				DictTabInfo::UndefTableType);
3351 
3352   if(it == DictTabInfo::UndefTableType){
3353     m_error.code = 4250;
3354     return -1;
3355   }
3356   req->setIndexType((DictTabInfo::TableType) it);
3357 
3358   req->setTableId(table.m_id);
3359   req->setOnline(true);
3360   AttributeList attributeList;
3361   attributeList.sz = impl.m_columns.size();
3362   for(i = 0; i<attributeList.sz; i++){
3363     const NdbColumnImpl* col =
3364       table.getColumn(impl.m_columns[i]->m_name.c_str());
3365     if(col == 0){
3366       m_error.code = 4247;
3367       return -1;
3368     }
3369     // Copy column definition  XXX must be wrong, overwrites
3370     *impl.m_columns[i] = *col;
3371 
3372     // index key type check
3373     if (it == DictTabInfo::UniqueHashIndex &&
3374         (err = NdbSqlUtil::check_column_for_hash_index(col->m_type, col->m_cs))
3375         ||
3376         it == DictTabInfo::OrderedIndex &&
3377         (err = NdbSqlUtil::check_column_for_ordered_index(col->m_type, col->m_cs)))
3378     {
3379       m_error.code = err;
3380       return -1;
3381     }
3382     // API uses external column number to talk to DICT
3383     attributeList.id[i] = col->m_column_no;
3384   }
3385   LinearSectionPtr ptr[2];
3386   ptr[0].p = (Uint32*)&attributeList;
3387   ptr[0].sz = 1 + attributeList.sz;
3388   ptr[1].p = (Uint32*)m_buffer.get_data();
3389   ptr[1].sz = m_buffer.length() >> 2;                //BUG?
3390 
3391   int errCodes[] = { CreateIndxRef::Busy, CreateIndxRef::NotMaster, 0 };
3392   return dictSignal(&tSignal, ptr, 2,
3393 		    0, // master
3394 		    WAIT_CREATE_INDX_REQ,
3395 		    DICT_WAITFOR_TIMEOUT, 100,
3396 		    errCodes);
3397 }
3398 
3399 void
execCREATE_INDX_CONF(NdbApiSignal * signal,LinearSectionPtr ptr[3])3400 NdbDictInterface::execCREATE_INDX_CONF(NdbApiSignal * signal,
3401 				       LinearSectionPtr ptr[3])
3402 {
3403   m_waiter.signal(NO_WAIT);
3404 }
3405 
3406 void
execCREATE_INDX_REF(NdbApiSignal * sig,LinearSectionPtr ptr[3])3407 NdbDictInterface::execCREATE_INDX_REF(NdbApiSignal * sig,
3408 				      LinearSectionPtr ptr[3])
3409 {
3410   const CreateIndxRef* ref = CAST_CONSTPTR(CreateIndxRef, sig->getDataPtr());
3411   m_error.code = ref->getErrorCode();
3412   if(m_error.code == ref->NotMaster)
3413     m_masterNodeId= ref->masterNodeId;
3414   m_waiter.signal(NO_WAIT);
3415 }
3416 
3417 /*****************************************************************
3418  * Drop index
3419  */
3420 int
dropIndex(const char * indexName,const char * tableName)3421 NdbDictionaryImpl::dropIndex(const char * indexName,
3422 			     const char * tableName)
3423 {
3424   ASSERT_NOT_MYSQLD;
3425   NdbIndexImpl * idx = getIndex(indexName, tableName);
3426   if (idx == 0) {
3427     m_error.code = 4243;
3428     return -1;
3429   }
3430   int ret = dropIndex(*idx, tableName);
3431   // If index stored in cache is incompatible with the one in the kernel
3432   // we must clear the cache and try again
3433   if (ret == INCOMPATIBLE_VERSION) {
3434     const BaseString internalIndexName((tableName)
3435       ?
3436       m_ndb.internalize_index_name(getTable(tableName), indexName)
3437       :
3438       m_ndb.internalize_table_name(indexName)); // Index is also a table
3439 
3440     m_localHash.drop(internalIndexName.c_str());
3441     m_globalHash->lock();
3442     m_globalHash->release(idx->m_table, 1);
3443     m_globalHash->unlock();
3444     return dropIndex(indexName, tableName);
3445   }
3446 
3447   return ret;
3448 }
3449 
3450 int
dropIndex(NdbIndexImpl & impl,const char * tableName)3451 NdbDictionaryImpl::dropIndex(NdbIndexImpl & impl, const char * tableName)
3452 {
3453   const char * indexName = impl.getName();
3454   if (tableName || m_ndb.usingFullyQualifiedNames()) {
3455     NdbTableImpl * timpl = impl.m_table;
3456 
3457     if (timpl == 0) {
3458       m_error.code = 709;
3459       return -1;
3460     }
3461 
3462     const BaseString internalIndexName((tableName)
3463       ?
3464       m_ndb.internalize_index_name(getTable(tableName), indexName)
3465       :
3466       m_ndb.internalize_table_name(indexName)); // Index is also a table
3467 
3468     if(impl.m_status == NdbDictionary::Object::New){
3469       return dropIndex(indexName, tableName);
3470     }
3471 
3472     int ret= dropIndexGlobal(impl);
3473     if (ret == 0)
3474     {
3475       m_globalHash->lock();
3476       m_globalHash->release(impl.m_table, 1);
3477       m_globalHash->unlock();
3478       m_localHash.drop(internalIndexName.c_str());
3479     }
3480     return ret;
3481   }
3482 
3483   m_error.code = 4243;
3484   return -1;
3485 }
3486 
3487 int
dropIndexGlobal(NdbIndexImpl & impl)3488 NdbDictionaryImpl::dropIndexGlobal(NdbIndexImpl & impl)
3489 {
3490   DBUG_ENTER("NdbDictionaryImpl::dropIndexGlobal");
3491   int ret = m_receiver.dropIndex(impl, *impl.m_table);
3492   impl.m_status = NdbDictionary::Object::Invalid;
3493   if(ret == 0)
3494   {
3495     DBUG_RETURN(0);
3496   }
3497   ERR_RETURN(getNdbError(), ret);
3498 }
3499 
3500 int
dropIndex(const NdbIndexImpl & impl,const NdbTableImpl & timpl)3501 NdbDictInterface::dropIndex(const NdbIndexImpl & impl,
3502 			    const NdbTableImpl & timpl)
3503 {
3504   DBUG_ENTER("NdbDictInterface::dropIndex");
3505   DBUG_PRINT("enter", ("indexId: %d  indexVersion: %d",
3506                        timpl.m_id, timpl.m_version));
3507   NdbApiSignal tSignal(m_reference);
3508   tSignal.theReceiversBlockNumber = DBDICT;
3509   tSignal.theVerId_signalNumber   = GSN_DROP_INDX_REQ;
3510   tSignal.theLength = DropIndxReq::SignalLength;
3511 
3512   DropIndxReq * const req = CAST_PTR(DropIndxReq, tSignal.getDataPtrSend());
3513   req->setUserRef(m_reference);
3514   req->setConnectionPtr(0);
3515   req->setRequestType(DropIndxReq::RT_USER);
3516   req->setTableId(~0);  // DICT overwrites
3517   req->setIndexId(timpl.m_id);
3518   req->setIndexVersion(timpl.m_version);
3519 
3520   int errCodes[] = { DropIndxRef::Busy, DropIndxRef::NotMaster, 0 };
3521   int r = dictSignal(&tSignal, 0, 0,
3522 		     0, // master
3523 		     WAIT_DROP_INDX_REQ,
3524 		     DICT_WAITFOR_TIMEOUT, 100,
3525 		     errCodes);
3526   if(m_error.code == DropIndxRef::InvalidIndexVersion) {
3527     // Clear caches and try again
3528     ERR_RETURN(m_error, INCOMPATIBLE_VERSION);
3529   }
3530   ERR_RETURN(m_error, r);
3531 }
3532 
3533 void
execDROP_INDX_CONF(NdbApiSignal * signal,LinearSectionPtr ptr[3])3534 NdbDictInterface::execDROP_INDX_CONF(NdbApiSignal * signal,
3535 				       LinearSectionPtr ptr[3])
3536 {
3537   m_waiter.signal(NO_WAIT);
3538 }
3539 
3540 void
execDROP_INDX_REF(NdbApiSignal * signal,LinearSectionPtr ptr[3])3541 NdbDictInterface::execDROP_INDX_REF(NdbApiSignal * signal,
3542 				      LinearSectionPtr ptr[3])
3543 {
3544   const DropIndxRef* ref = CAST_CONSTPTR(DropIndxRef, signal->getDataPtr());
3545   m_error.code = ref->getErrorCode();
3546   if(m_error.code == ref->NotMaster)
3547     m_masterNodeId= ref->masterNodeId;
3548   m_waiter.signal(NO_WAIT);
3549 }
3550 
3551 /*****************************************************************
3552  * Create event
3553  */
3554 
3555 int
createEvent(NdbEventImpl & evnt)3556 NdbDictionaryImpl::createEvent(NdbEventImpl & evnt)
3557 {
3558   DBUG_ENTER("NdbDictionaryImpl::createEvent");
3559   int i;
3560   NdbTableImpl* tab= evnt.m_tableImpl;
3561   if (tab == 0)
3562   {
3563     tab= getTable(evnt.getTableName());
3564     if(tab == 0){
3565       DBUG_PRINT("info",("NdbDictionaryImpl::createEvent: table not found: %s",
3566 			 evnt.getTableName()));
3567       ERR_RETURN(getNdbError(), -1);
3568     }
3569     evnt.setTable(tab);
3570   }
3571 
3572   DBUG_PRINT("info",("Table: id: %d version: %d", tab->m_id, tab->m_version));
3573 
3574   NdbTableImpl &table = *evnt.m_tableImpl;
3575 
3576   int attributeList_sz = evnt.m_attrIds.size();
3577 
3578   for (i = 0; i < attributeList_sz; i++) {
3579     NdbColumnImpl *col_impl = table.getColumn(evnt.m_attrIds[i]);
3580     if (col_impl) {
3581       evnt.m_facade->addColumn(*(col_impl->m_facade));
3582     } else {
3583       ndbout_c("Attr id %u in table %s not found", evnt.m_attrIds[i],
3584 	       evnt.getTableName());
3585       m_error.code= 4713;
3586       ERR_RETURN(getNdbError(), -1);
3587     }
3588   }
3589 
3590   evnt.m_attrIds.clear();
3591 
3592   attributeList_sz = evnt.m_columns.size();
3593 
3594   DBUG_PRINT("info",("Event on tableId=%d, tableVersion=%d, event name %s, no of columns %d",
3595 		     table.m_id, table.m_version,
3596 		     evnt.m_name.c_str(),
3597 		     evnt.m_columns.size()));
3598 
3599   int pk_count = 0;
3600   evnt.m_attrListBitmask.clear();
3601 
3602   for(i = 0; i<attributeList_sz; i++){
3603     const NdbColumnImpl* col =
3604       table.getColumn(evnt.m_columns[i]->m_name.c_str());
3605     if(col == 0){
3606       m_error.code= 4247;
3607       ERR_RETURN(getNdbError(), -1);
3608     }
3609     // Copy column definition
3610     *evnt.m_columns[i] = *col;
3611 
3612     if(col->m_pk){
3613       pk_count++;
3614     }
3615 
3616     evnt.m_attrListBitmask.set(col->m_attrId);
3617   }
3618 
3619   // Sort index attributes according to primary table (using insertion sort)
3620   for(i = 1; i < attributeList_sz; i++) {
3621     NdbColumnImpl* temp = evnt.m_columns[i];
3622     unsigned int j = i;
3623     while((j > 0) && (evnt.m_columns[j - 1]->m_attrId > temp->m_attrId)) {
3624       evnt.m_columns[j] = evnt.m_columns[j - 1];
3625       j--;
3626     }
3627     evnt.m_columns[j] = temp;
3628   }
3629   // Check for illegal duplicate attributes
3630   for(i = 1; i<attributeList_sz; i++) {
3631     if (evnt.m_columns[i-1]->m_attrId == evnt.m_columns[i]->m_attrId) {
3632       m_error.code= 4258;
3633       ERR_RETURN(getNdbError(), -1);
3634     }
3635   }
3636 
3637 #ifdef EVENT_DEBUG
3638   char buf[128] = {0};
3639   evnt.m_attrListBitmask.getText(buf);
3640   ndbout_c("createEvent: mask = %s", buf);
3641 #endif
3642 
3643   // NdbDictInterface m_receiver;
3644   if (m_receiver.createEvent(m_ndb, evnt, 0 /* getFlag unset */) != 0)
3645     ERR_RETURN(getNdbError(), -1);
3646 
3647   // Create blob events
3648   if (evnt.m_mergeEvents && createBlobEvents(evnt) != 0) {
3649     int save_code = m_error.code;
3650     (void)dropEvent(evnt.m_name.c_str());
3651     m_error.code = save_code;
3652     ERR_RETURN(getNdbError(), -1);
3653   }
3654   DBUG_RETURN(0);
3655 }
3656 
3657 int
createBlobEvents(NdbEventImpl & evnt)3658 NdbDictionaryImpl::createBlobEvents(NdbEventImpl& evnt)
3659 {
3660   DBUG_ENTER("NdbDictionaryImpl::createBlobEvents");
3661   NdbTableImpl& t = *evnt.m_tableImpl;
3662   Uint32 n = t.m_noOfBlobs;
3663   Uint32 i;
3664   for (i = 0; i < evnt.m_columns.size() && n > 0; i++) {
3665     NdbColumnImpl & c = *evnt.m_columns[i];
3666     if (! c.getBlobType() || c.getPartSize() == 0)
3667       continue;
3668     n--;
3669     NdbEventImpl blob_evnt;
3670     NdbBlob::getBlobEvent(blob_evnt, &evnt, &c);
3671     if (createEvent(blob_evnt) != 0)
3672       ERR_RETURN(getNdbError(), -1);
3673   }
3674   DBUG_RETURN(0);
3675 }
3676 
3677 int
createEvent(class Ndb & ndb,NdbEventImpl & evnt,int getFlag)3678 NdbDictInterface::createEvent(class Ndb & ndb,
3679 			      NdbEventImpl & evnt,
3680 			      int getFlag)
3681 {
3682   DBUG_ENTER("NdbDictInterface::createEvent");
3683   DBUG_PRINT("enter",("getFlag=%d",getFlag));
3684 
3685   NdbApiSignal tSignal(m_reference);
3686   tSignal.theReceiversBlockNumber = DBDICT;
3687   tSignal.theVerId_signalNumber   = GSN_CREATE_EVNT_REQ;
3688   if (getFlag)
3689     tSignal.theLength = CreateEvntReq::SignalLengthGet;
3690   else
3691     tSignal.theLength = CreateEvntReq::SignalLengthCreate;
3692 
3693   CreateEvntReq * const req = CAST_PTR(CreateEvntReq, tSignal.getDataPtrSend());
3694 
3695   req->setUserRef(m_reference);
3696   req->setUserData(0);
3697 
3698   if (getFlag) {
3699     // getting event from Dictionary
3700     req->setRequestType(CreateEvntReq::RT_USER_GET);
3701   } else {
3702     DBUG_PRINT("info",("tableId: %u tableVersion: %u",
3703 		       evnt.m_tableImpl->m_id,
3704                        evnt.m_tableImpl->m_version));
3705     // creating event in Dictionary
3706     req->setRequestType(CreateEvntReq::RT_USER_CREATE);
3707     req->setTableId(evnt.m_tableImpl->m_id);
3708     req->setTableVersion(evnt.m_tableImpl->m_version);
3709     req->setAttrListBitmask(evnt.m_attrListBitmask);
3710     req->setEventType(evnt.mi_type);
3711     req->clearFlags();
3712     if (evnt.m_rep & NdbDictionary::Event::ER_ALL)
3713       req->setReportAll();
3714     if (evnt.m_rep & NdbDictionary::Event::ER_SUBSCRIBE)
3715       req->setReportSubscribe();
3716   }
3717 
3718   UtilBufferWriter w(m_buffer);
3719 
3720   const size_t len = strlen(evnt.m_name.c_str()) + 1;
3721   if(len > MAX_TAB_NAME_SIZE) {
3722     m_error.code= 4241;
3723     ERR_RETURN(getNdbError(), -1);
3724   }
3725 
3726   w.add(SimpleProperties::StringValue, evnt.m_name.c_str());
3727 
3728   if (getFlag == 0)
3729   {
3730     const BaseString internal_tabname(
3731       ndb.internalize_table_name(evnt.m_tableName.c_str()));
3732     w.add(SimpleProperties::StringValue,
3733 	 internal_tabname.c_str());
3734   }
3735 
3736   LinearSectionPtr ptr[1];
3737   ptr[0].p = (Uint32*)m_buffer.get_data();
3738   ptr[0].sz = (m_buffer.length()+3) >> 2;
3739 
3740   int ret = dictSignal(&tSignal,ptr, 1,
3741 		       0, // master
3742 		       WAIT_CREATE_INDX_REQ,
3743 		       DICT_WAITFOR_TIMEOUT, 100,
3744 		       0, -1);
3745 
3746   if (ret) {
3747     ERR_RETURN(getNdbError(), ret);
3748   }
3749 
3750   char *dataPtr = (char *)m_buffer.get_data();
3751   unsigned int lenCreateEvntConf = *((unsigned int *)dataPtr);
3752   dataPtr += sizeof(lenCreateEvntConf);
3753   CreateEvntConf const * evntConf = (CreateEvntConf *)dataPtr;
3754   dataPtr += lenCreateEvntConf;
3755 
3756   //  NdbEventImpl *evntImpl = (NdbEventImpl *)evntConf->getUserData();
3757 
3758   evnt.m_eventId = evntConf->getEventId();
3759   evnt.m_eventKey = evntConf->getEventKey();
3760   evnt.m_table_id = evntConf->getTableId();
3761   evnt.m_table_version = evntConf->getTableVersion();
3762 
3763   if (getFlag) {
3764     evnt.m_attrListBitmask = evntConf->getAttrListBitmask();
3765     evnt.mi_type           = evntConf->getEventType();
3766     evnt.setTable(dataPtr);
3767   } else {
3768     if ((Uint32) evnt.m_tableImpl->m_id         != evntConf->getTableId() ||
3769 	evnt.m_tableImpl->m_version    != evntConf->getTableVersion() ||
3770 	//evnt.m_attrListBitmask != evntConf->getAttrListBitmask() ||
3771 	evnt.mi_type           != evntConf->getEventType()) {
3772       ndbout_c("ERROR*************");
3773       ERR_RETURN(getNdbError(), 1);
3774     }
3775   }
3776 
3777   DBUG_RETURN(0);
3778 }
3779 
3780 int
executeSubscribeEvent(NdbEventOperationImpl & ev_op)3781 NdbDictionaryImpl::executeSubscribeEvent(NdbEventOperationImpl & ev_op)
3782 {
3783   // NdbDictInterface m_receiver;
3784   return m_receiver.executeSubscribeEvent(m_ndb, ev_op);
3785 }
3786 
3787 int
executeSubscribeEvent(class Ndb & ndb,NdbEventOperationImpl & ev_op)3788 NdbDictInterface::executeSubscribeEvent(class Ndb & ndb,
3789 					NdbEventOperationImpl & ev_op)
3790 {
3791   DBUG_ENTER("NdbDictInterface::executeSubscribeEvent");
3792   NdbApiSignal tSignal(m_reference);
3793   tSignal.theReceiversBlockNumber = DBDICT;
3794   tSignal.theVerId_signalNumber   = GSN_SUB_START_REQ;
3795   tSignal.theLength = SubStartReq::SignalLength2;
3796 
3797   SubStartReq * req = CAST_PTR(SubStartReq, tSignal.getDataPtrSend());
3798 
3799   req->subscriptionId   = ev_op.m_eventImpl->m_eventId;
3800   req->subscriptionKey  = ev_op.m_eventImpl->m_eventKey;
3801   req->part             = SubscriptionData::TableData;
3802   req->subscriberData   = ev_op.m_oid;
3803   req->subscriberRef    = m_reference;
3804 
3805   DBUG_PRINT("info",("GSN_SUB_START_REQ subscriptionId=%d,subscriptionKey=%d,"
3806 		     "subscriberData=%d",req->subscriptionId,
3807 		     req->subscriptionKey,req->subscriberData));
3808 
3809   DBUG_RETURN(dictSignal(&tSignal,NULL,0,
3810 			 0 /*use masternode id*/,
3811 			 WAIT_CREATE_INDX_REQ /*WAIT_CREATE_EVNT_REQ*/,
3812 			 -1, 100,
3813 			 0, -1));
3814 }
3815 
3816 int
stopSubscribeEvent(NdbEventOperationImpl & ev_op)3817 NdbDictionaryImpl::stopSubscribeEvent(NdbEventOperationImpl & ev_op)
3818 {
3819   // NdbDictInterface m_receiver;
3820   return m_receiver.stopSubscribeEvent(m_ndb, ev_op);
3821 }
3822 
3823 int
stopSubscribeEvent(class Ndb & ndb,NdbEventOperationImpl & ev_op)3824 NdbDictInterface::stopSubscribeEvent(class Ndb & ndb,
3825 				     NdbEventOperationImpl & ev_op)
3826 {
3827   DBUG_ENTER("NdbDictInterface::stopSubscribeEvent");
3828 
3829   NdbApiSignal tSignal(m_reference);
3830   //  tSignal.theReceiversBlockNumber = SUMA;
3831   tSignal.theReceiversBlockNumber = DBDICT;
3832   tSignal.theVerId_signalNumber   = GSN_SUB_STOP_REQ;
3833   tSignal.theLength = SubStopReq::SignalLength;
3834 
3835   SubStopReq * req = CAST_PTR(SubStopReq, tSignal.getDataPtrSend());
3836 
3837   req->subscriptionId  = ev_op.m_eventImpl->m_eventId;
3838   req->subscriptionKey = ev_op.m_eventImpl->m_eventKey;
3839   req->subscriberData  = ev_op.m_oid;
3840   req->part            = (Uint32) SubscriptionData::TableData;
3841   req->subscriberRef   = m_reference;
3842 
3843   DBUG_PRINT("info",("GSN_SUB_STOP_REQ subscriptionId=%d,subscriptionKey=%d,"
3844 		     "subscriberData=%d",req->subscriptionId,
3845 		     req->subscriptionKey,req->subscriberData));
3846 
3847   DBUG_RETURN(dictSignal(&tSignal,NULL,0,
3848 			 0 /*use masternode id*/,
3849 			 WAIT_CREATE_INDX_REQ /*WAIT_SUB_STOP__REQ*/,
3850 			 -1, 100,
3851 			 0, -1));
3852 }
3853 
3854 NdbEventImpl *
getEvent(const char * eventName,NdbTableImpl * tab)3855 NdbDictionaryImpl::getEvent(const char * eventName, NdbTableImpl* tab)
3856 {
3857   DBUG_ENTER("NdbDictionaryImpl::getEvent");
3858   DBUG_PRINT("enter",("eventName= %s", eventName));
3859 
3860   NdbEventImpl *ev =  new NdbEventImpl();
3861   if (ev == NULL) {
3862     DBUG_RETURN(NULL);
3863   }
3864 
3865   ev->setName(eventName);
3866 
3867   int ret = m_receiver.createEvent(m_ndb, *ev, 1 /* getFlag set */);
3868 
3869   if (ret) {
3870     delete ev;
3871     DBUG_RETURN(NULL);
3872   }
3873 
3874   // We only have the table name with internal name
3875   DBUG_PRINT("info",("table %s", ev->getTableName()));
3876   if (tab == NULL)
3877   {
3878     tab= fetchGlobalTableImplRef(InitTable(this, ev->getTableName()));
3879     if (tab == 0)
3880     {
3881       DBUG_PRINT("error",("unable to find table %s", ev->getTableName()));
3882       delete ev;
3883       DBUG_RETURN(NULL);
3884     }
3885     if ((tab->m_status != NdbDictionary::Object::Retrieved) ||
3886         ((Uint32) tab->m_id != ev->m_table_id) ||
3887         (table_version_major(tab->m_version) !=
3888          table_version_major(ev->m_table_version)))
3889     {
3890       DBUG_PRINT("info", ("mismatch on verison in cache"));
3891       releaseTableGlobal(*tab, 1);
3892       tab= fetchGlobalTableImplRef(InitTable(this, ev->getTableName()));
3893       if (tab == 0)
3894       {
3895         DBUG_PRINT("error",("unable to find table %s", ev->getTableName()));
3896         delete ev;
3897         DBUG_RETURN(NULL);
3898       }
3899     }
3900     ev->setTable(tab);
3901     releaseTableGlobal(*tab, 0);
3902   }
3903   else
3904     ev->setTable(tab);
3905   tab = 0;
3906 
3907   ev->setTable(m_ndb.externalizeTableName(ev->getTableName()));
3908   // get the columns from the attrListBitmask
3909   NdbTableImpl &table = *ev->m_tableImpl;
3910   AttributeMask & mask = ev->m_attrListBitmask;
3911   unsigned attributeList_sz = mask.count();
3912 
3913   DBUG_PRINT("info",("Table: id: %d version: %d",
3914                      table.m_id, table.m_version));
3915 
3916   if ((Uint32) table.m_id != ev->m_table_id ||
3917       table_version_major(table.m_version) !=
3918       table_version_major(ev->m_table_version))
3919   {
3920     m_error.code = 241;
3921     delete ev;
3922     DBUG_RETURN(NULL);
3923   }
3924 #ifndef DBUG_OFF
3925   char buf[128] = {0};
3926   mask.getText(buf);
3927   DBUG_PRINT("info",("attributeList_sz= %d, mask= %s",
3928                      attributeList_sz, buf));
3929 #endif
3930 
3931 
3932   if ( attributeList_sz > (uint) table.getNoOfColumns() )
3933   {
3934     m_error.code = 241;
3935     DBUG_PRINT("error",("Invalid version, too many columns"));
3936     delete ev;
3937     DBUG_RETURN(NULL);
3938   }
3939 
3940   assert( (int)attributeList_sz <= table.getNoOfColumns() );
3941   for(unsigned id= 0; ev->m_columns.size() < attributeList_sz; id++) {
3942     if ( id >= (uint) table.getNoOfColumns())
3943     {
3944       m_error.code = 241;
3945       DBUG_PRINT("error",("Invalid version, column %d out of range", id));
3946       delete ev;
3947       DBUG_RETURN(NULL);
3948     }
3949     if (!mask.get(id))
3950       continue;
3951 
3952     const NdbColumnImpl* col = table.getColumn(id);
3953     DBUG_PRINT("info",("column %d %s", id, col->getName()));
3954     NdbColumnImpl* new_col = new NdbColumnImpl;
3955     // Copy column definition
3956     *new_col = *col;
3957     ev->m_columns.push_back(new_col);
3958   }
3959   DBUG_RETURN(ev);
3960 }
3961 
3962 // ev is main event and has been retrieved previously
3963 NdbEventImpl *
getBlobEvent(const NdbEventImpl & ev,uint col_no)3964 NdbDictionaryImpl::getBlobEvent(const NdbEventImpl& ev, uint col_no)
3965 {
3966   DBUG_ENTER("NdbDictionaryImpl::getBlobEvent");
3967   DBUG_PRINT("enter", ("ev=%s col=%u", ev.m_name.c_str(), col_no));
3968 
3969   NdbTableImpl* tab = ev.m_tableImpl;
3970   assert(tab != NULL && col_no < tab->m_columns.size());
3971   NdbColumnImpl* col = tab->m_columns[col_no];
3972   assert(col != NULL && col->getBlobType() && col->getPartSize() != 0);
3973   NdbTableImpl* blob_tab = col->m_blobTable;
3974   assert(blob_tab != NULL);
3975   char bename[MAX_TAB_NAME_SIZE];
3976   NdbBlob::getBlobEventName(bename, &ev, col);
3977 
3978   NdbEventImpl* blob_ev = getEvent(bename, blob_tab);
3979   DBUG_RETURN(blob_ev);
3980 }
3981 
3982 void
execCREATE_EVNT_CONF(NdbApiSignal * signal,LinearSectionPtr ptr[3])3983 NdbDictInterface::execCREATE_EVNT_CONF(NdbApiSignal * signal,
3984 				       LinearSectionPtr ptr[3])
3985 {
3986   DBUG_ENTER("NdbDictInterface::execCREATE_EVNT_CONF");
3987 
3988   m_buffer.clear();
3989   unsigned int len = signal->getLength() << 2;
3990   m_buffer.append((char *)&len, sizeof(len));
3991   m_buffer.append(signal->getDataPtr(), len);
3992 
3993   if (signal->m_noOfSections > 0) {
3994     m_buffer.append((char *)ptr[0].p, strlen((char *)ptr[0].p)+1);
3995   }
3996 
3997   const CreateEvntConf * const createEvntConf=
3998     CAST_CONSTPTR(CreateEvntConf, signal->getDataPtr());
3999 
4000   Uint32 subscriptionId = createEvntConf->getEventId();
4001   Uint32 subscriptionKey = createEvntConf->getEventKey();
4002 
4003   DBUG_PRINT("info",("nodeid=%d,subscriptionId=%d,subscriptionKey=%d",
4004 		     refToNode(signal->theSendersBlockRef),
4005 		     subscriptionId,subscriptionKey));
4006   m_waiter.signal(NO_WAIT);
4007   DBUG_VOID_RETURN;
4008 }
4009 
4010 void
execCREATE_EVNT_REF(NdbApiSignal * signal,LinearSectionPtr ptr[3])4011 NdbDictInterface::execCREATE_EVNT_REF(NdbApiSignal * signal,
4012 				      LinearSectionPtr ptr[3])
4013 {
4014   DBUG_ENTER("NdbDictInterface::execCREATE_EVNT_REF");
4015 
4016   const CreateEvntRef* const ref=
4017     CAST_CONSTPTR(CreateEvntRef, signal->getDataPtr());
4018   m_error.code= ref->getErrorCode();
4019   DBUG_PRINT("error",("error=%d,line=%d,node=%d",ref->getErrorCode(),
4020 		      ref->getErrorLine(),ref->getErrorNode()));
4021   if (m_error.code == CreateEvntRef::NotMaster)
4022     m_masterNodeId = ref->getMasterNode();
4023   m_waiter.signal(NO_WAIT);
4024   DBUG_VOID_RETURN;
4025 }
4026 
4027 void
execSUB_STOP_CONF(NdbApiSignal * signal,LinearSectionPtr ptr[3])4028 NdbDictInterface::execSUB_STOP_CONF(NdbApiSignal * signal,
4029 				      LinearSectionPtr ptr[3])
4030 {
4031   DBUG_ENTER("NdbDictInterface::execSUB_STOP_CONF");
4032   const SubStopConf * const subStopConf=
4033     CAST_CONSTPTR(SubStopConf, signal->getDataPtr());
4034 
4035   Uint32 subscriptionId = subStopConf->subscriptionId;
4036   Uint32 subscriptionKey = subStopConf->subscriptionKey;
4037   Uint32 subscriberData = subStopConf->subscriberData;
4038 
4039   DBUG_PRINT("info",("subscriptionId=%d,subscriptionKey=%d,subscriberData=%d",
4040 		     subscriptionId,subscriptionKey,subscriberData));
4041   m_waiter.signal(NO_WAIT);
4042   DBUG_VOID_RETURN;
4043 }
4044 
4045 void
execSUB_STOP_REF(NdbApiSignal * signal,LinearSectionPtr ptr[3])4046 NdbDictInterface::execSUB_STOP_REF(NdbApiSignal * signal,
4047 				     LinearSectionPtr ptr[3])
4048 {
4049   DBUG_ENTER("NdbDictInterface::execSUB_STOP_REF");
4050   const SubStopRef * const subStopRef=
4051     CAST_CONSTPTR(SubStopRef, signal->getDataPtr());
4052 
4053   Uint32 subscriptionId = subStopRef->subscriptionId;
4054   Uint32 subscriptionKey = subStopRef->subscriptionKey;
4055   Uint32 subscriberData = subStopRef->subscriberData;
4056   m_error.code= subStopRef->errorCode;
4057 
4058   DBUG_PRINT("error",("subscriptionId=%d,subscriptionKey=%d,subscriberData=%d,error=%d",
4059 		      subscriptionId,subscriptionKey,subscriberData,m_error.code));
4060   if (m_error.code == SubStopRef::NotMaster)
4061     m_masterNodeId = subStopRef->m_masterNodeId;
4062   m_waiter.signal(NO_WAIT);
4063   DBUG_VOID_RETURN;
4064 }
4065 
4066 void
execSUB_START_CONF(NdbApiSignal * signal,LinearSectionPtr ptr[3])4067 NdbDictInterface::execSUB_START_CONF(NdbApiSignal * signal,
4068 				     LinearSectionPtr ptr[3])
4069 {
4070   DBUG_ENTER("NdbDictInterface::execSUB_START_CONF");
4071   const SubStartConf * const subStartConf=
4072     CAST_CONSTPTR(SubStartConf, signal->getDataPtr());
4073 
4074   Uint32 subscriptionId = subStartConf->subscriptionId;
4075   Uint32 subscriptionKey = subStartConf->subscriptionKey;
4076   SubscriptionData::Part part =
4077     (SubscriptionData::Part)subStartConf->part;
4078   Uint32 subscriberData = subStartConf->subscriberData;
4079 
4080   switch(part) {
4081   case SubscriptionData::MetaData: {
4082     DBUG_PRINT("error",("SubscriptionData::MetaData"));
4083     m_error.code= 1;
4084     break;
4085   }
4086   case SubscriptionData::TableData: {
4087     DBUG_PRINT("info",("SubscriptionData::TableData"));
4088     break;
4089   }
4090   default: {
4091     DBUG_PRINT("error",("wrong data"));
4092     m_error.code= 2;
4093     break;
4094   }
4095   }
4096   DBUG_PRINT("info",("subscriptionId=%d,subscriptionKey=%d,subscriberData=%d",
4097 		     subscriptionId,subscriptionKey,subscriberData));
4098   m_waiter.signal(NO_WAIT);
4099   DBUG_VOID_RETURN;
4100 }
4101 
4102 void
execSUB_START_REF(NdbApiSignal * signal,LinearSectionPtr ptr[3])4103 NdbDictInterface::execSUB_START_REF(NdbApiSignal * signal,
4104 				    LinearSectionPtr ptr[3])
4105 {
4106   DBUG_ENTER("NdbDictInterface::execSUB_START_REF");
4107   const SubStartRef * const subStartRef=
4108     CAST_CONSTPTR(SubStartRef, signal->getDataPtr());
4109   m_error.code= subStartRef->errorCode;
4110   if (m_error.code == SubStartRef::NotMaster)
4111     m_masterNodeId = subStartRef->m_masterNodeId;
4112   m_waiter.signal(NO_WAIT);
4113   DBUG_VOID_RETURN;
4114 }
4115 
4116 /*****************************************************************
4117  * Drop event
4118  */
4119 int
dropEvent(const char * eventName)4120 NdbDictionaryImpl::dropEvent(const char * eventName)
4121 {
4122   DBUG_ENTER("NdbDictionaryImpl::dropEvent");
4123   DBUG_PRINT("info", ("name=%s", eventName));
4124 
4125   NdbEventImpl *evnt = getEvent(eventName); // allocated
4126   if (evnt == NULL) {
4127     if (m_error.code != 723 && // no such table
4128         m_error.code != 241)   // invalid table
4129       DBUG_RETURN(-1);
4130     DBUG_PRINT("info", ("no table err=%d, drop by name alone", m_error.code));
4131     evnt = new NdbEventImpl();
4132     evnt->setName(eventName);
4133   }
4134   int ret = dropEvent(*evnt);
4135   delete evnt;
4136   DBUG_RETURN(ret);
4137 }
4138 
4139 int
dropEvent(const NdbEventImpl & evnt)4140 NdbDictionaryImpl::dropEvent(const NdbEventImpl& evnt)
4141 {
4142   if (dropBlobEvents(evnt) != 0)
4143     return -1;
4144   if (m_receiver.dropEvent(evnt) != 0)
4145     return -1;
4146   return 0;
4147 }
4148 
4149 int
dropBlobEvents(const NdbEventImpl & evnt)4150 NdbDictionaryImpl::dropBlobEvents(const NdbEventImpl& evnt)
4151 {
4152   DBUG_ENTER("NdbDictionaryImpl::dropBlobEvents");
4153   if (evnt.m_tableImpl != 0) {
4154     const NdbTableImpl& t = *evnt.m_tableImpl;
4155     Uint32 n = t.m_noOfBlobs;
4156     Uint32 i;
4157     for (i = 0; i < evnt.m_columns.size() && n > 0; i++) {
4158       const NdbColumnImpl& c = *evnt.m_columns[i];
4159       if (! c.getBlobType() || c.getPartSize() == 0)
4160         continue;
4161       n--;
4162       NdbEventImpl* blob_evnt = getBlobEvent(evnt, i);
4163       if (blob_evnt == NULL)
4164         continue;
4165       (void)dropEvent(*blob_evnt);
4166       delete blob_evnt;
4167     }
4168   } else {
4169     // loop over MAX_ATTRIBUTES_IN_TABLE ...
4170     Uint32 i;
4171     DBUG_PRINT("info", ("missing table definition, looping over "
4172                         "MAX_ATTRIBUTES_IN_TABLE(%d)",
4173                         MAX_ATTRIBUTES_IN_TABLE));
4174     for (i = 0; i < MAX_ATTRIBUTES_IN_TABLE; i++) {
4175       char bename[MAX_TAB_NAME_SIZE];
4176       // XXX should get name from NdbBlob
4177       sprintf(bename, "NDB$BLOBEVENT_%s_%u", evnt.getName(), i);
4178       NdbEventImpl* bevnt = new NdbEventImpl();
4179       bevnt->setName(bename);
4180       (void)m_receiver.dropEvent(*bevnt);
4181       delete bevnt;
4182     }
4183   }
4184   DBUG_RETURN(0);
4185 }
4186 
4187 int
dropEvent(const NdbEventImpl & evnt)4188 NdbDictInterface::dropEvent(const NdbEventImpl &evnt)
4189 {
4190   NdbApiSignal tSignal(m_reference);
4191   tSignal.theReceiversBlockNumber = DBDICT;
4192   tSignal.theVerId_signalNumber   = GSN_DROP_EVNT_REQ;
4193   tSignal.theLength = DropEvntReq::SignalLength;
4194 
4195   DropEvntReq * const req = CAST_PTR(DropEvntReq, tSignal.getDataPtrSend());
4196 
4197   req->setUserRef(m_reference);
4198   req->setUserData(0);
4199 
4200   UtilBufferWriter w(m_buffer);
4201 
4202   w.add(SimpleProperties::StringValue, evnt.m_name.c_str());
4203 
4204   LinearSectionPtr ptr[1];
4205   ptr[0].p = (Uint32*)m_buffer.get_data();
4206   ptr[0].sz = (m_buffer.length()+3) >> 2;
4207 
4208   return dictSignal(&tSignal,ptr, 1,
4209 		    0 /*use masternode id*/,
4210 		    WAIT_CREATE_INDX_REQ,
4211 		    -1, 100,
4212 		    0, -1);
4213 }
4214 
4215 void
execDROP_EVNT_CONF(NdbApiSignal * signal,LinearSectionPtr ptr[3])4216 NdbDictInterface::execDROP_EVNT_CONF(NdbApiSignal * signal,
4217 				     LinearSectionPtr ptr[3])
4218 {
4219   DBUG_ENTER("NdbDictInterface::execDROP_EVNT_CONF");
4220   m_waiter.signal(NO_WAIT);
4221   DBUG_VOID_RETURN;
4222 }
4223 
4224 void
execDROP_EVNT_REF(NdbApiSignal * signal,LinearSectionPtr ptr[3])4225 NdbDictInterface::execDROP_EVNT_REF(NdbApiSignal * signal,
4226 				    LinearSectionPtr ptr[3])
4227 {
4228   DBUG_ENTER("NdbDictInterface::execDROP_EVNT_REF");
4229   const DropEvntRef* const ref=
4230     CAST_CONSTPTR(DropEvntRef, signal->getDataPtr());
4231   m_error.code= ref->getErrorCode();
4232 
4233   DBUG_PRINT("info",("ErrorCode=%u Errorline=%u ErrorNode=%u",
4234 	     ref->getErrorCode(), ref->getErrorLine(), ref->getErrorNode()));
4235   if (m_error.code == DropEvntRef::NotMaster)
4236     m_masterNodeId = ref->getMasterNode();
4237   m_waiter.signal(NO_WAIT);
4238   DBUG_VOID_RETURN;
4239 }
4240 
4241 /*****************************************************************
4242  * List objects or indexes
4243  */
4244 int
listObjects(List & list,NdbDictionary::Object::Type type)4245 NdbDictionaryImpl::listObjects(List& list, NdbDictionary::Object::Type type)
4246 {
4247   ListTablesReq req;
4248   req.requestData = 0;
4249   req.setTableType(getKernelConstant(type, objectTypeMapping, 0));
4250   req.setListNames(true);
4251   return m_receiver.listObjects(list, req.requestData, m_ndb.usingFullyQualifiedNames());
4252 }
4253 
4254 int
listIndexes(List & list,Uint32 indexId)4255 NdbDictionaryImpl::listIndexes(List& list, Uint32 indexId)
4256 {
4257   ListTablesReq req;
4258   req.requestData = 0;
4259   req.setTableId(indexId);
4260   req.setListNames(true);
4261   req.setListIndexes(true);
4262   return m_receiver.listObjects(list, req.requestData, m_ndb.usingFullyQualifiedNames());
4263 }
4264 
4265 int
listObjects(NdbDictionary::Dictionary::List & list,Uint32 requestData,bool fullyQualifiedNames)4266 NdbDictInterface::listObjects(NdbDictionary::Dictionary::List& list,
4267 			      Uint32 requestData, bool fullyQualifiedNames)
4268 {
4269   NdbApiSignal tSignal(m_reference);
4270   ListTablesReq* const req = CAST_PTR(ListTablesReq, tSignal.getDataPtrSend());
4271   req->senderRef = m_reference;
4272   req->senderData = 0;
4273   req->requestData = requestData;
4274   tSignal.theReceiversBlockNumber = DBDICT;
4275   tSignal.theVerId_signalNumber = GSN_LIST_TABLES_REQ;
4276   tSignal.theLength = ListTablesReq::SignalLength;
4277   if (listObjects(&tSignal) != 0)
4278     return -1;
4279   // count
4280   const Uint32* data = (const Uint32*)m_buffer.get_data();
4281   const unsigned length = m_buffer.length() / 4;
4282   list.count = 0;
4283   bool ok = true;
4284   unsigned pos, count;
4285   pos = count = 0;
4286   while (pos < length) {
4287     // table id - name length - name
4288     pos++;
4289     if (pos >= length) {
4290       ok = false;
4291       break;
4292     }
4293     Uint32 n = (data[pos++] + 3) >> 2;
4294     pos += n;
4295     if (pos > length) {
4296       ok = false;
4297       break;
4298     }
4299     count++;
4300   }
4301   if (! ok) {
4302     // bad signal data
4303     m_error.code= 4213;
4304     return -1;
4305   }
4306   list.count = count;
4307   list.elements = new NdbDictionary::Dictionary::List::Element[count];
4308   pos = count = 0;
4309   while (pos < length) {
4310     NdbDictionary::Dictionary::List::Element& element = list.elements[count];
4311     Uint32 d = data[pos++];
4312     element.id = ListTablesConf::getTableId(d);
4313     element.type = (NdbDictionary::Object::Type)
4314       getApiConstant(ListTablesConf::getTableType(d), objectTypeMapping, 0);
4315     element.state = (NdbDictionary::Object::State)
4316       getApiConstant(ListTablesConf::getTableState(d), objectStateMapping, 0);
4317     element.store = (NdbDictionary::Object::Store)
4318       getApiConstant(ListTablesConf::getTableStore(d), objectStoreMapping, 0);
4319     element.temp = ListTablesConf::getTableTemp(d);
4320     // table or index name
4321     Uint32 n = (data[pos++] + 3) >> 2;
4322     BaseString databaseName;
4323     BaseString schemaName;
4324     BaseString objectName;
4325     if (!databaseName || !schemaName || !objectName)
4326     {
4327       m_error.code= 4000;
4328       return -1;
4329     }
4330     if ((element.type == NdbDictionary::Object::UniqueHashIndex) ||
4331 	(element.type == NdbDictionary::Object::OrderedIndex)) {
4332       char * indexName = new char[n << 2];
4333       if (indexName == NULL)
4334       {
4335         m_error.code= 4000;
4336         return -1;
4337       }
4338       memcpy(indexName, &data[pos], n << 2);
4339       if (!(databaseName = Ndb::getDatabaseFromInternalName(indexName)) ||
4340           !(schemaName = Ndb::getSchemaFromInternalName(indexName)))
4341       {
4342         delete [] indexName;
4343         m_error.code= 4000;
4344         return -1;
4345       }
4346       objectName = BaseString(Ndb::externalizeIndexName(indexName, fullyQualifiedNames));
4347       delete [] indexName;
4348     } else if ((element.type == NdbDictionary::Object::SystemTable) ||
4349 	       (element.type == NdbDictionary::Object::UserTable)) {
4350       char * tableName = new char[n << 2];
4351       if (tableName == NULL)
4352       {
4353         m_error.code= 4000;
4354         return -1;
4355       }
4356       memcpy(tableName, &data[pos], n << 2);
4357       if (!(databaseName = Ndb::getDatabaseFromInternalName(tableName)) ||
4358           !(schemaName = Ndb::getSchemaFromInternalName(tableName)))
4359       {
4360         delete [] tableName;
4361         m_error.code= 4000;
4362         return -1;
4363       }
4364       objectName = BaseString(Ndb::externalizeTableName(tableName, fullyQualifiedNames));
4365       delete [] tableName;
4366     }
4367     else {
4368       char * otherName = new char[n << 2];
4369       if (otherName == NULL)
4370       {
4371         m_error.code= 4000;
4372         return -1;
4373       }
4374       memcpy(otherName, &data[pos], n << 2);
4375       if (!(objectName = BaseString(otherName)))
4376       {
4377         m_error.code= 4000;
4378         return -1;
4379       }
4380       delete [] otherName;
4381     }
4382     if (!(element.database = new char[databaseName.length() + 1]) ||
4383         !(element.schema = new char[schemaName.length() + 1]) ||
4384         !(element.name = new char[objectName.length() + 1]))
4385     {
4386       m_error.code= 4000;
4387       return -1;
4388     }
4389     strcpy(element.database, databaseName.c_str());
4390     strcpy(element.schema, schemaName.c_str());
4391     strcpy(element.name, objectName.c_str());
4392     pos += n;
4393     count++;
4394   }
4395   return 0;
4396 }
4397 
4398 int
listObjects(NdbApiSignal * signal)4399 NdbDictInterface::listObjects(NdbApiSignal* signal)
4400 {
4401   const Uint32 RETRIES = 100;
4402   for (Uint32 i = 0; i < RETRIES; i++) {
4403     m_buffer.clear();
4404     // begin protected
4405     /*
4406       The PollGuard has an implicit call of unlock_and_signal through the
4407       ~PollGuard method. This method is called implicitly by the compiler
4408       in all places where the object is out of context due to a return,
4409       break, continue or simply end of statement block
4410     */
4411     PollGuard poll_guard(m_transporter, &m_waiter, refToBlock(m_reference));
4412     Uint16 aNodeId = m_transporter->get_an_alive_node();
4413     if (aNodeId == 0) {
4414       m_error.code= 4009;
4415       return -1;
4416     }
4417     if (m_transporter->sendSignal(signal, aNodeId) != 0) {
4418       continue;
4419     }
4420     m_error.code= 0;
4421     int ret_val= poll_guard.wait_n_unlock(DICT_WAITFOR_TIMEOUT,
4422                                           aNodeId, WAIT_LIST_TABLES_CONF);
4423     // end protected
4424     if (ret_val == 0 && m_error.code == 0)
4425       return 0;
4426     if (ret_val == -2) //WAIT_NODE_FAILURE
4427       continue;
4428     return -1;
4429   }
4430   return -1;
4431 }
4432 
4433 void
execLIST_TABLES_CONF(NdbApiSignal * signal,LinearSectionPtr ptr[3])4434 NdbDictInterface::execLIST_TABLES_CONF(NdbApiSignal* signal,
4435 				       LinearSectionPtr ptr[3])
4436 {
4437   const unsigned off = ListTablesConf::HeaderLength;
4438   const unsigned len = (signal->getLength() - off);
4439   if (m_buffer.append(signal->getDataPtr() + off, len << 2))
4440   {
4441     m_error.code= 4000;
4442   }
4443   if (signal->getLength() < ListTablesConf::SignalLength) {
4444     // last signal has less than full length
4445     m_waiter.signal(NO_WAIT);
4446   }
4447 }
4448 
4449 int
forceGCPWait()4450 NdbDictionaryImpl::forceGCPWait()
4451 {
4452   return m_receiver.forceGCPWait();
4453 }
4454 
4455 int
forceGCPWait()4456 NdbDictInterface::forceGCPWait()
4457 {
4458   NdbApiSignal tSignal(m_reference);
4459   WaitGCPReq* const req = CAST_PTR(WaitGCPReq, tSignal.getDataPtrSend());
4460   req->senderRef = m_reference;
4461   req->senderData = 0;
4462   req->requestType = WaitGCPReq::CompleteForceStart;
4463   tSignal.theReceiversBlockNumber = DBDIH;
4464   tSignal.theVerId_signalNumber = GSN_WAIT_GCP_REQ;
4465   tSignal.theLength = WaitGCPReq::SignalLength;
4466 
4467   const Uint32 RETRIES = 100;
4468   for (Uint32 i = 0; i < RETRIES; i++)
4469   {
4470     m_transporter->lock_mutex();
4471     Uint16 aNodeId = m_transporter->get_an_alive_node();
4472     if (aNodeId == 0) {
4473       m_error.code= 4009;
4474       m_transporter->unlock_mutex();
4475       return -1;
4476     }
4477     if (m_transporter->sendSignal(&tSignal, aNodeId) != 0) {
4478       m_transporter->unlock_mutex();
4479       continue;
4480     }
4481     m_error.code= 0;
4482     m_waiter.m_node = aNodeId;
4483     m_waiter.m_state = WAIT_LIST_TABLES_CONF;
4484     m_waiter.wait(DICT_WAITFOR_TIMEOUT);
4485     m_transporter->unlock_mutex();
4486     return 0;
4487   }
4488   return -1;
4489 }
4490 
4491 void
execWAIT_GCP_CONF(NdbApiSignal * signal,LinearSectionPtr ptr[3])4492 NdbDictInterface::execWAIT_GCP_CONF(NdbApiSignal* signal,
4493 				    LinearSectionPtr ptr[3])
4494 {
4495   m_waiter.signal(NO_WAIT);
4496 }
4497 
4498 void
execWAIT_GCP_REF(NdbApiSignal * signal,LinearSectionPtr ptr[3])4499 NdbDictInterface::execWAIT_GCP_REF(NdbApiSignal* signal,
4500 				    LinearSectionPtr ptr[3])
4501 {
4502   m_waiter.signal(NO_WAIT);
4503 }
4504 
NdbFilegroupImpl(NdbDictionary::Object::Type t)4505 NdbFilegroupImpl::NdbFilegroupImpl(NdbDictionary::Object::Type t)
4506   : NdbDictObjectImpl(t)
4507 {
4508   m_extent_size = 0;
4509   m_undo_buffer_size = 0;
4510   m_logfile_group_id = ~0;
4511   m_logfile_group_version = ~0;
4512 }
4513 
NdbTablespaceImpl()4514 NdbTablespaceImpl::NdbTablespaceImpl() :
4515   NdbDictionary::Tablespace(* this),
4516   NdbFilegroupImpl(NdbDictionary::Object::Tablespace), m_facade(this)
4517 {
4518 }
4519 
NdbTablespaceImpl(NdbDictionary::Tablespace & f)4520 NdbTablespaceImpl::NdbTablespaceImpl(NdbDictionary::Tablespace & f) :
4521   NdbDictionary::Tablespace(* this),
4522   NdbFilegroupImpl(NdbDictionary::Object::Tablespace), m_facade(&f)
4523 {
4524 }
4525 
~NdbTablespaceImpl()4526 NdbTablespaceImpl::~NdbTablespaceImpl(){
4527 }
4528 
4529 int
assign(const NdbTablespaceImpl & org)4530 NdbTablespaceImpl::assign(const NdbTablespaceImpl& org)
4531 {
4532   m_id = org.m_id;
4533   m_version = org.m_version;
4534   m_status = org.m_status;
4535   m_type = org.m_type;
4536 
4537   if (!m_name.assign(org.m_name))
4538     return -1;
4539   m_grow_spec = org.m_grow_spec;
4540   m_extent_size = org.m_extent_size;
4541   m_undo_free_words = org.m_undo_free_words;
4542   m_logfile_group_id = org.m_logfile_group_id;
4543   m_logfile_group_version = org.m_logfile_group_version;
4544   if (!m_logfile_group_name.assign(org.m_logfile_group_name))
4545     return -1;
4546   m_undo_free_words = org.m_undo_free_words;
4547   return 0;
4548 }
4549 
NdbLogfileGroupImpl()4550 NdbLogfileGroupImpl::NdbLogfileGroupImpl() :
4551   NdbDictionary::LogfileGroup(* this),
4552   NdbFilegroupImpl(NdbDictionary::Object::LogfileGroup), m_facade(this)
4553 {
4554 }
4555 
NdbLogfileGroupImpl(NdbDictionary::LogfileGroup & f)4556 NdbLogfileGroupImpl::NdbLogfileGroupImpl(NdbDictionary::LogfileGroup & f) :
4557   NdbDictionary::LogfileGroup(* this),
4558   NdbFilegroupImpl(NdbDictionary::Object::LogfileGroup), m_facade(&f)
4559 {
4560 }
4561 
~NdbLogfileGroupImpl()4562 NdbLogfileGroupImpl::~NdbLogfileGroupImpl(){
4563 }
4564 
4565 int
assign(const NdbLogfileGroupImpl & org)4566 NdbLogfileGroupImpl::assign(const NdbLogfileGroupImpl& org)
4567 {
4568   m_id = org.m_id;
4569   m_version = org.m_version;
4570   m_status = org.m_status;
4571   m_type = org.m_type;
4572 
4573   if (!m_name.assign(org.m_name))
4574     return -1;
4575   m_grow_spec = org.m_grow_spec;
4576   m_extent_size = org.m_extent_size;
4577   m_undo_free_words = org.m_undo_free_words;
4578   m_logfile_group_id = org.m_logfile_group_id;
4579   m_logfile_group_version = org.m_logfile_group_version;
4580   if (!m_logfile_group_name.assign(org.m_logfile_group_name))
4581     return -1;
4582   m_undo_free_words = org.m_undo_free_words;
4583   return 0;
4584 }
4585 
NdbFileImpl(NdbDictionary::Object::Type t)4586 NdbFileImpl::NdbFileImpl(NdbDictionary::Object::Type t)
4587   : NdbDictObjectImpl(t)
4588 {
4589   m_size = 0;
4590   m_free = 0;
4591   m_filegroup_id = ~0;
4592   m_filegroup_version = ~0;
4593 }
4594 
NdbDatafileImpl()4595 NdbDatafileImpl::NdbDatafileImpl() :
4596   NdbDictionary::Datafile(* this),
4597   NdbFileImpl(NdbDictionary::Object::Datafile), m_facade(this)
4598 {
4599 }
4600 
NdbDatafileImpl(NdbDictionary::Datafile & f)4601 NdbDatafileImpl::NdbDatafileImpl(NdbDictionary::Datafile & f) :
4602   NdbDictionary::Datafile(* this),
4603   NdbFileImpl(NdbDictionary::Object::Datafile), m_facade(&f)
4604 {
4605 }
4606 
~NdbDatafileImpl()4607 NdbDatafileImpl::~NdbDatafileImpl(){
4608 }
4609 
4610 int
assign(const NdbDatafileImpl & org)4611 NdbDatafileImpl::assign(const NdbDatafileImpl& org)
4612 {
4613   m_id = org.m_id;
4614   m_version = org.m_version;
4615   m_status = org.m_status;
4616   m_type = org.m_type;
4617 
4618   m_size = org.m_size;
4619   m_free = org.m_free;
4620   m_filegroup_id = org.m_filegroup_id;
4621   m_filegroup_version = org.m_filegroup_version;
4622   if (!m_path.assign(org.m_path) ||
4623       !m_filegroup_name.assign(org.m_filegroup_name))
4624     return -1;
4625   return 0;
4626 }
4627 
NdbUndofileImpl()4628 NdbUndofileImpl::NdbUndofileImpl() :
4629   NdbDictionary::Undofile(* this),
4630   NdbFileImpl(NdbDictionary::Object::Undofile), m_facade(this)
4631 {
4632 }
4633 
NdbUndofileImpl(NdbDictionary::Undofile & f)4634 NdbUndofileImpl::NdbUndofileImpl(NdbDictionary::Undofile & f) :
4635   NdbDictionary::Undofile(* this),
4636   NdbFileImpl(NdbDictionary::Object::Undofile), m_facade(&f)
4637 {
4638 }
4639 
~NdbUndofileImpl()4640 NdbUndofileImpl::~NdbUndofileImpl(){
4641 }
4642 
4643 int
assign(const NdbUndofileImpl & org)4644 NdbUndofileImpl::assign(const NdbUndofileImpl& org)
4645 {
4646   m_id = org.m_id;
4647   m_version = org.m_version;
4648   m_status = org.m_status;
4649   m_type = org.m_type;
4650 
4651   m_size = org.m_size;
4652   m_free = org.m_free;
4653   m_filegroup_id = org.m_filegroup_id;
4654   m_filegroup_version = org.m_filegroup_version;
4655   if (!m_path.assign(org.m_path) ||
4656       !m_filegroup_name.assign(org.m_filegroup_name))
4657     return 4000;
4658   return 0;
4659 }
4660 
4661 int
createDatafile(const NdbDatafileImpl & file,bool force,NdbDictObjectImpl * obj)4662 NdbDictionaryImpl::createDatafile(const NdbDatafileImpl & file,
4663 				  bool force,
4664 				  NdbDictObjectImpl* obj)
4665 
4666 {
4667   DBUG_ENTER("NdbDictionaryImpl::createDatafile");
4668   NdbFilegroupImpl tmp(NdbDictionary::Object::Tablespace);
4669   if(file.m_filegroup_version != ~(Uint32)0){
4670     tmp.m_id = file.m_filegroup_id;
4671     tmp.m_version = file.m_filegroup_version;
4672     DBUG_RETURN(m_receiver.create_file(file, tmp, force, obj));
4673   }
4674 
4675 
4676   if(m_receiver.get_filegroup(tmp, NdbDictionary::Object::Tablespace,
4677 			      file.m_filegroup_name.c_str()) == 0){
4678     DBUG_RETURN(m_receiver.create_file(file, tmp, force, obj));
4679   }
4680   DBUG_RETURN(-1);
4681 }
4682 
4683 int
dropDatafile(const NdbDatafileImpl & file)4684 NdbDictionaryImpl::dropDatafile(const NdbDatafileImpl & file){
4685   return m_receiver.drop_file(file);
4686 }
4687 
4688 int
createUndofile(const NdbUndofileImpl & file,bool force,NdbDictObjectImpl * obj)4689 NdbDictionaryImpl::createUndofile(const NdbUndofileImpl & file,
4690 				  bool force,
4691 				  NdbDictObjectImpl* obj)
4692 {
4693   DBUG_ENTER("NdbDictionaryImpl::createUndofile");
4694   NdbFilegroupImpl tmp(NdbDictionary::Object::LogfileGroup);
4695   if(file.m_filegroup_version != ~(Uint32)0){
4696     tmp.m_id = file.m_filegroup_id;
4697     tmp.m_version = file.m_filegroup_version;
4698     DBUG_RETURN(m_receiver.create_file(file, tmp, force, obj));
4699   }
4700 
4701 
4702   if(m_receiver.get_filegroup(tmp, NdbDictionary::Object::LogfileGroup,
4703 			      file.m_filegroup_name.c_str()) == 0){
4704     DBUG_RETURN(m_receiver.create_file(file, tmp, force, obj));
4705   }
4706   DBUG_PRINT("info", ("Failed to find filegroup"));
4707   DBUG_RETURN(-1);
4708 }
4709 
4710 int
dropUndofile(const NdbUndofileImpl & file)4711 NdbDictionaryImpl::dropUndofile(const NdbUndofileImpl & file)
4712 {
4713   return m_receiver.drop_file(file);
4714 }
4715 
4716 int
createTablespace(const NdbTablespaceImpl & fg,NdbDictObjectImpl * obj)4717 NdbDictionaryImpl::createTablespace(const NdbTablespaceImpl & fg,
4718 				    NdbDictObjectImpl* obj)
4719 {
4720   return m_receiver.create_filegroup(fg, obj);
4721 }
4722 
4723 int
dropTablespace(const NdbTablespaceImpl & fg)4724 NdbDictionaryImpl::dropTablespace(const NdbTablespaceImpl & fg)
4725 {
4726   return m_receiver.drop_filegroup(fg);
4727 }
4728 
4729 int
createLogfileGroup(const NdbLogfileGroupImpl & fg,NdbDictObjectImpl * obj)4730 NdbDictionaryImpl::createLogfileGroup(const NdbLogfileGroupImpl & fg,
4731 				      NdbDictObjectImpl* obj)
4732 {
4733   return m_receiver.create_filegroup(fg, obj);
4734 }
4735 
4736 int
dropLogfileGroup(const NdbLogfileGroupImpl & fg)4737 NdbDictionaryImpl::dropLogfileGroup(const NdbLogfileGroupImpl & fg)
4738 {
4739   return m_receiver.drop_filegroup(fg);
4740 }
4741 
4742 int
create_file(const NdbFileImpl & file,const NdbFilegroupImpl & group,bool overwrite,NdbDictObjectImpl * obj)4743 NdbDictInterface::create_file(const NdbFileImpl & file,
4744 			      const NdbFilegroupImpl & group,
4745 			      bool overwrite,
4746 			      NdbDictObjectImpl* obj)
4747 {
4748   DBUG_ENTER("NdbDictInterface::create_file");
4749   UtilBufferWriter w(m_buffer);
4750   DictFilegroupInfo::File f; f.init();
4751   snprintf(f.FileName, sizeof(f.FileName), file.m_path.c_str());
4752   f.FileType = file.m_type;
4753   f.FilegroupId = group.m_id;
4754   f.FilegroupVersion = group.m_version;
4755   f.FileSizeHi = (file.m_size >> 32);
4756   f.FileSizeLo = (file.m_size & 0xFFFFFFFF);
4757 
4758   SimpleProperties::UnpackStatus s;
4759   s = SimpleProperties::pack(w,
4760 			     &f,
4761 			     DictFilegroupInfo::FileMapping,
4762 			     DictFilegroupInfo::FileMappingSize, true);
4763 
4764   if(s != SimpleProperties::Eof){
4765     abort();
4766   }
4767 
4768   NdbApiSignal tSignal(m_reference);
4769   tSignal.theReceiversBlockNumber = DBDICT;
4770   tSignal.theVerId_signalNumber = GSN_CREATE_FILE_REQ;
4771   tSignal.theLength = CreateFileReq::SignalLength;
4772 
4773   CreateFileReq* req = CAST_PTR(CreateFileReq, tSignal.getDataPtrSend());
4774   req->senderRef = m_reference;
4775   req->senderData = 0;
4776   req->objType = file.m_type;
4777   req->requestInfo = 0;
4778   if (overwrite)
4779     req->requestInfo |= CreateFileReq::ForceCreateFile;
4780 
4781   LinearSectionPtr ptr[3];
4782   ptr[0].p = (Uint32*)m_buffer.get_data();
4783   ptr[0].sz = m_buffer.length() / 4;
4784 
4785   int err[] = { CreateFileRef::Busy, CreateFileRef::NotMaster, 0};
4786   /*
4787     Send signal without time-out since creating files can take a very long
4788     time if the file is very big.
4789   */
4790   int ret = dictSignal(&tSignal, ptr, 1,
4791 		       0, // master
4792 		       WAIT_CREATE_INDX_REQ,
4793 		       -1, 100,
4794 		       err);
4795 
4796   if (ret == 0 && obj)
4797   {
4798     Uint32* data = (Uint32*)m_buffer.get_data();
4799     obj->m_id = data[0];
4800     obj->m_version = data[1];
4801   }
4802 
4803   DBUG_RETURN(ret);
4804 }
4805 
4806 void
execCREATE_FILE_CONF(NdbApiSignal * signal,LinearSectionPtr ptr[3])4807 NdbDictInterface::execCREATE_FILE_CONF(NdbApiSignal * signal,
4808 				       LinearSectionPtr ptr[3])
4809 {
4810   const CreateFileConf* conf=
4811     CAST_CONSTPTR(CreateFileConf, signal->getDataPtr());
4812   m_buffer.grow(4 * 2); // 2 words
4813   Uint32* data = (Uint32*)m_buffer.get_data();
4814   data[0] = conf->fileId;
4815   data[1] = conf->fileVersion;
4816 
4817   m_waiter.signal(NO_WAIT);
4818 }
4819 
4820 void
execCREATE_FILE_REF(NdbApiSignal * signal,LinearSectionPtr ptr[3])4821 NdbDictInterface::execCREATE_FILE_REF(NdbApiSignal * signal,
4822 				      LinearSectionPtr ptr[3])
4823 {
4824   const CreateFileRef* ref =
4825     CAST_CONSTPTR(CreateFileRef, signal->getDataPtr());
4826   m_error.code = ref->errorCode;
4827   m_masterNodeId = ref->masterNodeId;
4828   m_waiter.signal(NO_WAIT);
4829 }
4830 
4831 int
drop_file(const NdbFileImpl & file)4832 NdbDictInterface::drop_file(const NdbFileImpl & file)
4833 {
4834   DBUG_ENTER("NdbDictInterface::drop_file");
4835   NdbApiSignal tSignal(m_reference);
4836   tSignal.theReceiversBlockNumber = DBDICT;
4837   tSignal.theVerId_signalNumber = GSN_DROP_FILE_REQ;
4838   tSignal.theLength = DropFileReq::SignalLength;
4839 
4840   DropFileReq* req = CAST_PTR(DropFileReq, tSignal.getDataPtrSend());
4841   req->senderRef = m_reference;
4842   req->senderData = 0;
4843   req->file_id = file.m_id;
4844   req->file_version = file.m_version;
4845 
4846   int err[] = { DropFileRef::Busy, DropFileRef::NotMaster, 0};
4847   DBUG_RETURN(dictSignal(&tSignal, 0, 0,
4848 	                 0, // master
4849 		         WAIT_CREATE_INDX_REQ,
4850 		         DICT_WAITFOR_TIMEOUT, 100,
4851 		         err));
4852 }
4853 
4854 void
execDROP_FILE_CONF(NdbApiSignal * signal,LinearSectionPtr ptr[3])4855 NdbDictInterface::execDROP_FILE_CONF(NdbApiSignal * signal,
4856 					    LinearSectionPtr ptr[3])
4857 {
4858   m_waiter.signal(NO_WAIT);
4859 }
4860 
4861 void
execDROP_FILE_REF(NdbApiSignal * signal,LinearSectionPtr ptr[3])4862 NdbDictInterface::execDROP_FILE_REF(NdbApiSignal * signal,
4863 					   LinearSectionPtr ptr[3])
4864 {
4865   const DropFileRef* ref =
4866     CAST_CONSTPTR(DropFileRef, signal->getDataPtr());
4867   m_error.code = ref->errorCode;
4868   m_masterNodeId = ref->masterNodeId;
4869   m_waiter.signal(NO_WAIT);
4870 }
4871 
4872 int
create_filegroup(const NdbFilegroupImpl & group,NdbDictObjectImpl * obj)4873 NdbDictInterface::create_filegroup(const NdbFilegroupImpl & group,
4874 				   NdbDictObjectImpl* obj)
4875 {
4876   DBUG_ENTER("NdbDictInterface::create_filegroup");
4877   UtilBufferWriter w(m_buffer);
4878   DictFilegroupInfo::Filegroup fg; fg.init();
4879   snprintf(fg.FilegroupName, sizeof(fg.FilegroupName), group.m_name.c_str());
4880   switch(group.m_type){
4881   case NdbDictionary::Object::Tablespace:
4882   {
4883     fg.FilegroupType = DictTabInfo::Tablespace;
4884     //fg.TS_DataGrow = group.m_grow_spec;
4885     fg.TS_ExtentSize = group.m_extent_size;
4886 
4887     if(group.m_logfile_group_version != ~(Uint32)0)
4888     {
4889       fg.TS_LogfileGroupId = group.m_logfile_group_id;
4890       fg.TS_LogfileGroupVersion = group.m_logfile_group_version;
4891     }
4892     else
4893     {
4894       NdbLogfileGroupImpl tmp;
4895       if(get_filegroup(tmp, NdbDictionary::Object::LogfileGroup,
4896 		       group.m_logfile_group_name.c_str()) == 0)
4897       {
4898 	fg.TS_LogfileGroupId = tmp.m_id;
4899 	fg.TS_LogfileGroupVersion = tmp.m_version;
4900       }
4901       else // error set by get filegroup
4902       {
4903 	DBUG_RETURN(-1);
4904       }
4905     }
4906   }
4907   break;
4908   case NdbDictionary::Object::LogfileGroup:
4909     fg.LF_UndoBufferSize = group.m_undo_buffer_size;
4910     fg.FilegroupType = DictTabInfo::LogfileGroup;
4911     //fg.LF_UndoGrow = group.m_grow_spec;
4912     break;
4913   default:
4914     abort();
4915     DBUG_RETURN(-1);
4916   };
4917 
4918   SimpleProperties::UnpackStatus s;
4919   s = SimpleProperties::pack(w,
4920 			     &fg,
4921 			     DictFilegroupInfo::Mapping,
4922 			     DictFilegroupInfo::MappingSize, true);
4923 
4924   if(s != SimpleProperties::Eof){
4925     abort();
4926   }
4927 
4928   NdbApiSignal tSignal(m_reference);
4929   tSignal.theReceiversBlockNumber = DBDICT;
4930   tSignal.theVerId_signalNumber = GSN_CREATE_FILEGROUP_REQ;
4931   tSignal.theLength = CreateFilegroupReq::SignalLength;
4932 
4933   CreateFilegroupReq* req =
4934     CAST_PTR(CreateFilegroupReq, tSignal.getDataPtrSend());
4935   req->senderRef = m_reference;
4936   req->senderData = 0;
4937   req->objType = fg.FilegroupType;
4938 
4939   LinearSectionPtr ptr[3];
4940   ptr[0].p = (Uint32*)m_buffer.get_data();
4941   ptr[0].sz = m_buffer.length() / 4;
4942 
4943   int err[] = { CreateFilegroupRef::Busy, CreateFilegroupRef::NotMaster, 0};
4944   int ret = dictSignal(&tSignal, ptr, 1,
4945 		       0, // master
4946 		       WAIT_CREATE_INDX_REQ,
4947 		       DICT_WAITFOR_TIMEOUT, 100,
4948 		       err);
4949 
4950   if (ret == 0 && obj)
4951   {
4952     Uint32* data = (Uint32*)m_buffer.get_data();
4953     obj->m_id = data[0];
4954     obj->m_version = data[1];
4955   }
4956 
4957   DBUG_RETURN(ret);
4958 }
4959 
4960 void
execCREATE_FILEGROUP_CONF(NdbApiSignal * signal,LinearSectionPtr ptr[3])4961 NdbDictInterface::execCREATE_FILEGROUP_CONF(NdbApiSignal * signal,
4962 					    LinearSectionPtr ptr[3])
4963 {
4964   const CreateFilegroupConf* conf=
4965     CAST_CONSTPTR(CreateFilegroupConf, signal->getDataPtr());
4966   m_buffer.grow(4 * 2); // 2 words
4967   Uint32* data = (Uint32*)m_buffer.get_data();
4968   data[0] = conf->filegroupId;
4969   data[1] = conf->filegroupVersion;
4970   m_waiter.signal(NO_WAIT);
4971 }
4972 
4973 void
execCREATE_FILEGROUP_REF(NdbApiSignal * signal,LinearSectionPtr ptr[3])4974 NdbDictInterface::execCREATE_FILEGROUP_REF(NdbApiSignal * signal,
4975 					   LinearSectionPtr ptr[3])
4976 {
4977   const CreateFilegroupRef* ref =
4978     CAST_CONSTPTR(CreateFilegroupRef, signal->getDataPtr());
4979   m_error.code = ref->errorCode;
4980   m_masterNodeId = ref->masterNodeId;
4981   m_waiter.signal(NO_WAIT);
4982 }
4983 
4984 int
drop_filegroup(const NdbFilegroupImpl & group)4985 NdbDictInterface::drop_filegroup(const NdbFilegroupImpl & group)
4986 {
4987   DBUG_ENTER("NdbDictInterface::drop_filegroup");
4988   NdbApiSignal tSignal(m_reference);
4989   tSignal.theReceiversBlockNumber = DBDICT;
4990   tSignal.theVerId_signalNumber = GSN_DROP_FILEGROUP_REQ;
4991   tSignal.theLength = DropFilegroupReq::SignalLength;
4992 
4993   DropFilegroupReq* req = CAST_PTR(DropFilegroupReq, tSignal.getDataPtrSend());
4994   req->senderRef = m_reference;
4995   req->senderData = 0;
4996   req->filegroup_id = group.m_id;
4997   req->filegroup_version = group.m_version;
4998 
4999   int err[] = { DropFilegroupRef::Busy, DropFilegroupRef::NotMaster, 0};
5000   DBUG_RETURN(dictSignal(&tSignal, 0, 0,
5001                          0, // master
5002 		         WAIT_CREATE_INDX_REQ,
5003 		         DICT_WAITFOR_TIMEOUT, 100,
5004 		         err));
5005 }
5006 
5007 void
execDROP_FILEGROUP_CONF(NdbApiSignal * signal,LinearSectionPtr ptr[3])5008 NdbDictInterface::execDROP_FILEGROUP_CONF(NdbApiSignal * signal,
5009 					    LinearSectionPtr ptr[3])
5010 {
5011   m_waiter.signal(NO_WAIT);
5012 }
5013 
5014 void
execDROP_FILEGROUP_REF(NdbApiSignal * signal,LinearSectionPtr ptr[3])5015 NdbDictInterface::execDROP_FILEGROUP_REF(NdbApiSignal * signal,
5016 					   LinearSectionPtr ptr[3])
5017 {
5018   const DropFilegroupRef* ref =
5019     CAST_CONSTPTR(DropFilegroupRef, signal->getDataPtr());
5020   m_error.code = ref->errorCode;
5021   m_masterNodeId = ref->masterNodeId;
5022   m_waiter.signal(NO_WAIT);
5023 }
5024 
5025 
5026 int
get_filegroup(NdbFilegroupImpl & dst,NdbDictionary::Object::Type type,const char * name)5027 NdbDictInterface::get_filegroup(NdbFilegroupImpl & dst,
5028 				NdbDictionary::Object::Type type,
5029 				const char * name){
5030   DBUG_ENTER("NdbDictInterface::get_filegroup");
5031   NdbApiSignal tSignal(m_reference);
5032   GetTabInfoReq * req = CAST_PTR(GetTabInfoReq, tSignal.getDataPtrSend());
5033 
5034   size_t strLen = strlen(name) + 1;
5035 
5036   req->senderRef = m_reference;
5037   req->senderData = 0;
5038   req->requestType =
5039     GetTabInfoReq::RequestByName | GetTabInfoReq::LongSignalConf;
5040   req->tableNameLen = strLen;
5041   tSignal.theReceiversBlockNumber = DBDICT;
5042   tSignal.theVerId_signalNumber   = GSN_GET_TABINFOREQ;
5043   tSignal.theLength = GetTabInfoReq::SignalLength;
5044 
5045   LinearSectionPtr ptr[1];
5046   ptr[0].p  = (Uint32*)name;
5047   ptr[0].sz = (strLen + 3)/4;
5048 
5049 #ifndef IGNORE_VALGRIND_WARNINGS
5050   if (strLen & 3)
5051   {
5052     Uint32 pad = 0;
5053     m_buffer.clear();
5054     m_buffer.append(name, strLen);
5055     m_buffer.append(&pad, 4);
5056     ptr[0].p = (Uint32*)m_buffer.get_data();
5057   }
5058 #endif
5059 
5060   int r = dictSignal(&tSignal, ptr, 1,
5061 		     -1, // any node
5062 		     WAIT_GET_TAB_INFO_REQ,
5063 		     DICT_WAITFOR_TIMEOUT, 100);
5064   if (r)
5065   {
5066     dst.m_id = -1;
5067     dst.m_version = ~0;
5068 
5069     DBUG_PRINT("info", ("get_filegroup failed dictSignal"));
5070     DBUG_RETURN(-1);
5071   }
5072 
5073   m_error.code = parseFilegroupInfo(dst,
5074 				    (Uint32*)m_buffer.get_data(),
5075 				    m_buffer.length() / 4);
5076 
5077   if(m_error.code)
5078   {
5079     DBUG_PRINT("info", ("get_filegroup failed parseFilegroupInfo %d",
5080                          m_error.code));
5081     DBUG_RETURN(m_error.code);
5082   }
5083 
5084   if(dst.m_type == NdbDictionary::Object::Tablespace)
5085   {
5086     NdbDictionary::LogfileGroup tmp;
5087     get_filegroup(NdbLogfileGroupImpl::getImpl(tmp),
5088 		  NdbDictionary::Object::LogfileGroup,
5089 		  dst.m_logfile_group_id);
5090     if (!dst.m_logfile_group_name.assign(tmp.getName()))
5091       DBUG_RETURN(m_error.code = 4000);
5092   }
5093 
5094   if(dst.m_type == type)
5095   {
5096     DBUG_RETURN(0);
5097   }
5098   DBUG_PRINT("info", ("get_filegroup failed no such filegroup"));
5099   DBUG_RETURN(m_error.code = GetTabInfoRef::TableNotDefined);
5100 }
5101 
5102 int
parseFilegroupInfo(NdbFilegroupImpl & dst,const Uint32 * data,Uint32 len)5103 NdbDictInterface::parseFilegroupInfo(NdbFilegroupImpl &dst,
5104 				     const Uint32 * data, Uint32 len)
5105 
5106 {
5107   SimplePropertiesLinearReader it(data, len);
5108 
5109   SimpleProperties::UnpackStatus status;
5110   DictFilegroupInfo::Filegroup fg; fg.init();
5111   status = SimpleProperties::unpack(it, &fg,
5112 				    DictFilegroupInfo::Mapping,
5113 				    DictFilegroupInfo::MappingSize,
5114 				    true, true);
5115 
5116   if(status != SimpleProperties::Eof){
5117     return CreateFilegroupRef::InvalidFormat;
5118   }
5119 
5120   dst.m_id = fg.FilegroupId;
5121   dst.m_version = fg.FilegroupVersion;
5122   dst.m_type = (NdbDictionary::Object::Type)fg.FilegroupType;
5123   dst.m_status = NdbDictionary::Object::Retrieved;
5124 
5125   if (!dst.m_name.assign(fg.FilegroupName))
5126     return 4000;
5127   dst.m_extent_size = fg.TS_ExtentSize;
5128   dst.m_undo_buffer_size = fg.LF_UndoBufferSize;
5129   dst.m_logfile_group_id = fg.TS_LogfileGroupId;
5130   dst.m_logfile_group_version = fg.TS_LogfileGroupVersion;
5131   dst.m_undo_free_words= ((Uint64)fg.LF_UndoFreeWordsHi << 32)
5132     | (fg.LF_UndoFreeWordsLo);
5133 
5134   return 0;
5135 }
5136 
5137 int
get_filegroup(NdbFilegroupImpl & dst,NdbDictionary::Object::Type type,Uint32 id)5138 NdbDictInterface::get_filegroup(NdbFilegroupImpl & dst,
5139 				NdbDictionary::Object::Type type,
5140 				Uint32 id){
5141   DBUG_ENTER("NdbDictInterface::get_filegroup");
5142   NdbApiSignal tSignal(m_reference);
5143   GetTabInfoReq * req = CAST_PTR(GetTabInfoReq, tSignal.getDataPtrSend());
5144 
5145   req->senderRef = m_reference;
5146   req->senderData = 0;
5147   req->requestType =
5148     GetTabInfoReq::RequestById | GetTabInfoReq::LongSignalConf;
5149   req->tableId = id;
5150   tSignal.theReceiversBlockNumber = DBDICT;
5151   tSignal.theVerId_signalNumber   = GSN_GET_TABINFOREQ;
5152   tSignal.theLength = GetTabInfoReq::SignalLength;
5153 
5154   int r = dictSignal(&tSignal, NULL, 1,
5155 		     -1, // any node
5156 		     WAIT_GET_TAB_INFO_REQ,
5157 		     DICT_WAITFOR_TIMEOUT, 100);
5158   if (r)
5159   {
5160     DBUG_PRINT("info", ("get_filegroup failed dictSignal"));
5161     DBUG_RETURN(-1);
5162   }
5163 
5164   m_error.code = parseFilegroupInfo(dst,
5165 				    (Uint32*)m_buffer.get_data(),
5166 				    m_buffer.length() / 4);
5167 
5168   if(m_error.code)
5169   {
5170     DBUG_PRINT("info", ("get_filegroup failed parseFilegroupInfo %d",
5171                          m_error.code));
5172     DBUG_RETURN(m_error.code);
5173   }
5174 
5175   if(dst.m_type == type)
5176   {
5177     DBUG_RETURN(0);
5178   }
5179   DBUG_PRINT("info", ("get_filegroup failed no such filegroup"));
5180   DBUG_RETURN(m_error.code = GetTabInfoRef::TableNotDefined);
5181 }
5182 
5183 int
get_file(NdbFileImpl & dst,NdbDictionary::Object::Type type,int node,const char * name)5184 NdbDictInterface::get_file(NdbFileImpl & dst,
5185 			   NdbDictionary::Object::Type type,
5186 			   int node,
5187 			   const char * name){
5188   DBUG_ENTER("NdbDictInterface::get_file");
5189   NdbApiSignal tSignal(m_reference);
5190   GetTabInfoReq * req = CAST_PTR(GetTabInfoReq, tSignal.getDataPtrSend());
5191 
5192   size_t strLen = strlen(name) + 1;
5193 
5194   req->senderRef = m_reference;
5195   req->senderData = 0;
5196   req->requestType =
5197     GetTabInfoReq::RequestByName | GetTabInfoReq::LongSignalConf;
5198   req->tableNameLen = strLen;
5199   tSignal.theReceiversBlockNumber = DBDICT;
5200   tSignal.theVerId_signalNumber   = GSN_GET_TABINFOREQ;
5201   tSignal.theLength = GetTabInfoReq::SignalLength;
5202 
5203   LinearSectionPtr ptr[1];
5204   ptr[0].p  = (Uint32*)name;
5205   ptr[0].sz = (strLen + 3)/4;
5206 
5207 #ifndef IGNORE_VALGRIND_WARNINGS
5208   if (strLen & 3)
5209   {
5210     Uint32 pad = 0;
5211     m_buffer.clear();
5212     m_buffer.append(name, strLen);
5213     m_buffer.append(&pad, 4);
5214     ptr[0].p = (Uint32*)m_buffer.get_data();
5215   }
5216 #endif
5217 
5218   int r = dictSignal(&tSignal, ptr, 1,
5219 		     node,
5220 		     WAIT_GET_TAB_INFO_REQ,
5221 		     DICT_WAITFOR_TIMEOUT, 100);
5222   if (r)
5223   {
5224     DBUG_PRINT("info", ("get_file failed dictSignal"));
5225     DBUG_RETURN(-1);
5226   }
5227 
5228   m_error.code = parseFileInfo(dst,
5229 			       (Uint32*)m_buffer.get_data(),
5230 			       m_buffer.length() / 4);
5231 
5232   if(m_error.code)
5233   {
5234     DBUG_PRINT("info", ("get_file failed parseFileInfo %d",
5235                          m_error.code));
5236     DBUG_RETURN(m_error.code);
5237   }
5238 
5239   if(dst.m_type == NdbDictionary::Object::Undofile)
5240   {
5241     NdbDictionary::LogfileGroup tmp;
5242     get_filegroup(NdbLogfileGroupImpl::getImpl(tmp),
5243 		  NdbDictionary::Object::LogfileGroup,
5244 		  dst.m_filegroup_id);
5245     if (!dst.m_filegroup_name.assign(tmp.getName()))
5246       DBUG_RETURN(m_error.code = 4000);
5247   }
5248   else if(dst.m_type == NdbDictionary::Object::Datafile)
5249   {
5250     NdbDictionary::Tablespace tmp;
5251     get_filegroup(NdbTablespaceImpl::getImpl(tmp),
5252 		  NdbDictionary::Object::Tablespace,
5253 		  dst.m_filegroup_id);
5254     if (!dst.m_filegroup_name.assign(tmp.getName()))
5255       DBUG_RETURN(m_error.code = 4000);
5256     dst.m_free *= tmp.getExtentSize();
5257   }
5258   else
5259     dst.m_filegroup_name.assign("Not Yet Implemented");
5260 
5261   if(dst.m_type == type)
5262   {
5263     DBUG_RETURN(0);
5264   }
5265   DBUG_PRINT("info", ("get_file failed no such file"));
5266   DBUG_RETURN(m_error.code = GetTabInfoRef::TableNotDefined);
5267 }
5268 
5269 int
parseFileInfo(NdbFileImpl & dst,const Uint32 * data,Uint32 len)5270 NdbDictInterface::parseFileInfo(NdbFileImpl &dst,
5271 				const Uint32 * data, Uint32 len)
5272 {
5273   SimplePropertiesLinearReader it(data, len);
5274 
5275   SimpleProperties::UnpackStatus status;
5276   DictFilegroupInfo::File f; f.init();
5277   status = SimpleProperties::unpack(it, &f,
5278 				    DictFilegroupInfo::FileMapping,
5279 				    DictFilegroupInfo::FileMappingSize,
5280 				    true, true);
5281 
5282   if(status != SimpleProperties::Eof){
5283     return CreateFilegroupRef::InvalidFormat;
5284   }
5285 
5286   dst.m_type= (NdbDictionary::Object::Type)f.FileType;
5287   dst.m_id= f.FileId;
5288   dst.m_version = f.FileVersion;
5289 
5290   dst.m_size= ((Uint64)f.FileSizeHi << 32) | (f.FileSizeLo);
5291   if (!dst.m_path.assign(f.FileName))
5292     return 4000;
5293 
5294   dst.m_filegroup_id= f.FilegroupId;
5295   dst.m_filegroup_version= f.FilegroupVersion;
5296   dst.m_free=  f.FileFreeExtents;
5297   return 0;
5298 }
5299 
5300 template class Vector<int>;
5301 template class Vector<Uint16>;
5302 template class Vector<Uint32>;
5303 template class Vector<Vector<Uint32> >;
5304 template class Vector<NdbTableImpl*>;
5305 template class Vector<NdbColumnImpl*>;
5306 
5307 const NdbDictionary::Column * NdbDictionary::Column::FRAGMENT = 0;
5308 const NdbDictionary::Column * NdbDictionary::Column::FRAGMENT_FIXED_MEMORY = 0;
5309 const NdbDictionary::Column * NdbDictionary::Column::FRAGMENT_VARSIZED_MEMORY = 0;
5310 const NdbDictionary::Column * NdbDictionary::Column::ROW_COUNT = 0;
5311 const NdbDictionary::Column * NdbDictionary::Column::COMMIT_COUNT = 0;
5312 const NdbDictionary::Column * NdbDictionary::Column::ROW_SIZE = 0;
5313 const NdbDictionary::Column * NdbDictionary::Column::RANGE_NO = 0;
5314 const NdbDictionary::Column * NdbDictionary::Column::DISK_REF = 0;
5315 const NdbDictionary::Column * NdbDictionary::Column::RECORDS_IN_RANGE = 0;
5316 const NdbDictionary::Column * NdbDictionary::Column::ROWID = 0;
5317 const NdbDictionary::Column * NdbDictionary::Column::ROW_GCI = 0;
5318 const NdbDictionary::Column * NdbDictionary::Column::ANY_VALUE = 0;
5319 const NdbDictionary::Column * NdbDictionary::Column::COPY_ROWID = 0;
5320