1 /*
2    Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License, version 2.0,
6    as published by the Free Software Foundation.
7 
8    This program is also distributed with certain software (including
9    but not limited to OpenSSL) that is licensed under separate terms,
10    as designated in a particular file or component or in included license
11    documentation.  The authors of MySQL hereby grant you an additional
12    permission to link the program and your derivative works with the
13    separately licensed software that they have included with MySQL.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License, version 2.0, for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
23 */
24 
25 #include "API.hpp"
26 #include <NdbOut.hpp>
27 #include <SimpleProperties.hpp>
28 #include <Bitmask.hpp>
29 #include <AttributeList.hpp>
30 #include <AttributeHeader.hpp>
31 #include <my_sys.h>
32 #include <NdbEnv.h>
33 #include <NdbMem.h>
34 #include <util/version.h>
35 #include <NdbSleep.h>
36 #include <signaldata/IndexStatSignal.hpp>
37 
38 #include <signaldata/GetTabInfo.hpp>
39 #include <signaldata/DictTabInfo.hpp>
40 #include <signaldata/CreateTable.hpp>
41 #include <signaldata/CreateIndx.hpp>
42 #include <signaldata/CreateEvnt.hpp>
43 #include <signaldata/SumaImpl.hpp>
44 #include <signaldata/DropTable.hpp>
45 #include <signaldata/AlterTable.hpp>
46 #include <signaldata/DropIndx.hpp>
47 #include <signaldata/ListTables.hpp>
48 #include <signaldata/DropFilegroup.hpp>
49 #include <signaldata/CreateFilegroup.hpp>
50 #include <signaldata/WaitGCP.hpp>
51 #include <signaldata/SchemaTrans.hpp>
52 #include <signaldata/CreateHashMap.hpp>
53 #include <signaldata/ApiRegSignalData.hpp>
54 #include <signaldata/NodeFailRep.hpp>
55 
56 #define DEBUG_PRINT 0
57 #define INCOMPATIBLE_VERSION -2
58 
59 #define DICT_WAITFOR_TIMEOUT (7*24*60*60*1000)
60 
61 #define ERR_RETURN(a,b) \
62 {\
63    DBUG_PRINT("exit", ("error %d  return %d", (a).code, b));\
64    DBUG_RETURN(b);\
65 }
66 
67 int ndb_dictionary_is_mysqld = 0;
68 
69 bool
is_ndb_blob_table(const char * name,Uint32 * ptab_id,Uint32 * pcol_no)70 is_ndb_blob_table(const char* name, Uint32* ptab_id, Uint32* pcol_no)
71 {
72   return DictTabInfo::isBlobTableName(name, ptab_id, pcol_no);
73 }
74 
75 bool
is_ndb_blob_table(const NdbTableImpl * t)76 is_ndb_blob_table(const NdbTableImpl* t)
77 {
78   return is_ndb_blob_table(t->m_internalName.c_str());
79 }
80 
81 bool
ignore_broken_blob_tables()82 ignore_broken_blob_tables()
83 {
84   /* To be able to fix broken blob tables, we must be able
85    * to ignore them when getting the table description
86    */
87   char envBuf[10];
88   const char* v = NdbEnv_GetEnv("NDB_FORCE_IGNORE_BROKEN_BLOB",
89                                 envBuf,
90                                 10);
91   return (v != NULL && *v != 0 && *v != '0' && *v != 'n' && *v != 'N');
92 }
93 
94 //#define EVENT_DEBUG
95 
96 /**
97  * Column
98  */
NdbColumnImpl()99 NdbColumnImpl::NdbColumnImpl()
100   : NdbDictionary::Column(* this), m_attrId(-1), m_facade(this)
101 {
102   DBUG_ENTER("NdbColumnImpl::NdbColumnImpl");
103   DBUG_PRINT("info", ("this: %p", this));
104   init();
105   DBUG_VOID_RETURN;
106 }
107 
NdbColumnImpl(NdbDictionary::Column & f)108 NdbColumnImpl::NdbColumnImpl(NdbDictionary::Column & f)
109   : NdbDictionary::Column(* this), m_attrId(-1), m_facade(&f)
110 {
111   DBUG_ENTER("NdbColumnImpl::NdbColumnImpl");
112   DBUG_PRINT("info", ("this: %p", this));
113   init();
114   DBUG_VOID_RETURN;
115 }
116 
117 NdbColumnImpl&
operator =(const NdbColumnImpl & col)118 NdbColumnImpl::operator=(const NdbColumnImpl& col)
119 {
120   DBUG_ENTER("NdbColumnImpl::operator=");
121   DBUG_PRINT("info", ("this: %p  &col: %p", this, &col));
122   m_attrId = col.m_attrId;
123   m_name = col.m_name;
124   m_type = col.m_type;
125   m_precision = col.m_precision;
126   m_cs = col.m_cs;
127   m_scale = col.m_scale;
128   m_length = col.m_length;
129   m_pk = col.m_pk;
130   m_distributionKey = col.m_distributionKey;
131   m_nullable = col.m_nullable;
132   m_autoIncrement = col.m_autoIncrement;
133   m_autoIncrementInitialValue = col.m_autoIncrementInitialValue;
134   m_defaultValue.assign(col.m_defaultValue);
135   m_attrSize = col.m_attrSize;
136   m_arraySize = col.m_arraySize;
137   m_arrayType = col.m_arrayType;
138   m_storageType = col.m_storageType;
139   m_blobVersion = col.m_blobVersion;
140   m_dynamic = col.m_dynamic;
141   m_indexSourced = col.m_indexSourced;
142   m_keyInfoPos = col.m_keyInfoPos;
143   if (col.m_blobTable == NULL)
144     m_blobTable = NULL;
145   else {
146     if (m_blobTable == NULL)
147       m_blobTable = new NdbTableImpl();
148     m_blobTable->assign(*col.m_blobTable);
149   }
150   m_column_no = col.m_column_no;
151   // Do not copy m_facade !!
152 
153   DBUG_RETURN(*this);
154 }
155 
156 void
init(Type t)157 NdbColumnImpl::init(Type t)
158 {
159   // do not use default_charset_info as it may not be initialized yet
160   // use binary collation until NDB tests can handle charsets
161   CHARSET_INFO* default_cs = &my_charset_bin;
162   m_blobVersion = 0;
163   m_type = t;
164   switch (m_type) {
165   case Tinyint:
166   case Tinyunsigned:
167   case Smallint:
168   case Smallunsigned:
169   case Mediumint:
170   case Mediumunsigned:
171   case Int:
172   case Unsigned:
173   case Bigint:
174   case Bigunsigned:
175   case Float:
176   case Double:
177     m_precision = 0;
178     m_scale = 0;
179     m_length = 1;
180     m_cs = NULL;
181     m_arrayType = NDB_ARRAYTYPE_FIXED;
182     break;
183   case Olddecimal:
184   case Olddecimalunsigned:
185   case Decimal:
186   case Decimalunsigned:
187     m_precision = 10;
188     m_scale = 0;
189     m_length = 1;
190     m_cs = NULL;
191     m_arrayType = NDB_ARRAYTYPE_FIXED;
192     break;
193   case Char:
194     m_precision = 0;
195     m_scale = 0;
196     m_length = 1;
197     m_cs = default_cs;
198     m_arrayType = NDB_ARRAYTYPE_FIXED;
199     break;
200   case Varchar:
201     m_precision = 0;
202     m_scale = 0;
203     m_length = 1;
204     m_cs = default_cs;
205     m_arrayType = NDB_ARRAYTYPE_SHORT_VAR;
206     break;
207   case Binary:
208     m_precision = 0;
209     m_scale = 0;
210     m_length = 1;
211     m_cs = NULL;
212     m_arrayType = NDB_ARRAYTYPE_FIXED;
213     break;
214   case Varbinary:
215     m_precision = 0;
216     m_scale = 0;
217     m_length = 1;
218     m_cs = NULL;
219     m_arrayType = NDB_ARRAYTYPE_SHORT_VAR;
220     break;
221   case Datetime:
222   case Date:
223     m_precision = 0;
224     m_scale = 0;
225     m_length = 1;
226     m_cs = NULL;
227     m_arrayType = NDB_ARRAYTYPE_FIXED;
228     break;
229   case Blob:
230   case Text:
231     m_precision = 256;
232     m_scale = 8000;
233     m_length = 0; // default no striping
234     m_cs = m_type == Blob ? NULL : default_cs;
235     m_arrayType = NDB_ARRAYTYPE_MEDIUM_VAR;
236     m_blobVersion = NDB_BLOB_V2;
237 #ifdef VM_TRACE
238     if (NdbEnv_GetEnv("NDB_DEFAULT_BLOB_V1", (char *)0, 0)) {
239       m_length = 4;
240       m_arrayType = NDB_ARRAYTYPE_FIXED;
241       m_blobVersion = NDB_BLOB_V1;
242     }
243 #endif
244     break;
245   case Time:
246   case Year:
247   case Timestamp:
248     m_precision = 0;
249     m_scale = 0;
250     m_length = 1;
251     m_cs = NULL;
252     m_arrayType = NDB_ARRAYTYPE_FIXED;
253     break;
254   case Bit:
255     m_precision = 0;
256     m_scale = 0;
257     m_length = 1;
258     m_cs = NULL;
259     m_arrayType = NDB_ARRAYTYPE_FIXED;
260     break;
261   case Longvarchar:
262     m_precision = 0;
263     m_scale = 0;
264     m_length = 1; // legal
265     m_cs = default_cs;
266     m_arrayType = NDB_ARRAYTYPE_MEDIUM_VAR;
267     break;
268   case Longvarbinary:
269     m_precision = 0;
270     m_scale = 0;
271     m_length = 1; // legal
272     m_cs = NULL;
273     m_arrayType = NDB_ARRAYTYPE_MEDIUM_VAR;
274     break;
275   default:
276   case Undefined:
277     assert(false);
278     break;
279   }
280   m_pk = false;
281   m_nullable = false;
282   m_distributionKey = false;
283   m_keyInfoPos = 0;
284   // next 2 are set at run time
285   m_attrSize = 0;
286   m_arraySize = 0;
287   m_autoIncrement = false;
288   m_autoIncrementInitialValue = 1;
289   m_blobTable = NULL;
290   m_storageType = NDB_STORAGETYPE_MEMORY;
291   m_dynamic = false;
292   m_indexSourced= false;
293 #ifdef VM_TRACE
294   if(NdbEnv_GetEnv("NDB_DEFAULT_DISK", (char *)0, 0))
295     m_storageType = NDB_STORAGETYPE_DISK;
296 #endif
297 }
298 
~NdbColumnImpl()299 NdbColumnImpl::~NdbColumnImpl()
300 {
301   DBUG_ENTER("NdbColumnImpl::~NdbColumnImpl");
302   DBUG_PRINT("info", ("this: %p", this));
303   if (m_blobTable != NULL)
304     delete m_blobTable;
305   m_blobTable = NULL;
306   DBUG_VOID_RETURN;
307 }
308 
309 bool
equal(const NdbColumnImpl & col) const310 NdbColumnImpl::equal(const NdbColumnImpl& col) const
311 {
312   DBUG_ENTER("NdbColumnImpl::equal");
313   DBUG_PRINT("info", ("this: %p  &col: %p", this, &col));
314   /* New member comparisons added here should also be
315    * handled in the BackupRestore::column_compatible_check()
316    * member of tools/restore/consumer_restore.cpp
317    */
318   if(strcmp(m_name.c_str(), col.m_name.c_str()) != 0){
319     DBUG_RETURN(false);
320   }
321   if(m_type != col.m_type){
322     DBUG_RETURN(false);
323   }
324   if(m_pk != col.m_pk){
325     DBUG_RETURN(false);
326   }
327   if(m_nullable != col.m_nullable){
328     DBUG_RETURN(false);
329   }
330   if (m_pk) {
331     if (m_distributionKey != col.m_distributionKey) {
332       DBUG_RETURN(false);
333     }
334   }
335   if (m_precision != col.m_precision ||
336       m_scale != col.m_scale ||
337       m_length != col.m_length ||
338       m_cs != col.m_cs) {
339     DBUG_RETURN(false);
340   }
341   if (m_autoIncrement != col.m_autoIncrement){
342     DBUG_RETURN(false);
343   }
344   if (m_defaultValue.length() != col.m_defaultValue.length())
345     DBUG_RETURN(false);
346 
347   if(memcmp(m_defaultValue.get_data(), col.m_defaultValue.get_data(), m_defaultValue.length()) != 0){
348     DBUG_RETURN(false);
349   }
350 
351   if (m_arrayType != col.m_arrayType || m_storageType != col.m_storageType){
352     DBUG_RETURN(false);
353   }
354   if (m_blobVersion != col.m_blobVersion) {
355     DBUG_RETURN(false);
356   }
357   if(m_dynamic != col.m_dynamic){
358     DBUG_RETURN(false);
359   }
360 
361   DBUG_RETURN(true);
362 }
363 
364 void
create_pseudo_columns()365 NdbColumnImpl::create_pseudo_columns()
366 {
367   NdbDictionary::Column::FRAGMENT=
368     NdbColumnImpl::create_pseudo("NDB$FRAGMENT");
369   NdbDictionary::Column::FRAGMENT_FIXED_MEMORY=
370     NdbColumnImpl::create_pseudo("NDB$FRAGMENT_FIXED_MEMORY");
371   NdbDictionary::Column::FRAGMENT_VARSIZED_MEMORY=
372     NdbColumnImpl::create_pseudo("NDB$FRAGMENT_VARSIZED_MEMORY");
373   NdbDictionary::Column::ROW_COUNT=
374     NdbColumnImpl::create_pseudo("NDB$ROW_COUNT");
375   NdbDictionary::Column::COMMIT_COUNT=
376     NdbColumnImpl::create_pseudo("NDB$COMMIT_COUNT");
377   NdbDictionary::Column::ROW_SIZE=
378     NdbColumnImpl::create_pseudo("NDB$ROW_SIZE");
379   NdbDictionary::Column::RANGE_NO=
380     NdbColumnImpl::create_pseudo("NDB$RANGE_NO");
381   NdbDictionary::Column::DISK_REF=
382     NdbColumnImpl::create_pseudo("NDB$DISK_REF");
383   NdbDictionary::Column::RECORDS_IN_RANGE=
384     NdbColumnImpl::create_pseudo("NDB$RECORDS_IN_RANGE");
385   NdbDictionary::Column::ROWID=
386     NdbColumnImpl::create_pseudo("NDB$ROWID");
387   NdbDictionary::Column::ROW_GCI=
388     NdbColumnImpl::create_pseudo("NDB$ROW_GCI");
389   NdbDictionary::Column::ROW_GCI64 =
390     NdbColumnImpl::create_pseudo("NDB$ROW_GCI64");
391   NdbDictionary::Column::ROW_AUTHOR =
392     NdbColumnImpl::create_pseudo("NDB$ROW_AUTHOR");
393   NdbDictionary::Column::ANY_VALUE=
394     NdbColumnImpl::create_pseudo("NDB$ANY_VALUE");
395   NdbDictionary::Column::COPY_ROWID=
396     NdbColumnImpl::create_pseudo("NDB$COPY_ROWID");
397   NdbDictionary::Column::OPTIMIZE=
398     NdbColumnImpl::create_pseudo("NDB$OPTIMIZE");
399   NdbDictionary::Column::FRAGMENT_EXTENT_SPACE =
400     NdbColumnImpl::create_pseudo("NDB$FRAGMENT_EXTENT_SPACE");
401   NdbDictionary::Column::FRAGMENT_FREE_EXTENT_SPACE =
402     NdbColumnImpl::create_pseudo("NDB$FRAGMENT_FREE_EXTENT_SPACE");
403   NdbDictionary::Column::LOCK_REF =
404     NdbColumnImpl::create_pseudo("NDB$LOCK_REF");
405   NdbDictionary::Column::OP_ID =
406     NdbColumnImpl::create_pseudo("NDB$OP_ID");
407 }
408 
409 void
destory_pseudo_columns()410 NdbColumnImpl::destory_pseudo_columns()
411 {
412   delete NdbDictionary::Column::FRAGMENT;
413   delete NdbDictionary::Column::FRAGMENT_FIXED_MEMORY;
414   delete NdbDictionary::Column::FRAGMENT_VARSIZED_MEMORY;
415   delete NdbDictionary::Column::ROW_COUNT;
416   delete NdbDictionary::Column::COMMIT_COUNT;
417   delete NdbDictionary::Column::ROW_SIZE;
418   delete NdbDictionary::Column::RANGE_NO;
419   delete NdbDictionary::Column::DISK_REF;
420   delete NdbDictionary::Column::RECORDS_IN_RANGE;
421   delete NdbDictionary::Column::ROWID;
422   delete NdbDictionary::Column::ROW_GCI;
423   delete NdbDictionary::Column::ROW_GCI64;
424   delete NdbDictionary::Column::ROW_AUTHOR;
425   delete NdbDictionary::Column::ANY_VALUE;
426   delete NdbDictionary::Column::OPTIMIZE;
427   NdbDictionary::Column::FRAGMENT= 0;
428   NdbDictionary::Column::FRAGMENT_FIXED_MEMORY= 0;
429   NdbDictionary::Column::FRAGMENT_VARSIZED_MEMORY= 0;
430   NdbDictionary::Column::ROW_COUNT= 0;
431   NdbDictionary::Column::COMMIT_COUNT= 0;
432   NdbDictionary::Column::ROW_SIZE= 0;
433   NdbDictionary::Column::RANGE_NO= 0;
434   NdbDictionary::Column::DISK_REF= 0;
435   NdbDictionary::Column::RECORDS_IN_RANGE= 0;
436   NdbDictionary::Column::ROWID= 0;
437   NdbDictionary::Column::ROW_GCI= 0;
438   NdbDictionary::Column::ROW_GCI64= 0;
439   NdbDictionary::Column::ROW_AUTHOR= 0;
440   NdbDictionary::Column::ANY_VALUE= 0;
441   NdbDictionary::Column::OPTIMIZE= 0;
442 
443   delete NdbDictionary::Column::COPY_ROWID;
444   NdbDictionary::Column::COPY_ROWID = 0;
445 
446   delete NdbDictionary::Column::FRAGMENT_EXTENT_SPACE;
447   NdbDictionary::Column::FRAGMENT_EXTENT_SPACE = 0;
448 
449   delete NdbDictionary::Column::FRAGMENT_FREE_EXTENT_SPACE;
450   NdbDictionary::Column::FRAGMENT_FREE_EXTENT_SPACE = 0;
451 
452   delete NdbDictionary::Column::LOCK_REF;
453   delete NdbDictionary::Column::OP_ID;
454   NdbDictionary::Column::LOCK_REF = 0;
455   NdbDictionary::Column::OP_ID = 0;
456 }
457 
458 NdbDictionary::Column *
create_pseudo(const char * name)459 NdbColumnImpl::create_pseudo(const char * name){
460   NdbDictionary::Column * col = new NdbDictionary::Column();
461   col->setName(name);
462   if(!strcmp(name, "NDB$FRAGMENT")){
463     col->setType(NdbDictionary::Column::Unsigned);
464     col->m_impl.m_attrId = AttributeHeader::FRAGMENT;
465     col->m_impl.m_attrSize = 4;
466     col->m_impl.m_arraySize = 1;
467   } else if(!strcmp(name, "NDB$FRAGMENT_FIXED_MEMORY")){
468     col->setType(NdbDictionary::Column::Bigunsigned);
469     col->m_impl.m_attrId = AttributeHeader::FRAGMENT_FIXED_MEMORY;
470     col->m_impl.m_attrSize = 8;
471     col->m_impl.m_arraySize = 1;
472   } else if(!strcmp(name, "NDB$FRAGMENT_VARSIZED_MEMORY")){
473     col->setType(NdbDictionary::Column::Bigunsigned);
474     col->m_impl.m_attrId = AttributeHeader::FRAGMENT_VARSIZED_MEMORY;
475     col->m_impl.m_attrSize = 8;
476     col->m_impl.m_arraySize = 1;
477   } else if(!strcmp(name, "NDB$ROW_COUNT")){
478     col->setType(NdbDictionary::Column::Bigunsigned);
479     col->m_impl.m_attrId = AttributeHeader::ROW_COUNT;
480     col->m_impl.m_attrSize = 8;
481     col->m_impl.m_arraySize = 1;
482   } else if(!strcmp(name, "NDB$COMMIT_COUNT")){
483     col->setType(NdbDictionary::Column::Bigunsigned);
484     col->m_impl.m_attrId = AttributeHeader::COMMIT_COUNT;
485     col->m_impl.m_attrSize = 8;
486     col->m_impl.m_arraySize = 1;
487   } else if(!strcmp(name, "NDB$ROW_SIZE")){
488     col->setType(NdbDictionary::Column::Unsigned);
489     col->m_impl.m_attrId = AttributeHeader::ROW_SIZE;
490     col->m_impl.m_attrSize = 4;
491     col->m_impl.m_arraySize = 1;
492   } else if(!strcmp(name, "NDB$RANGE_NO")){
493     col->setType(NdbDictionary::Column::Unsigned);
494     col->m_impl.m_attrId = AttributeHeader::RANGE_NO;
495     col->m_impl.m_attrSize = 4;
496     col->m_impl.m_arraySize = 1;
497   } else if(!strcmp(name, "NDB$DISK_REF")){
498     col->setType(NdbDictionary::Column::Bigunsigned);
499     col->m_impl.m_attrId = AttributeHeader::DISK_REF;
500     col->m_impl.m_attrSize = 8;
501     col->m_impl.m_arraySize = 1;
502   } else if(!strcmp(name, "NDB$RECORDS_IN_RANGE")){
503     col->setType(NdbDictionary::Column::Unsigned);
504     col->m_impl.m_attrId = AttributeHeader::RECORDS_IN_RANGE;
505     col->m_impl.m_attrSize = 4;
506     col->m_impl.m_arraySize = 4;
507   } else if(!strcmp(name, "NDB$ROWID")){
508     col->setType(NdbDictionary::Column::Bigunsigned);
509     col->m_impl.m_attrId = AttributeHeader::ROWID;
510     col->m_impl.m_attrSize = 4;
511     col->m_impl.m_arraySize = 2;
512   } else if(!strcmp(name, "NDB$ROW_GCI")){
513     col->setType(NdbDictionary::Column::Bigunsigned);
514     col->m_impl.m_attrId = AttributeHeader::ROW_GCI;
515     col->m_impl.m_attrSize = 8;
516     col->m_impl.m_arraySize = 1;
517     col->m_impl.m_nullable = true;
518   } else if(!strcmp(name, "NDB$ROW_GCI64")){
519     col->setType(NdbDictionary::Column::Bigunsigned);
520     col->m_impl.m_attrId = AttributeHeader::ROW_GCI64;
521     col->m_impl.m_attrSize = 8;
522     col->m_impl.m_arraySize = 1;
523     col->m_impl.m_nullable = true;
524   } else if(!strcmp(name, "NDB$ROW_AUTHOR")){
525     col->setType(NdbDictionary::Column::Unsigned);
526     col->m_impl.m_attrId = AttributeHeader::ROW_AUTHOR;
527     col->m_impl.m_attrSize = 4;
528     col->m_impl.m_arraySize = 1;
529     col->m_impl.m_nullable = true;
530   } else if(!strcmp(name, "NDB$ANY_VALUE")){
531     col->setType(NdbDictionary::Column::Unsigned);
532     col->m_impl.m_attrId = AttributeHeader::ANY_VALUE;
533     col->m_impl.m_attrSize = 4;
534     col->m_impl.m_arraySize = 1;
535   } else if(!strcmp(name, "NDB$COPY_ROWID")){
536     col->setType(NdbDictionary::Column::Bigunsigned);
537     col->m_impl.m_attrId = AttributeHeader::COPY_ROWID;
538     col->m_impl.m_attrSize = 4;
539     col->m_impl.m_arraySize = 2;
540   } else if(!strcmp(name, "NDB$OPTIMIZE")){
541     col->setType(NdbDictionary::Column::Unsigned);
542     col->m_impl.m_attrId = AttributeHeader::OPTIMIZE;
543     col->m_impl.m_attrSize = 4;
544     col->m_impl.m_arraySize = 1;
545   } else if(!strcmp(name, "NDB$FRAGMENT_EXTENT_SPACE")){
546     col->setType(NdbDictionary::Column::Bigunsigned);
547     col->m_impl.m_attrId = AttributeHeader::FRAGMENT_EXTENT_SPACE;
548     col->m_impl.m_attrSize = 4;
549     col->m_impl.m_arraySize = 2;
550   } else if(!strcmp(name, "NDB$FRAGMENT_FREE_EXTENT_SPACE")){
551     col->setType(NdbDictionary::Column::Bigunsigned);
552     col->m_impl.m_attrId = AttributeHeader::FRAGMENT_FREE_EXTENT_SPACE;
553     col->m_impl.m_attrSize = 4;
554     col->m_impl.m_arraySize = 2;
555   } else if (!strcmp(name, "NDB$LOCK_REF")){
556     col->setType(NdbDictionary::Column::Unsigned);
557     col->m_impl.m_attrId = AttributeHeader::LOCK_REF;
558     col->m_impl.m_attrSize = 4;
559     col->m_impl.m_arraySize = 3;
560   } else if (!strcmp(name, "NDB$OP_ID")){
561     col->setType(NdbDictionary::Column::Bigunsigned);
562     col->m_impl.m_attrId = AttributeHeader::OP_ID;
563     col->m_impl.m_attrSize = 8;
564     col->m_impl.m_arraySize = 1;
565   }
566   else {
567     abort();
568   }
569   col->m_impl.m_storageType = NDB_STORAGETYPE_MEMORY;
570   return col;
571 }
572 
573 /**
574  * NdbTableImpl
575  */
576 
NdbTableImpl()577 NdbTableImpl::NdbTableImpl()
578   : NdbDictionary::Table(* this),
579     NdbDictObjectImpl(NdbDictionary::Object::UserTable), m_facade(this)
580 {
581   DBUG_ENTER("NdbTableImpl::NdbTableImpl");
582   DBUG_PRINT("info", ("this: %p", this));
583   init();
584   DBUG_VOID_RETURN;
585 }
586 
NdbTableImpl(NdbDictionary::Table & f)587 NdbTableImpl::NdbTableImpl(NdbDictionary::Table & f)
588   : NdbDictionary::Table(* this),
589     NdbDictObjectImpl(NdbDictionary::Object::UserTable), m_facade(&f)
590 {
591   DBUG_ENTER("NdbTableImpl::NdbTableImpl");
592   DBUG_PRINT("info", ("this: %p", this));
593   init();
594   DBUG_VOID_RETURN;
595 }
596 
~NdbTableImpl()597 NdbTableImpl::~NdbTableImpl()
598 {
599   DBUG_ENTER("NdbTableImpl::~NdbTableImpl");
600   DBUG_PRINT("info", ("this: %p", this));
601   if (m_index != 0) {
602     delete m_index;
603     m_index = 0;
604   }
605   for (unsigned i = 0; i < m_columns.size(); i++)
606     delete m_columns[i];
607 
608   if (m_ndbrecord !=0) {
609     free(m_ndbrecord); // As it was calloc'd
610     m_ndbrecord= 0;
611   }
612 
613   if (m_pkMask != 0) {
614     free(const_cast<unsigned char *>(m_pkMask));
615     m_pkMask= 0;
616   }
617 
618   DBUG_VOID_RETURN;
619 }
620 
621 void
init()622 NdbTableImpl::init(){
623   m_id= RNIL;
624   m_version = ~0;
625   m_status = NdbDictionary::Object::Invalid;
626   m_type = NdbDictionary::Object::TypeUndefined;
627   m_primaryTableId= RNIL;
628   m_internalName.clear();
629   m_externalName.clear();
630   m_mysqlName.clear();
631   m_frm.clear();
632   m_fd.clear();
633   m_range.clear();
634   m_fragmentType= NdbDictionary::Object::HashMapPartition;
635   m_hashValueMask= 0;
636   m_hashpointerValue= 0;
637   m_linear_flag= true;
638   m_primaryTable.clear();
639   m_default_no_part_flag = 1;
640   m_logging= true;
641   m_temporary = false;
642   m_row_gci = true;
643   m_row_checksum = true;
644   m_force_var_part = false;
645   m_has_default_values = false;
646   m_kvalue= 6;
647   m_minLoadFactor= 78;
648   m_maxLoadFactor= 80;
649   m_keyLenInWords= 0;
650   m_fragmentCount= 0;
651   m_index= NULL;
652   m_indexType= NdbDictionary::Object::TypeUndefined;
653   m_noOfKeys= 0;
654   m_noOfDistributionKeys= 0;
655   m_noOfBlobs= 0;
656   m_replicaCount= 0;
657   m_noOfAutoIncColumns = 0;
658   m_ndbrecord= 0;
659   m_pkMask= 0;
660   m_min_rows = 0;
661   m_max_rows = 0;
662   m_tablespace_name.clear();
663   m_tablespace_id = RNIL;
664   m_tablespace_version = ~0;
665   m_single_user_mode = 0;
666   m_hash_map_id = RNIL;
667   m_hash_map_version = ~0;
668   m_storageType = NDB_STORAGETYPE_DEFAULT;
669   m_extra_row_gci_bits = 0;
670   m_extra_row_author_bits = 0;
671 }
672 
673 bool
equal(const NdbTableImpl & obj) const674 NdbTableImpl::equal(const NdbTableImpl& obj) const
675 {
676   DBUG_ENTER("NdbTableImpl::equal");
677   if ((m_internalName.c_str() == NULL) ||
678       (strcmp(m_internalName.c_str(), "") == 0) ||
679       (obj.m_internalName.c_str() == NULL) ||
680       (strcmp(obj.m_internalName.c_str(), "") == 0))
681   {
682     // Shallow equal
683     if(strcmp(getName(), obj.getName()) != 0)
684     {
685       DBUG_PRINT("info",("name %s != %s",getName(),obj.getName()));
686       DBUG_RETURN(false);
687     }
688   }
689   else
690   {
691     // Deep equal
692     if(strcmp(m_internalName.c_str(), obj.m_internalName.c_str()) != 0)
693     {
694       DBUG_PRINT("info",("m_internalName %s != %s",
695 			 m_internalName.c_str(),obj.m_internalName.c_str()));
696       DBUG_RETURN(false);
697     }
698   }
699   if (m_frm.length() != obj.m_frm.length() ||
700       (memcmp(m_frm.get_data(), obj.m_frm.get_data(), m_frm.length())))
701   {
702     DBUG_PRINT("info",("m_frm not equal"));
703     DBUG_RETURN(false);
704   }
705   if (!m_fd.equal(obj.m_fd))
706   {
707     DBUG_PRINT("info",("m_fd not equal"));
708     DBUG_RETURN(false);
709   }
710   if (!m_range.equal(obj.m_range))
711   {
712     DBUG_PRINT("info",("m_range not equal"));
713     DBUG_RETURN(false);
714   }
715   if(m_fragmentType != obj.m_fragmentType)
716   {
717     DBUG_PRINT("info",("m_fragmentType %d != %d",m_fragmentType,
718                         obj.m_fragmentType));
719     DBUG_RETURN(false);
720   }
721   if(m_columns.size() != obj.m_columns.size())
722   {
723     DBUG_PRINT("info",("m_columns.size %d != %d",m_columns.size(),
724                        obj.m_columns.size()));
725     DBUG_RETURN(false);
726   }
727 
728   for(unsigned i = 0; i<obj.m_columns.size(); i++)
729   {
730     if(!m_columns[i]->equal(* obj.m_columns[i]))
731     {
732       DBUG_PRINT("info",("m_columns [%d] != [%d]",i,i));
733       DBUG_RETURN(false);
734     }
735   }
736 
737   if(m_linear_flag != obj.m_linear_flag)
738   {
739     DBUG_PRINT("info",("m_linear_flag %d != %d",m_linear_flag,
740                         obj.m_linear_flag));
741     DBUG_RETURN(false);
742   }
743 
744   if(m_max_rows != obj.m_max_rows)
745   {
746     DBUG_PRINT("info",("m_max_rows %d != %d",(int32)m_max_rows,
747                        (int32)obj.m_max_rows));
748     DBUG_RETURN(false);
749   }
750 
751   if(m_default_no_part_flag != obj.m_default_no_part_flag)
752   {
753     DBUG_PRINT("info",("m_default_no_part_flag %d != %d",m_default_no_part_flag,
754                         obj.m_default_no_part_flag));
755     DBUG_RETURN(false);
756   }
757 
758   if(m_logging != obj.m_logging)
759   {
760     DBUG_PRINT("info",("m_logging %d != %d",m_logging,obj.m_logging));
761     DBUG_RETURN(false);
762   }
763 
764   if(m_temporary != obj.m_temporary)
765   {
766     DBUG_PRINT("info",("m_temporary %d != %d",m_temporary,obj.m_temporary));
767     DBUG_RETURN(false);
768   }
769 
770   if(m_row_gci != obj.m_row_gci)
771   {
772     DBUG_PRINT("info",("m_row_gci %d != %d",m_row_gci,obj.m_row_gci));
773     DBUG_RETURN(false);
774   }
775 
776   if(m_row_checksum != obj.m_row_checksum)
777   {
778     DBUG_PRINT("info",("m_row_checksum %d != %d",m_row_checksum,
779                         obj.m_row_checksum));
780     DBUG_RETURN(false);
781   }
782 
783   if(m_kvalue != obj.m_kvalue)
784   {
785     DBUG_PRINT("info",("m_kvalue %d != %d",m_kvalue,obj.m_kvalue));
786     DBUG_RETURN(false);
787   }
788 
789   if(m_minLoadFactor != obj.m_minLoadFactor)
790   {
791     DBUG_PRINT("info",("m_minLoadFactor %d != %d",m_minLoadFactor,
792                         obj.m_minLoadFactor));
793     DBUG_RETURN(false);
794   }
795 
796   if(m_maxLoadFactor != obj.m_maxLoadFactor)
797   {
798     DBUG_PRINT("info",("m_maxLoadFactor %d != %d",m_maxLoadFactor,
799                         obj.m_maxLoadFactor));
800     DBUG_RETURN(false);
801   }
802 
803   if(m_tablespace_id != obj.m_tablespace_id)
804   {
805     DBUG_PRINT("info",("m_tablespace_id %d != %d",m_tablespace_id,
806                         obj.m_tablespace_id));
807     DBUG_RETURN(false);
808   }
809 
810   if(m_tablespace_version != obj.m_tablespace_version)
811   {
812     DBUG_PRINT("info",("m_tablespace_version %d != %d",m_tablespace_version,
813                         obj.m_tablespace_version));
814     DBUG_RETURN(false);
815   }
816 
817   if(m_id != obj.m_id)
818   {
819     DBUG_PRINT("info",("m_id %d != %d",m_id,obj.m_id));
820     DBUG_RETURN(false);
821   }
822 
823   if(m_version != obj.m_version)
824   {
825     DBUG_PRINT("info",("m_version %d != %d",m_version,obj.m_version));
826     DBUG_RETURN(false);
827   }
828 
829   if(m_type != obj.m_type)
830   {
831     DBUG_PRINT("info",("m_type %d != %d",m_type,obj.m_type));
832     DBUG_RETURN(false);
833   }
834 
835   if (m_type == NdbDictionary::Object::UniqueHashIndex ||
836       m_type == NdbDictionary::Object::OrderedIndex)
837   {
838     if(m_primaryTableId != obj.m_primaryTableId)
839     {
840       DBUG_PRINT("info",("m_primaryTableId %d != %d",m_primaryTableId,
841                  obj.m_primaryTableId));
842       DBUG_RETURN(false);
843     }
844     if (m_indexType != obj.m_indexType)
845     {
846       DBUG_PRINT("info",("m_indexType %d != %d",m_indexType,obj.m_indexType));
847       DBUG_RETURN(false);
848     }
849     if(strcmp(m_primaryTable.c_str(), obj.m_primaryTable.c_str()) != 0)
850     {
851       DBUG_PRINT("info",("m_primaryTable %s != %s",
852 			 m_primaryTable.c_str(),obj.m_primaryTable.c_str()));
853       DBUG_RETURN(false);
854     }
855   }
856 
857   if(m_single_user_mode != obj.m_single_user_mode)
858   {
859     DBUG_PRINT("info",("m_single_user_mode %d != %d",
860                        (int32)m_single_user_mode,
861                        (int32)obj.m_single_user_mode));
862     DBUG_RETURN(false);
863   }
864 
865   if (m_extra_row_gci_bits != obj.m_extra_row_gci_bits)
866   {
867     DBUG_PRINT("info",("m_extra_row_gci_bits %d != %d",
868                        (int32)m_extra_row_gci_bits,
869                        (int32)obj.m_extra_row_gci_bits));
870     DBUG_RETURN(false);
871   }
872 
873   if (m_extra_row_author_bits != obj.m_extra_row_author_bits)
874   {
875     DBUG_PRINT("info",("m_extra_row_author_bits %d != %d",
876                        (int32)m_extra_row_author_bits,
877                        (int32)obj.m_extra_row_author_bits));
878     DBUG_RETURN(false);
879   }
880 
881   DBUG_RETURN(true);
882 }
883 
884 int
assign(const NdbTableImpl & org)885 NdbTableImpl::assign(const NdbTableImpl& org)
886 {
887   DBUG_ENTER("NdbColumnImpl::assign");
888   DBUG_PRINT("info", ("this: %p  &org: %p", this, &org));
889   m_primaryTableId = org.m_primaryTableId;
890   if (!m_internalName.assign(org.m_internalName) ||
891       updateMysqlName())
892   {
893     return -1;
894   }
895   m_externalName.assign(org.m_externalName);
896   m_frm.assign(org.m_frm.get_data(), org.m_frm.length());
897   m_fd.assign(org.m_fd);
898   m_range.assign(org.m_range);
899 
900   m_fragmentType = org.m_fragmentType;
901   /*
902     m_columnHashMask, m_columnHash, m_hashValueMask, m_hashpointerValue
903     is state calculated by computeAggregates and buildColumnHash
904   */
905   unsigned i;
906   for(i = 0; i < m_columns.size(); i++)
907   {
908     delete m_columns[i];
909   }
910   m_columns.clear();
911   for(i = 0; i < org.m_columns.size(); i++)
912   {
913     NdbColumnImpl * col = new NdbColumnImpl();
914     if (col == NULL)
915     {
916       errno = ENOMEM;
917       return -1;
918     }
919     const NdbColumnImpl * iorg = org.m_columns[i];
920     (* col) = (* iorg);
921     if (m_columns.push_back(col))
922     {
923       delete col;
924       return -1;
925     }
926   }
927 
928   m_fragments = org.m_fragments;
929 
930   m_linear_flag = org.m_linear_flag;
931   m_max_rows = org.m_max_rows;
932   m_default_no_part_flag = org.m_default_no_part_flag;
933   m_logging = org.m_logging;
934   m_temporary = org.m_temporary;
935   m_row_gci = org.m_row_gci;
936   m_row_checksum = org.m_row_checksum;
937   m_force_var_part = org.m_force_var_part;
938   m_has_default_values = org.m_has_default_values;
939   m_kvalue = org.m_kvalue;
940   m_minLoadFactor = org.m_minLoadFactor;
941   m_maxLoadFactor = org.m_maxLoadFactor;
942   m_keyLenInWords = org.m_keyLenInWords;
943   m_fragmentCount = org.m_fragmentCount;
944 
945   m_single_user_mode = org.m_single_user_mode;
946   m_extra_row_gci_bits = org.m_extra_row_gci_bits;
947   m_extra_row_author_bits = org.m_extra_row_author_bits;
948 
949   if (m_index != 0)
950     delete m_index;
951   m_index = org.m_index;
952 
953   m_primaryTable = org.m_primaryTable;
954   m_indexType = org.m_indexType;
955 
956   m_noOfKeys = org.m_noOfKeys;
957   m_noOfDistributionKeys = org.m_noOfDistributionKeys;
958   m_noOfBlobs = org.m_noOfBlobs;
959   m_replicaCount = org.m_replicaCount;
960 
961   m_noOfAutoIncColumns = org.m_noOfAutoIncColumns;
962 
963   m_id = org.m_id;
964   m_version = org.m_version;
965   m_status = org.m_status;
966 
967   m_max_rows = org.m_max_rows;
968   m_min_rows = org.m_min_rows;
969 
970   m_tablespace_name = org.m_tablespace_name;
971   m_tablespace_id= org.m_tablespace_id;
972   m_tablespace_version = org.m_tablespace_version;
973   m_storageType = org.m_storageType;
974 
975   DBUG_RETURN(0);
976 }
977 
setName(const char * name)978 int NdbTableImpl::setName(const char * name)
979 {
980   return !m_externalName.assign(name);
981 }
982 
983 const char *
getName() const984 NdbTableImpl::getName() const
985 {
986   return m_externalName.c_str();
987 }
988 
989 int
getDbName(char buf[],size_t len) const990 NdbTableImpl::getDbName(char buf[], size_t len) const
991 {
992   if (len == 0)
993     return -1;
994 
995   // db/schema/table
996   const char *ptr = m_internalName.c_str();
997 
998   size_t pos = 0;
999   while (ptr[pos] && ptr[pos] != table_name_separator)
1000   {
1001     buf[pos] = ptr[pos];
1002     pos++;
1003 
1004     if (pos == len)
1005       return -1;
1006   }
1007   buf[pos] = 0;
1008   return 0;
1009 }
1010 
1011 int
getSchemaName(char buf[],size_t len) const1012 NdbTableImpl::getSchemaName(char buf[], size_t len) const
1013 {
1014   if (len == 0)
1015     return -1;
1016 
1017   // db/schema/table
1018   const char *ptr = m_internalName.c_str();
1019 
1020   // skip over "db"
1021   while (*ptr && *ptr != table_name_separator)
1022     ptr++;
1023 
1024   buf[0] = 0;
1025   if (*ptr == table_name_separator)
1026   {
1027     ptr++;
1028     size_t pos = 0;
1029     while (ptr[pos] && ptr[pos] != table_name_separator)
1030     {
1031       buf[pos] = ptr[pos];
1032       pos++;
1033 
1034       if (pos == len)
1035         return -1;
1036     }
1037     buf[pos] = 0;
1038   }
1039 
1040   return 0;
1041 }
1042 
1043 void
setDbSchema(const char * db,const char * schema)1044 NdbTableImpl::setDbSchema(const char * db, const char * schema)
1045 {
1046   m_internalName.assfmt("%s%c%s%c%s",
1047                         db,
1048                         table_name_separator,
1049                         schema,
1050                         table_name_separator,
1051                         m_externalName.c_str());
1052   updateMysqlName();
1053 }
1054 
1055 void
computeAggregates()1056 NdbTableImpl::computeAggregates()
1057 {
1058   m_noOfKeys = 0;
1059   m_keyLenInWords = 0;
1060   m_noOfDistributionKeys = 0;
1061   m_noOfBlobs = 0;
1062   m_noOfDiskColumns = 0;
1063   Uint32 i, n;
1064   for (i = 0; i < m_columns.size(); i++) {
1065     NdbColumnImpl* col = m_columns[i];
1066     if (col->m_pk) {
1067       m_noOfKeys++;
1068       m_keyLenInWords += (col->m_attrSize * col->m_arraySize + 3) / 4;
1069     }
1070     if (col->m_distributionKey)
1071       m_noOfDistributionKeys++; // XXX check PK
1072 
1073     if (col->getBlobType())
1074       m_noOfBlobs++;
1075 
1076     if (col->getStorageType() == NdbDictionary::Column::StorageTypeDisk)
1077       m_noOfDiskColumns++;
1078 
1079     col->m_keyInfoPos = ~0;
1080 
1081     if (col->m_autoIncrement)
1082       m_noOfAutoIncColumns++;
1083   }
1084   if (m_noOfDistributionKeys == m_noOfKeys) {
1085     // all is none!
1086     m_noOfDistributionKeys = 0;
1087   }
1088 
1089   if (m_noOfDistributionKeys == 0)
1090   {
1091     // none is all!
1092     for (i = 0, n = m_noOfKeys; n != 0; i++) {
1093       NdbColumnImpl* col = m_columns[i];
1094       if (col->m_pk) {
1095         col->m_distributionKey = true;
1096         n--;
1097       }
1098     }
1099   }
1100 
1101   Uint32 keyInfoPos = 0;
1102   for (i = 0, n = m_noOfKeys; n != 0; i++) {
1103     NdbColumnImpl* col = m_columns[i];
1104     if (col->m_pk) {
1105       col->m_keyInfoPos = keyInfoPos++;
1106       n--;
1107     }
1108   }
1109 }
1110 
1111 // TODO add error checks
1112 // TODO use these internally at create and retrieve
1113 int
aggregate(NdbError & error)1114 NdbTableImpl::aggregate(NdbError& error)
1115 {
1116   computeAggregates();
1117   return 0;
1118 }
1119 int
validate(NdbError & error)1120 NdbTableImpl::validate(NdbError& error)
1121 {
1122   if (aggregate(error) == -1)
1123     return -1;
1124   return 0;
1125 }
1126 
1127 void
setFragmentCount(Uint32 count)1128 NdbTableImpl::setFragmentCount(Uint32 count)
1129 {
1130   m_fragmentCount= count;
1131 }
1132 
getFragmentCount() const1133 Uint32 NdbTableImpl::getFragmentCount() const
1134 {
1135   return m_fragmentCount;
1136 }
1137 
setFrm(const void * data,Uint32 len)1138 int NdbTableImpl::setFrm(const void* data, Uint32 len)
1139 {
1140   return m_frm.assign(data, len);
1141 }
1142 
1143 const void *
getFrmData() const1144 NdbTableImpl::getFrmData() const
1145 {
1146   return m_frm.get_data();
1147 }
1148 
1149 Uint32
getFrmLength() const1150 NdbTableImpl::getFrmLength() const
1151 {
1152   return m_frm.length();
1153 }
1154 
1155 int
setFragmentData(const Uint32 * data,Uint32 cnt)1156 NdbTableImpl::setFragmentData(const Uint32* data, Uint32 cnt)
1157 {
1158   return m_fd.assign(data, cnt);
1159 }
1160 
1161 const Uint32 *
getFragmentData() const1162 NdbTableImpl::getFragmentData() const
1163 {
1164   return m_fd.getBase();
1165 }
1166 
1167 Uint32
getFragmentDataLen() const1168 NdbTableImpl::getFragmentDataLen() const
1169 {
1170   return m_fd.size();
1171 }
1172 
1173 int
setRangeListData(const Int32 * data,Uint32 len)1174 NdbTableImpl::setRangeListData(const Int32* data, Uint32 len)
1175 {
1176   return m_range.assign(data, len);
1177 }
1178 
1179 const Int32 *
getRangeListData() const1180 NdbTableImpl::getRangeListData() const
1181 {
1182   return m_range.getBase();
1183 }
1184 
1185 Uint32
getRangeListDataLen() const1186 NdbTableImpl::getRangeListDataLen() const
1187 {
1188   return m_range.size();
1189 }
1190 
1191 Uint32
getFragmentNodes(Uint32 fragmentId,Uint32 * nodeIdArrayPtr,Uint32 arraySize) const1192 NdbTableImpl::getFragmentNodes(Uint32 fragmentId,
1193                                Uint32* nodeIdArrayPtr,
1194                                Uint32 arraySize) const
1195 {
1196   const Uint16 *shortNodeIds;
1197   Uint32 nodeCount = get_nodes(fragmentId, &shortNodeIds);
1198 
1199   for(Uint32 i = 0;
1200       ((i < nodeCount) &&
1201        (i < arraySize));
1202       i++)
1203     nodeIdArrayPtr[i] = (Uint32) shortNodeIds[i];
1204 
1205   return nodeCount;
1206 }
1207 
1208 int
updateMysqlName()1209 NdbTableImpl::updateMysqlName()
1210 {
1211   Vector<BaseString> v;
1212   if (m_internalName.split(v,"/") == 3)
1213   {
1214     return !m_mysqlName.assfmt("%s/%s",v[0].c_str(),v[2].c_str());
1215   }
1216   return !m_mysqlName.assign("");
1217 }
1218 
1219 int
buildColumnHash()1220 NdbTableImpl::buildColumnHash(){
1221   const Uint32 size = m_columns.size();
1222   int i;
1223   for(i = 31; i >= 0; i--){
1224     if(((1 << i) & size) != 0){
1225       m_columnHashMask = (1 << (i + 1)) - 1;
1226       break;
1227     }
1228   }
1229 
1230   Vector<Uint32> hashValues;
1231   Vector<Vector<Uint32> > chains;
1232   if (chains.fill(size, hashValues))
1233   {
1234     return -1;
1235   }
1236   for(i = 0; i< (int) size; i++){
1237     Uint32 hv = Hash(m_columns[i]->getName()) & 0xFFFE;
1238     Uint32 bucket = hv & m_columnHashMask;
1239     bucket = (bucket < size ? bucket : bucket - size);
1240     assert(bucket < size);
1241     if (hashValues.push_back(hv) ||
1242         chains[bucket].push_back(i))
1243     {
1244       return -1;
1245     }
1246   }
1247 
1248   m_columnHash.clear();
1249   Uint32 tmp = 1;
1250   if (m_columnHash.fill((unsigned)size-1, tmp))   // Default no chaining
1251   {
1252     return -1;
1253   }
1254 
1255   Uint32 pos = 0; // In overflow vector
1256   for(i = 0; i< (int) size; i++){
1257     Uint32 sz = chains[i].size();
1258     if(sz == 1){
1259       Uint32 col = chains[i][0];
1260       Uint32 hv = hashValues[col];
1261       Uint32 bucket = hv & m_columnHashMask;
1262       bucket = (bucket < size ? bucket : bucket - size);
1263       m_columnHash[bucket] = (col << 16) | hv | 1;
1264     } else if(sz > 1){
1265       Uint32 col = chains[i][0];
1266       Uint32 hv = hashValues[col];
1267       Uint32 bucket = hv & m_columnHashMask;
1268       bucket = (bucket < size ? bucket : bucket - size);
1269       m_columnHash[bucket] = (sz << 16) | (((size - bucket) + pos) << 1);
1270       for(size_t j = 0; j<sz; j++, pos++){
1271 	Uint32 col = chains[i][j];
1272 	Uint32 hv = hashValues[col];
1273 	if (m_columnHash.push_back((col << 16) | hv))
1274         {
1275           return -1;
1276         }
1277       }
1278     }
1279   }
1280 
1281   if (m_columnHash.push_back(0)) // Overflow when looping in end of array
1282   {
1283     return -1;
1284   }
1285 
1286 #if 0
1287   for(size_t i = 0; i<m_columnHash.size(); i++){
1288     Uint32 tmp = m_columnHash[i];
1289     int col = -1;
1290     if(i < size && (tmp & 1) == 1){
1291       col = (tmp >> 16);
1292     } else if(i >= size){
1293       col = (tmp >> 16);
1294     }
1295     ndbout_c("m_columnHash[%d] %s = %x",
1296 	     i, col > 0 ? m_columns[col]->getName() : "" , m_columnHash[i]);
1297   }
1298 #endif
1299   return 0;
1300 }
1301 
1302 Uint32
get_nodes(Uint32 fragmentId,const Uint16 ** nodes) const1303 NdbTableImpl::get_nodes(Uint32 fragmentId, const Uint16 ** nodes) const
1304 {
1305   Uint32 pos = fragmentId * m_replicaCount;
1306   if (pos + m_replicaCount <= m_fragments.size())
1307   {
1308     *nodes = m_fragments.getBase()+pos;
1309     return m_replicaCount;
1310   }
1311   return 0;
1312 }
1313 
1314 int
checkColumns(const Uint32 * map,Uint32 len) const1315 NdbDictionary::Table::checkColumns(const Uint32* map, Uint32 len) const
1316 {
1317   int ret = 0;
1318   Uint32 colCnt = m_impl.m_columns.size();
1319   if (map == 0)
1320   {
1321     ret |= 1;
1322     ret |= (m_impl.m_noOfDiskColumns) ? 2 : 0;
1323     ret |= (colCnt > m_impl.m_noOfDiskColumns) ? 4 : 0;
1324     return ret;
1325   }
1326 
1327   NdbColumnImpl** cols = m_impl.m_columns.getBase();
1328   const char * ptr = reinterpret_cast<const char*>(map);
1329   const char * end = ptr + len;
1330   Uint32 no = 0;
1331   while (ptr < end)
1332   {
1333     Uint32 val = (Uint32)* ptr;
1334     Uint32 idx = 1;
1335     for (Uint32 i = 0; i<8; i++)
1336     {
1337       if (val & idx)
1338       {
1339 	if (cols[no]->getPrimaryKey())
1340 	  ret |= 1;
1341 	else
1342 	{
1343 	  if (cols[no]->getStorageType() == NdbDictionary::Column::StorageTypeDisk)
1344 	    ret |= 2;
1345 	  else
1346 	    ret |= 4;
1347 	}
1348       }
1349       no ++;
1350       idx *= 2;
1351       if (no == colCnt)
1352 	return ret;
1353     }
1354 
1355     ptr++;
1356   }
1357   return ret;
1358 }
1359 
1360 
1361 
1362 /**
1363  * NdbIndexImpl
1364  */
1365 
NdbIndexImpl()1366 NdbIndexImpl::NdbIndexImpl() :
1367   NdbDictionary::Index(* this),
1368   NdbDictObjectImpl(NdbDictionary::Object::OrderedIndex), m_facade(this)
1369 {
1370   init();
1371 }
1372 
NdbIndexImpl(NdbDictionary::Index & f)1373 NdbIndexImpl::NdbIndexImpl(NdbDictionary::Index & f) :
1374   NdbDictionary::Index(* this),
1375   NdbDictObjectImpl(NdbDictionary::Object::OrderedIndex), m_facade(&f)
1376 {
1377   init();
1378 }
1379 
init()1380 void NdbIndexImpl::init()
1381 {
1382   m_id= RNIL;
1383   m_type= NdbDictionary::Object::TypeUndefined;
1384   m_logging= true;
1385   m_temporary= false;
1386   m_table= NULL;
1387 }
1388 
~NdbIndexImpl()1389 NdbIndexImpl::~NdbIndexImpl(){
1390   for (unsigned i = 0; i < m_columns.size(); i++)
1391     delete m_columns[i];
1392 }
1393 
setName(const char * name)1394 int NdbIndexImpl::setName(const char * name)
1395 {
1396   return !m_externalName.assign(name);
1397 }
1398 
1399 const char *
getName() const1400 NdbIndexImpl::getName() const
1401 {
1402   return m_externalName.c_str();
1403 }
1404 
1405 int
setTable(const char * table)1406 NdbIndexImpl::setTable(const char * table)
1407 {
1408   return !m_tableName.assign(table);
1409 }
1410 
1411 const char *
getTable() const1412 NdbIndexImpl::getTable() const
1413 {
1414   return m_tableName.c_str();
1415 }
1416 
1417 const NdbTableImpl *
getIndexTable() const1418 NdbIndexImpl::getIndexTable() const
1419 {
1420   return m_table;
1421 }
1422 
1423 /**
1424  * NdbOptimizeTableHandleImpl
1425  */
1426 
NdbOptimizeTableHandleImpl(NdbDictionary::OptimizeTableHandle & f)1427 NdbOptimizeTableHandleImpl::NdbOptimizeTableHandleImpl(NdbDictionary::OptimizeTableHandle &f)
1428   : NdbDictionary::OptimizeTableHandle(* this),
1429     m_state(NdbOptimizeTableHandleImpl::CREATED),
1430     m_ndb(NULL), m_table(NULL),
1431     m_table_queue(NULL), m_table_queue_first(NULL), m_table_queue_end(NULL),
1432     m_trans(NULL), m_scan_op(NULL),
1433     m_facade(this)
1434 {
1435 }
1436 
~NdbOptimizeTableHandleImpl()1437 NdbOptimizeTableHandleImpl::~NdbOptimizeTableHandleImpl()
1438 {
1439   DBUG_ENTER("NdbOptimizeTableHandleImpl::~NdbOptimizeTableHandleImpl");
1440   close();
1441   DBUG_VOID_RETURN;
1442 }
1443 
start()1444 int NdbOptimizeTableHandleImpl::start()
1445 {
1446   int noRetries = 100;
1447   DBUG_ENTER("NdbOptimizeTableImpl::start");
1448 
1449   if (m_table_queue)
1450   {
1451     const NdbTableImpl * table = m_table_queue->table;
1452 
1453     /*
1454      * Start/Restart transaction
1455      */
1456     while (noRetries-- > 0)
1457     {
1458       if (m_trans && (m_trans->restart() != 0))
1459       {
1460         m_ndb->closeTransaction(m_trans);
1461         m_trans = NULL;
1462       }
1463       else
1464         m_trans = m_ndb->startTransaction();
1465       if (!m_trans)
1466       {
1467         if (noRetries == 0)
1468           goto do_error;
1469         continue;
1470       }
1471 
1472       /*
1473        * Get first scan operation
1474        */
1475       if ((m_scan_op = m_trans->getNdbScanOperation(table->m_facade))
1476           == NULL)
1477       {
1478         m_ndb->getNdbError(m_trans->getNdbError().code);
1479         goto do_error;
1480       }
1481 
1482       /**
1483        * Define a result set for the scan.
1484        */
1485       if (m_scan_op->readTuples(NdbOperation::LM_Exclusive)) {
1486         m_ndb->getNdbError(m_trans->getNdbError().code);
1487         goto do_error;
1488       }
1489 
1490       /**
1491        * Start scan    (NoCommit since we are only reading at this stage);
1492        */
1493       if (m_trans->execute(NdbTransaction::NoCommit) != 0) {
1494         if (m_trans->getNdbError().status == NdbError::TemporaryError)
1495           continue;  /* goto next_retry */
1496         m_ndb->getNdbError(m_trans->getNdbError().code);
1497         goto do_error;
1498       }
1499       break;
1500     } // while (noRetries-- > 0)
1501     m_state = NdbOptimizeTableHandleImpl::INITIALIZED;
1502   } // if (m_table_queue)
1503   else
1504     m_state = NdbOptimizeTableHandleImpl::FINISHED;
1505 
1506   DBUG_RETURN(0);
1507 do_error:
1508   DBUG_PRINT("info", ("NdbOptimizeTableImpl::start aborted"));
1509   m_state = NdbOptimizeTableHandleImpl::ABORTED;
1510   DBUG_RETURN(-1);
1511 }
1512 
init(Ndb * ndb,const NdbTableImpl & table)1513 int NdbOptimizeTableHandleImpl::init(Ndb* ndb, const NdbTableImpl &table)
1514 {
1515   DBUG_ENTER("NdbOptimizeTableHandleImpl::init");
1516   NdbDictionary::Dictionary* dict = ndb->getDictionary();
1517   Uint32 sz = table.m_columns.size();
1518   bool found_varpart = false;
1519   int blob_num = table.m_noOfBlobs;
1520 
1521   m_ndb = ndb;
1522   m_table = &table;
1523 
1524   /**
1525    * search whether there are var size columns in the table,
1526    * in first step, we only optimize var part, then if the
1527    * table has no var size columns, we do not do optimizing
1528    */
1529   for (Uint32 i = 0; i < sz; i++) {
1530     const NdbColumnImpl *col = m_table->m_columns[i];
1531     if (col != 0 && col->m_storageType == NDB_STORAGETYPE_MEMORY &&
1532         (col->m_dynamic || col->m_arrayType != NDB_ARRAYTYPE_FIXED)) {
1533       found_varpart= true;
1534       break;
1535     }
1536   }
1537   if (!found_varpart)
1538   {
1539     m_state = NdbOptimizeTableHandleImpl::FINISHED;
1540     DBUG_RETURN(0);
1541   }
1542 
1543   /*
1544    * Add main table to the table queue
1545    * to optimize
1546    */
1547   m_table_queue_end = new fifo_element_st(m_table, m_table_queue_end);
1548   m_table_queue = m_table_queue_first = m_table_queue_end;
1549   /*
1550    * Add any BLOB tables the table queue
1551    * to optimize.
1552    */
1553   for (int i = m_table->m_columns.size(); i > 0 && blob_num > 0;) {
1554     i--;
1555     NdbColumnImpl & c = *m_table->m_columns[i];
1556     if (! c.getBlobType() || c.getPartSize() == 0)
1557       continue;
1558 
1559     blob_num--;
1560     const NdbTableImpl * blob_table =
1561       (const NdbTableImpl *)dict->getBlobTable(m_table, c.m_attrId);
1562     if (blob_table)
1563     {
1564       m_table_queue_end = new fifo_element_st(blob_table, m_table_queue_end);
1565     }
1566   }
1567   /*
1568    * Initialize transaction
1569    */
1570   DBUG_RETURN(start());
1571 }
1572 
next()1573 int NdbOptimizeTableHandleImpl::next()
1574 {
1575   int noRetries = 100;
1576   int done, check;
1577   DBUG_ENTER("NdbOptimizeTableHandleImpl::next");
1578 
1579   if (m_state == NdbOptimizeTableHandleImpl::FINISHED)
1580     DBUG_RETURN(0);
1581   else if (m_state != NdbOptimizeTableHandleImpl::INITIALIZED)
1582     DBUG_RETURN(-1);
1583 
1584   while (noRetries-- > 0)
1585   {
1586     if ((done = check = m_scan_op->nextResult(true)) == 0)
1587     {
1588       do
1589       {
1590         /**
1591          * Get update operation
1592          */
1593         NdbOperation * myUpdateOp = m_scan_op->updateCurrentTuple();
1594         if (myUpdateOp == 0)
1595         {
1596           m_ndb->getNdbError(m_trans->getNdbError().code);
1597           goto do_error;
1598         }
1599         /**
1600          * optimize a tuple through doing the update
1601          * first step, move varpart
1602          */
1603         Uint32 options = 0 | AttributeHeader::OPTIMIZE_MOVE_VARPART;
1604         myUpdateOp->setOptimize(options);
1605         /**
1606          * nextResult(false) means that the records
1607          * cached in the NDBAPI are modified before
1608          * fetching more rows from NDB.
1609          */
1610       } while ((check = m_scan_op->nextResult(false)) == 0);
1611     }
1612 
1613     /**
1614      * Commit when all cached tuple have been updated
1615      */
1616     if (check != -1)
1617       check = m_trans->execute(NdbTransaction::Commit);
1618 
1619     if (done == 1)
1620     {
1621       DBUG_PRINT("info", ("Done with table %s",
1622                           m_table_queue->table->getName()));
1623       /*
1624        * We are done with optimizing current table
1625        * move to next
1626        */
1627       fifo_element_st *current = m_table_queue;
1628       m_table_queue = current->next;
1629       /*
1630        * Start scan of next table
1631        */
1632       if (start() != 0) {
1633         m_ndb->getNdbError(m_trans->getNdbError().code);
1634         goto do_error;
1635       }
1636       DBUG_RETURN(1);
1637     }
1638     if (check == -1)
1639     {
1640       if (m_trans->getNdbError().status == NdbError::TemporaryError)
1641       {
1642         /*
1643          * If we encountered temporary error, retry
1644          */
1645         m_ndb->closeTransaction(m_trans);
1646         m_trans = NULL;
1647         if (start() != 0) {
1648           m_ndb->getNdbError(m_trans->getNdbError().code);
1649           goto do_error;
1650         }
1651         continue; //retry
1652       }
1653       m_ndb->getNdbError(m_trans->getNdbError().code);
1654       goto do_error;
1655     }
1656     if (m_trans->restart() != 0)
1657     {
1658       DBUG_PRINT("info", ("Failed to restart transaction"));
1659       m_ndb->closeTransaction(m_trans);
1660       m_trans = NULL;
1661       if (start() != 0) {
1662         m_ndb->getNdbError(m_trans->getNdbError().code);
1663         goto do_error;
1664       }
1665     }
1666 
1667     DBUG_RETURN(1);
1668   }
1669 do_error:
1670   DBUG_PRINT("info", ("NdbOptimizeTableHandleImpl::next aborted"));
1671   m_state = NdbOptimizeTableHandleImpl::ABORTED;
1672   DBUG_RETURN(-1);
1673 }
1674 
close()1675 int NdbOptimizeTableHandleImpl::close()
1676 {
1677   DBUG_ENTER("NdbOptimizeTableHandleImpl::close");
1678   /*
1679    * Drop queued tables
1680    */
1681   while(m_table_queue_first != NULL)
1682   {
1683     fifo_element_st *next = m_table_queue_first->next;
1684     delete m_table_queue_first;
1685     m_table_queue_first = next;
1686   }
1687   m_table_queue = m_table_queue_first = m_table_queue_end = NULL;
1688   if (m_trans)
1689   {
1690     m_ndb->closeTransaction(m_trans);
1691     m_trans = NULL;
1692   }
1693   m_state = NdbOptimizeTableHandleImpl::CLOSED;
1694   DBUG_RETURN(0);
1695 }
1696 
1697 /**
1698  * NdbOptimizeIndexHandleImpl
1699  */
1700 
NdbOptimizeIndexHandleImpl(NdbDictionary::OptimizeIndexHandle & f)1701 NdbOptimizeIndexHandleImpl::NdbOptimizeIndexHandleImpl(NdbDictionary::OptimizeIndexHandle &f)
1702   : NdbDictionary::OptimizeIndexHandle(* this),
1703     m_state(NdbOptimizeIndexHandleImpl::CREATED),
1704     m_ndb(NULL), m_index(NULL),
1705     m_facade(this)
1706 {
1707   DBUG_ENTER("NdbOptimizeIndexHandleImpl::NdbOptimizeIndexHandleImpl");
1708   DBUG_VOID_RETURN;
1709 }
1710 
~NdbOptimizeIndexHandleImpl()1711 NdbOptimizeIndexHandleImpl::~NdbOptimizeIndexHandleImpl()
1712 {
1713   DBUG_ENTER("NdbOptimizeIndexHandleImpl::~NdbOptimizeIndexHandleImpl");
1714   DBUG_VOID_RETURN;
1715 }
1716 
init(Ndb * ndb,const NdbIndexImpl & index)1717 int NdbOptimizeIndexHandleImpl::init(Ndb *ndb, const NdbIndexImpl &index)
1718 {
1719   DBUG_ENTER("NdbOptimizeIndexHandleImpl::init");
1720   m_index = &index;
1721   m_state = NdbOptimizeIndexHandleImpl::INITIALIZED;
1722   /**
1723    * NOTE: we only optimize unique index
1724    */
1725   if (m_index->m_facade->getType() != NdbDictionary::Index::UniqueHashIndex)
1726     DBUG_RETURN(0);
1727   DBUG_RETURN(m_optimize_table_handle.m_impl.init(ndb, *index.getIndexTable()));
1728 }
1729 
next()1730 int NdbOptimizeIndexHandleImpl::next()
1731 {
1732   DBUG_ENTER("NdbOptimizeIndexHandleImpl::next");
1733   if (m_state != NdbOptimizeIndexHandleImpl::INITIALIZED)
1734     DBUG_RETURN(0);
1735   if (m_index->m_facade->getType() != NdbDictionary::Index::UniqueHashIndex)
1736     DBUG_RETURN(0);
1737   DBUG_RETURN(m_optimize_table_handle.m_impl.next());
1738 }
1739 
close()1740 int NdbOptimizeIndexHandleImpl::close()
1741 {
1742   DBUG_ENTER("NdbOptimizeIndexHandleImpl::close");
1743   m_state = NdbOptimizeIndexHandleImpl::CLOSED;
1744   if (m_index &&
1745       m_index->m_facade->getType() == NdbDictionary::Index::UniqueHashIndex)
1746     DBUG_RETURN(m_optimize_table_handle.m_impl.close());
1747 
1748   DBUG_RETURN(0);
1749 }
1750 
1751 /**
1752  * NdbEventImpl
1753  */
1754 
NdbEventImpl()1755 NdbEventImpl::NdbEventImpl() :
1756   NdbDictionary::Event(* this),
1757   NdbDictObjectImpl(NdbDictionary::Object::TypeUndefined), m_facade(this)
1758 {
1759   DBUG_ENTER("NdbEventImpl::NdbEventImpl");
1760   DBUG_PRINT("info", ("this: %p", this));
1761   init();
1762   DBUG_VOID_RETURN;
1763 }
1764 
NdbEventImpl(NdbDictionary::Event & f)1765 NdbEventImpl::NdbEventImpl(NdbDictionary::Event & f) :
1766   NdbDictionary::Event(* this),
1767   NdbDictObjectImpl(NdbDictionary::Object::TypeUndefined), m_facade(&f)
1768 {
1769   DBUG_ENTER("NdbEventImpl::NdbEventImpl");
1770   DBUG_PRINT("info", ("this: %p", this));
1771   init();
1772   DBUG_VOID_RETURN;
1773 }
1774 
init()1775 void NdbEventImpl::init()
1776 {
1777   m_eventId= RNIL;
1778   m_eventKey= RNIL;
1779   mi_type= 0;
1780   m_dur= NdbDictionary::Event::ED_UNDEFINED;
1781   m_mergeEvents = false;
1782   m_tableImpl= NULL;
1783   m_rep= NdbDictionary::Event::ER_UPDATED;
1784 }
1785 
~NdbEventImpl()1786 NdbEventImpl::~NdbEventImpl()
1787 {
1788   DBUG_ENTER("NdbEventImpl::~NdbEventImpl");
1789   DBUG_PRINT("info", ("this: %p", this));
1790   for (unsigned i = 0; i < m_columns.size(); i++)
1791     delete  m_columns[i];
1792   if (m_tableImpl)
1793     delete m_tableImpl;
1794   DBUG_VOID_RETURN;
1795 }
1796 
setName(const char * name)1797 int NdbEventImpl::setName(const char * name)
1798 {
1799   return !m_name.assign(name);
1800 }
1801 
getName() const1802 const char *NdbEventImpl::getName() const
1803 {
1804   return m_name.c_str();
1805 }
1806 
1807 int
setTable(const NdbDictionary::Table & table)1808 NdbEventImpl::setTable(const NdbDictionary::Table& table)
1809 {
1810   setTable(&NdbTableImpl::getImpl(table));
1811   return !m_tableName.assign(m_tableImpl->getName());
1812 }
1813 
1814 void
setTable(NdbTableImpl * tableImpl)1815 NdbEventImpl::setTable(NdbTableImpl *tableImpl)
1816 {
1817   DBUG_ENTER("NdbEventImpl::setTable");
1818   DBUG_PRINT("info", ("this: %p  tableImpl: %p", this, tableImpl));
1819 
1820   if (!m_tableImpl)
1821     m_tableImpl = new NdbTableImpl();
1822   // Copy table, since event might be accessed from different threads
1823   m_tableImpl->assign(*tableImpl);
1824   DBUG_VOID_RETURN;
1825 }
1826 
1827 const NdbDictionary::Table *
getTable() const1828 NdbEventImpl::getTable() const
1829 {
1830   if (m_tableImpl)
1831     return m_tableImpl->m_facade;
1832   else
1833     return NULL;
1834 }
1835 
1836 int
setTable(const char * table)1837 NdbEventImpl::setTable(const char * table)
1838 {
1839   return !m_tableName.assign(table);
1840 }
1841 
1842 const char *
getTableName() const1843 NdbEventImpl::getTableName() const
1844 {
1845   return m_tableName.c_str();
1846 }
1847 
1848 void
addTableEvent(const NdbDictionary::Event::TableEvent t=NdbDictionary::Event::TE_ALL)1849 NdbEventImpl::addTableEvent(const NdbDictionary::Event::TableEvent t =  NdbDictionary::Event::TE_ALL)
1850 {
1851   mi_type |= (unsigned)t;
1852 }
1853 
1854 bool
getTableEvent(const NdbDictionary::Event::TableEvent t) const1855 NdbEventImpl::getTableEvent(const NdbDictionary::Event::TableEvent t) const
1856 {
1857   return (mi_type & (unsigned)t) == (unsigned)t;
1858 }
1859 
1860 void
setDurability(NdbDictionary::Event::EventDurability d)1861 NdbEventImpl::setDurability(NdbDictionary::Event::EventDurability d)
1862 {
1863   m_dur = d;
1864 }
1865 
1866 NdbDictionary::Event::EventDurability
getDurability() const1867 NdbEventImpl::getDurability() const
1868 {
1869   return m_dur;
1870 }
1871 
1872 void
setReport(NdbDictionary::Event::EventReport r)1873 NdbEventImpl::setReport(NdbDictionary::Event::EventReport r)
1874 {
1875   m_rep = r;
1876 }
1877 
1878 NdbDictionary::Event::EventReport
getReport() const1879 NdbEventImpl::getReport() const
1880 {
1881   return m_rep;
1882 }
1883 
getNoOfEventColumns() const1884 int NdbEventImpl::getNoOfEventColumns() const
1885 {
1886   return m_attrIds.size() + m_columns.size();
1887 }
1888 
1889 const NdbDictionary::Column *
getEventColumn(unsigned no) const1890 NdbEventImpl::getEventColumn(unsigned no) const
1891 {
1892   if (m_columns.size())
1893   {
1894     if (no < m_columns.size())
1895     {
1896       return m_columns[no];
1897     }
1898   }
1899   else if (m_attrIds.size())
1900   {
1901     if (no < m_attrIds.size())
1902     {
1903       NdbTableImpl* tab= m_tableImpl;
1904       if (tab == 0)
1905         return 0;
1906       return tab->getColumn(m_attrIds[no]);
1907     }
1908   }
1909   return 0;
1910 }
1911 
1912 /**
1913  * NdbDictionaryImpl
1914  */
1915 
1916 /* Initialise static */
1917 const Uint32
1918 NdbDictionaryImpl::m_emptyMask[MAXNROFATTRIBUTESINWORDS]= {0,0,0,0};
1919 
NdbDictionaryImpl(Ndb & ndb)1920 NdbDictionaryImpl::NdbDictionaryImpl(Ndb &ndb)
1921   : NdbDictionary::Dictionary(* this),
1922     m_facade(this),
1923     m_receiver(m_tx, m_error, m_warn),
1924     m_ndb(ndb)
1925 {
1926   m_globalHash = 0;
1927   m_local_table_data_size= 0;
1928 #ifdef VM_TRACE
1929   STATIC_ASSERT(
1930     (int)WarnUndobufferRoundUp == (int)CreateFilegroupConf::WarnUndobufferRoundUp &&
1931     (int)WarnUndofileRoundDown == (int)CreateFileConf::WarnUndofileRoundDown &&
1932     (int)WarnExtentRoundUp == (int)CreateFilegroupConf::WarnExtentRoundUp &&
1933     (int)WarnDatafileRoundDown == (int)CreateFileConf::WarnDatafileRoundDown &&
1934     (int)WarnDatafileRoundUp == (int)CreateFileConf::WarnDatafileRoundUp
1935   );
1936 #endif
1937 }
1938 
NdbDictionaryImpl(Ndb & ndb,NdbDictionary::Dictionary & f)1939 NdbDictionaryImpl::NdbDictionaryImpl(Ndb &ndb,
1940 				     NdbDictionary::Dictionary & f)
1941   : NdbDictionary::Dictionary(* this),
1942     m_facade(&f),
1943     m_receiver(m_tx, m_error, m_warn),
1944     m_ndb(ndb)
1945 {
1946   m_globalHash = 0;
1947   m_local_table_data_size= 0;
1948 }
1949 
~NdbDictionaryImpl()1950 NdbDictionaryImpl::~NdbDictionaryImpl()
1951 {
1952   /* Release local table references back to the global cache */
1953   NdbElement_t<Ndb_local_table_info> * curr = m_localHash.m_tableHash.getNext(0);
1954   if(m_globalHash){
1955     while(curr != 0){
1956       m_globalHash->lock();
1957       m_globalHash->release(curr->theData->m_table_impl);
1958       Ndb_local_table_info::destroy(curr->theData);
1959       m_globalHash->unlock();
1960 
1961       curr = m_localHash.m_tableHash.getNext(curr);
1962     }
1963   } else {
1964     assert(curr == 0);
1965   }
1966 }
1967 
1968 NdbTableImpl *
fetchGlobalTableImplRef(const GlobalCacheInitObject & obj)1969 NdbDictionaryImpl::fetchGlobalTableImplRef(const GlobalCacheInitObject &obj)
1970 {
1971   DBUG_ENTER("fetchGlobalTableImplRef");
1972   NdbTableImpl *impl;
1973   int error= 0;
1974 
1975   m_globalHash->lock();
1976   impl = m_globalHash->get(obj.m_name.c_str(), &error);
1977   m_globalHash->unlock();
1978 
1979   if (impl == 0){
1980     if (error == 0)
1981       impl = m_receiver.getTable(obj.m_name,
1982                                  m_ndb.usingFullyQualifiedNames());
1983     else
1984       m_error.code = 4000;
1985     if (impl != 0 && (obj.init(this, *impl)))
1986     {
1987       delete impl;
1988       impl = 0;
1989     }
1990     m_globalHash->lock();
1991     m_globalHash->put(obj.m_name.c_str(), impl);
1992     m_globalHash->unlock();
1993   }
1994 
1995   DBUG_RETURN(impl);
1996 }
1997 
1998 void
putTable(NdbTableImpl * impl)1999 NdbDictionaryImpl::putTable(NdbTableImpl *impl)
2000 {
2001   NdbTableImpl *old;
2002 
2003   int ret = getBlobTables(*impl);
2004   int error = 0;
2005   assert(ret == 0);
2006 
2007   m_globalHash->lock();
2008   if ((old= m_globalHash->get(impl->m_internalName.c_str(), &error)))
2009   {
2010     m_globalHash->alter_table_rep(old->m_internalName.c_str(),
2011                                   impl->m_id,
2012                                   impl->m_version,
2013                                   FALSE);
2014   }
2015   m_globalHash->put(impl->m_internalName.c_str(), impl);
2016   m_globalHash->unlock();
2017   Ndb_local_table_info *info=
2018     Ndb_local_table_info::create(impl, m_local_table_data_size);
2019 
2020   m_localHash.put(impl->m_internalName.c_str(), info);
2021 }
2022 
2023 int
getBlobTables(NdbTableImpl & t)2024 NdbDictionaryImpl::getBlobTables(NdbTableImpl &t)
2025 {
2026   unsigned n= t.m_noOfBlobs;
2027   DBUG_ENTER("NdbDictionaryImpl::getBlobTables");
2028   // optimized for blob column being the last one
2029   // and not looking for more than one if not neccessary
2030   for (unsigned i = t.m_columns.size(); i > 0 && n > 0;) {
2031     i--;
2032     NdbColumnImpl & c = *t.m_columns[i];
2033     if (! c.getBlobType() || c.getPartSize() == 0)
2034       continue;
2035     n--;
2036     // retrieve blob table def from DICT - by-pass cache
2037     char btname[NdbBlobImpl::BlobTableNameSize];
2038     NdbBlob::getBlobTableName(btname, &t, &c);
2039     BaseString btname_internal = m_ndb.internalize_table_name(btname);
2040     NdbTableImpl* bt =
2041       m_receiver.getTable(btname_internal, m_ndb.usingFullyQualifiedNames());
2042     if (bt == NULL)
2043     {
2044       if (ignore_broken_blob_tables())
2045       {
2046         DBUG_PRINT("info", ("Blob table %s not found, continuing", btname));
2047         continue;
2048       }
2049       DBUG_RETURN(-1);
2050     }
2051 
2052     // TODO check primary id/version when returned by DICT
2053 
2054     // the blob column owns the blob table
2055     assert(c.m_blobTable == NULL);
2056     c.m_blobTable = bt;
2057 
2058     // change storage type to that of PART column
2059     const char* colName = c.m_blobVersion == 1 ? "DATA" : "NDB$DATA";
2060     const NdbColumnImpl* bc = bt->getColumn(colName);
2061     assert(bc != 0);
2062     assert(c.m_storageType == NDB_STORAGETYPE_MEMORY);
2063     c.m_storageType = bc->m_storageType;
2064   }
2065   DBUG_RETURN(0);
2066 }
2067 
2068 NdbTableImpl*
getBlobTable(const NdbTableImpl & tab,uint col_no)2069 NdbDictionaryImpl::getBlobTable(const NdbTableImpl& tab, uint col_no)
2070 {
2071   if (col_no < tab.m_columns.size()) {
2072     NdbColumnImpl* col = tab.m_columns[col_no];
2073     if (col != NULL) {
2074       NdbTableImpl* bt = col->m_blobTable;
2075       if (bt != NULL)
2076         return bt;
2077       else
2078         m_error.code = 4273; // No blob table..
2079     } else
2080       m_error.code = 4249; // Invalid table..
2081   } else
2082     m_error.code = 4318; // Invalid attribute..
2083   return NULL;
2084 }
2085 
2086 NdbTableImpl*
getBlobTable(uint tab_id,uint col_no)2087 NdbDictionaryImpl::getBlobTable(uint tab_id, uint col_no)
2088 {
2089   DBUG_ENTER("NdbDictionaryImpl::getBlobTable");
2090   DBUG_PRINT("enter", ("tab_id: %u col_no %u", tab_id, col_no));
2091 
2092   NdbTableImpl* tab = m_receiver.getTable(tab_id,
2093                                           m_ndb.usingFullyQualifiedNames());
2094   if (tab == NULL)
2095     DBUG_RETURN(NULL);
2096   Ndb_local_table_info* info =
2097     get_local_table_info(tab->m_internalName);
2098   delete tab;
2099   if (info == NULL)
2100     DBUG_RETURN(NULL);
2101   NdbTableImpl* bt = getBlobTable(*info->m_table_impl, col_no);
2102   DBUG_RETURN(bt);
2103 }
2104 
2105 bool
setTransporter(class Ndb * ndb,class TransporterFacade * tf)2106 NdbDictionaryImpl::setTransporter(class Ndb* ndb,
2107 				  class TransporterFacade * tf)
2108 {
2109   m_globalHash = tf->m_globalDictCache;
2110   if(m_receiver.setTransporter(ndb)){
2111     return true;
2112   }
2113   return false;
2114 }
2115 
2116 NdbTableImpl *
getIndexTable(NdbIndexImpl * index,NdbTableImpl * table)2117 NdbDictionaryImpl::getIndexTable(NdbIndexImpl * index,
2118 				 NdbTableImpl * table)
2119 {
2120   const char *current_db= m_ndb.getDatabaseName();
2121   NdbTableImpl *index_table;
2122   const BaseString internalName(
2123     m_ndb.internalize_index_name(table, index->getName()));
2124   // Get index table in system database
2125   m_ndb.setDatabaseName(NDB_SYSTEM_DATABASE);
2126   index_table= getTable(m_ndb.externalizeTableName(internalName.c_str()));
2127   m_ndb.setDatabaseName(current_db);
2128   if (!index_table)
2129   {
2130     // Index table not found
2131     // Try geting index table in current database (old format)
2132     index_table= getTable(m_ndb.externalizeTableName(internalName.c_str()));
2133   }
2134   return index_table;
2135 }
2136 
2137 bool
setTransporter(class Ndb * ndb)2138 NdbDictInterface::setTransporter(class Ndb* ndb)
2139 {
2140   m_reference = ndb->getReference();
2141   m_impl = ndb->theImpl;
2142 
2143   return true;
2144 }
2145 
2146 TransporterFacade *
getTransporter() const2147 NdbDictInterface::getTransporter() const
2148 {
2149   return m_impl->m_transporter_facade;
2150 }
2151 
~NdbDictInterface()2152 NdbDictInterface::~NdbDictInterface()
2153 {
2154 }
2155 
2156 void
execSignal(void * dictImpl,const class NdbApiSignal * signal,const struct LinearSectionPtr ptr[3])2157 NdbDictInterface::execSignal(void* dictImpl,
2158 			     const class NdbApiSignal* signal,
2159 			     const struct LinearSectionPtr ptr[3])
2160 {
2161   NdbDictInterface * tmp = (NdbDictInterface*)dictImpl;
2162 
2163   const Uint32 gsn = signal->readSignalNumber();
2164   switch(gsn){
2165   case GSN_GET_TABINFOREF:
2166     tmp->execGET_TABINFO_REF(signal, ptr);
2167     break;
2168   case GSN_GET_TABINFO_CONF:
2169     tmp->execGET_TABINFO_CONF(signal, ptr);
2170     break;
2171   case GSN_CREATE_TABLE_REF:
2172     tmp->execCREATE_TABLE_REF(signal, ptr);
2173     break;
2174   case GSN_CREATE_TABLE_CONF:
2175     tmp->execCREATE_TABLE_CONF(signal, ptr);
2176     break;
2177   case GSN_DROP_TABLE_REF:
2178     tmp->execDROP_TABLE_REF(signal, ptr);
2179     break;
2180   case GSN_DROP_TABLE_CONF:
2181     tmp->execDROP_TABLE_CONF(signal, ptr);
2182     break;
2183   case GSN_ALTER_TABLE_REF:
2184     tmp->execALTER_TABLE_REF(signal, ptr);
2185     break;
2186   case GSN_ALTER_TABLE_CONF:
2187     tmp->execALTER_TABLE_CONF(signal, ptr);
2188     break;
2189   case GSN_CREATE_INDX_REF:
2190     tmp->execCREATE_INDX_REF(signal, ptr);
2191     break;
2192   case GSN_CREATE_INDX_CONF:
2193     tmp->execCREATE_INDX_CONF(signal, ptr);
2194     break;
2195   case GSN_DROP_INDX_REF:
2196     tmp->execDROP_INDX_REF(signal, ptr);
2197     break;
2198   case GSN_DROP_INDX_CONF:
2199     tmp->execDROP_INDX_CONF(signal, ptr);
2200     break;
2201   case GSN_INDEX_STAT_CONF:
2202     tmp->execINDEX_STAT_CONF(signal, ptr);
2203     break;
2204   case GSN_INDEX_STAT_REF:
2205     tmp->execINDEX_STAT_REF(signal, ptr);
2206     break;
2207   case GSN_CREATE_EVNT_REF:
2208     tmp->execCREATE_EVNT_REF(signal, ptr);
2209     break;
2210   case GSN_CREATE_EVNT_CONF:
2211     tmp->execCREATE_EVNT_CONF(signal, ptr);
2212     break;
2213   case GSN_SUB_START_CONF:
2214     tmp->execSUB_START_CONF(signal, ptr);
2215     break;
2216   case GSN_SUB_START_REF:
2217     tmp->execSUB_START_REF(signal, ptr);
2218     break;
2219   case GSN_SUB_STOP_CONF:
2220     tmp->execSUB_STOP_CONF(signal, ptr);
2221     break;
2222   case GSN_SUB_STOP_REF:
2223     tmp->execSUB_STOP_REF(signal, ptr);
2224     break;
2225   case GSN_DROP_EVNT_REF:
2226     tmp->execDROP_EVNT_REF(signal, ptr);
2227     break;
2228   case GSN_DROP_EVNT_CONF:
2229     tmp->execDROP_EVNT_CONF(signal, ptr);
2230     break;
2231   case GSN_LIST_TABLES_CONF:
2232     tmp->execLIST_TABLES_CONF(signal, ptr);
2233     break;
2234   case GSN_CREATE_FILEGROUP_REF:
2235     tmp->execCREATE_FILEGROUP_REF(signal, ptr);
2236     break;
2237   case GSN_CREATE_FILEGROUP_CONF:
2238     tmp->execCREATE_FILEGROUP_CONF(signal, ptr);
2239     break;
2240   case GSN_CREATE_FILE_REF:
2241     tmp->execCREATE_FILE_REF(signal, ptr);
2242     break;
2243   case GSN_CREATE_FILE_CONF:
2244     tmp->execCREATE_FILE_CONF(signal, ptr);
2245     break;
2246   case GSN_DROP_FILEGROUP_REF:
2247     tmp->execDROP_FILEGROUP_REF(signal, ptr);
2248     break;
2249   case GSN_DROP_FILEGROUP_CONF:
2250     tmp->execDROP_FILEGROUP_CONF(signal, ptr);
2251     break;
2252   case GSN_DROP_FILE_REF:
2253     tmp->execDROP_FILE_REF(signal, ptr);
2254     break;
2255   case GSN_DROP_FILE_CONF:
2256     tmp->execDROP_FILE_CONF(signal, ptr);
2257     break;
2258   case GSN_SCHEMA_TRANS_BEGIN_CONF:
2259     tmp->execSCHEMA_TRANS_BEGIN_CONF(signal, ptr);
2260     break;
2261   case GSN_SCHEMA_TRANS_BEGIN_REF:
2262     tmp->execSCHEMA_TRANS_BEGIN_REF(signal, ptr);
2263     break;
2264   case GSN_SCHEMA_TRANS_END_CONF:
2265     tmp->execSCHEMA_TRANS_END_CONF(signal, ptr);
2266     break;
2267   case GSN_SCHEMA_TRANS_END_REF:
2268     tmp->execSCHEMA_TRANS_END_REF(signal, ptr);
2269     break;
2270   case GSN_SCHEMA_TRANS_END_REP:
2271     tmp->execSCHEMA_TRANS_END_REP(signal, ptr);
2272     break;
2273   case GSN_WAIT_GCP_CONF:
2274     tmp->execWAIT_GCP_CONF(signal, ptr);
2275     break;
2276   case GSN_WAIT_GCP_REF:
2277     tmp->execWAIT_GCP_REF(signal, ptr);
2278     break;
2279   case GSN_CREATE_HASH_MAP_REF:
2280     tmp->execCREATE_HASH_MAP_REF(signal, ptr);
2281     break;
2282   case GSN_CREATE_HASH_MAP_CONF:
2283     tmp->execCREATE_HASH_MAP_CONF(signal, ptr);
2284     break;
2285   case GSN_NODE_FAILREP:
2286   {
2287     const NodeFailRep *rep = CAST_CONSTPTR(NodeFailRep,
2288                                            signal->getDataPtr());
2289     for (Uint32 i = NdbNodeBitmask::find_first(rep->theNodes);
2290          i != NdbNodeBitmask::NotFound;
2291          i = NdbNodeBitmask::find_next(rep->theNodes, i + 1))
2292     {
2293       tmp->m_impl->theWaiter.nodeFail(i);
2294     }
2295     break;
2296   }
2297   default:
2298     abort();
2299   }
2300 }
2301 
2302 void
execNodeStatus(void * dictImpl,Uint32 aNode,Uint32 ns_event)2303 NdbDictInterface::execNodeStatus(void* dictImpl, Uint32 aNode, Uint32 ns_event)
2304 {
2305 }
2306 
2307 int
dictSignal(NdbApiSignal * sig,LinearSectionPtr ptr[3],int secs,int node_specification,Uint32 wst,int timeout,Uint32 RETRIES,const int * errcodes,int temporaryMask)2308 NdbDictInterface::dictSignal(NdbApiSignal* sig,
2309 			     LinearSectionPtr ptr[3], int secs,
2310 			     int node_specification,
2311 			     Uint32 wst,
2312 			     int timeout, Uint32 RETRIES,
2313 			     const int *errcodes, int temporaryMask)
2314 {
2315   DBUG_ENTER("NdbDictInterface::dictSignal");
2316   DBUG_PRINT("enter", ("useMasterNodeId: %d", node_specification));
2317 
2318   int sleep = 50;
2319   int mod = 5;
2320 
2321   for(Uint32 i = 0; i<RETRIES; i++)
2322   {
2323     if (i > 0)
2324     {
2325       Uint32 t = sleep + 10 * (rand() % mod);
2326 #ifdef VM_TRACE
2327       ndbout_c("retry sleep %ums on error %u", t, m_error.code);
2328 #endif
2329       NdbSleep_MilliSleep(t);
2330     }
2331     if (i == RETRIES / 2)
2332     {
2333       mod = 10;
2334     }
2335     if (i == 3*RETRIES/4)
2336     {
2337       sleep = 100;
2338     }
2339 
2340     m_buffer.clear();
2341 
2342     // Protected area
2343     /*
2344       The PollGuard has an implicit call of unlock_and_signal through the
2345       ~PollGuard method. This method is called implicitly by the compiler
2346       in all places where the object is out of context due to a return,
2347       break, continue or simply end of statement block
2348     */
2349     PollGuard poll_guard(* m_impl);
2350     Uint32 node;
2351     switch(node_specification){
2352     case 0:
2353       node = (m_impl->get_node_alive(m_masterNodeId) ? m_masterNodeId :
2354 	      (m_masterNodeId = getTransporter()->get_an_alive_node()));
2355       break;
2356     case -1:
2357       node = getTransporter()->get_an_alive_node();
2358       break;
2359     default:
2360       node = node_specification;
2361     }
2362     DBUG_PRINT("info", ("node %d", node));
2363     if(node == 0){
2364       m_error.code= 4009;
2365       DBUG_RETURN(-1);
2366     }
2367     int res = (ptr ?
2368 	       m_impl->sendFragmentedSignal(sig, node, ptr, secs):
2369 	       m_impl->sendSignal(sig, node));
2370     if(res != 0){
2371       DBUG_PRINT("info", ("dictSignal failed to send signal"));
2372       m_error.code = 4007;
2373       continue;
2374     }
2375 
2376     m_impl->incClientStat(Ndb::WaitMetaRequestCount,1);
2377     m_error.code= 0;
2378     int ret_val= poll_guard.wait_n_unlock(timeout, node, wst, true);
2379     // End of Protected area
2380 
2381     if(ret_val == 0 && m_error.code == 0){
2382       // Normal return
2383       DBUG_RETURN(0);
2384     }
2385 
2386     /**
2387      * Handle error codes
2388      */
2389     if(ret_val == -2) //WAIT_NODE_FAILURE
2390     {
2391       m_error.code = 4013;
2392       continue;
2393     }
2394     if(m_impl->theWaiter.get_state() == WST_WAIT_TIMEOUT)
2395     {
2396       DBUG_PRINT("info", ("dictSignal caught time-out"));
2397       m_error.code = 4008;
2398       DBUG_RETURN(-1);
2399     }
2400 
2401     if ( temporaryMask == -1)
2402     {
2403       const NdbError &error= getNdbError();
2404       if (error.status ==  NdbError::TemporaryError)
2405       {
2406         continue;
2407       }
2408     }
2409     else if ( (temporaryMask & m_error.code) != 0 )
2410     {
2411       continue;
2412     }
2413     DBUG_PRINT("info", ("dictSignal caught error= %d", m_error.code));
2414 
2415     if(m_error.code && errcodes)
2416     {
2417       int j;
2418       for(j = 0; errcodes[j] ; j++){
2419 	if(m_error.code == errcodes[j]){
2420 	  break;
2421 	}
2422       }
2423       if(errcodes[j]) // Accepted error code
2424       {
2425         continue;
2426       }
2427     }
2428     break;
2429   }
2430   DBUG_RETURN(-1);
2431 }
2432 
2433 /*
2434   Get dictionary information for a table using table id as reference
2435 
2436   DESCRIPTION
2437     Sends a GET_TABINFOREQ signal containing the table id
2438  */
2439 NdbTableImpl *
getTable(int tableId,bool fullyQualifiedNames)2440 NdbDictInterface::getTable(int tableId, bool fullyQualifiedNames)
2441 {
2442   NdbApiSignal tSignal(m_reference);
2443   GetTabInfoReq * req = CAST_PTR(GetTabInfoReq, tSignal.getDataPtrSend());
2444 
2445   req->senderRef = m_reference;
2446   req->senderData = 0;
2447   req->requestType =
2448     GetTabInfoReq::RequestById | GetTabInfoReq::LongSignalConf;
2449   req->tableId = tableId;
2450   req->schemaTransId = m_tx.transId();
2451   tSignal.theReceiversBlockNumber = DBDICT;
2452   tSignal.theVerId_signalNumber   = GSN_GET_TABINFOREQ;
2453   tSignal.theLength = GetTabInfoReq::SignalLength;
2454 
2455   return getTable(&tSignal, 0, 0, fullyQualifiedNames);
2456 }
2457 
2458 /*
2459   Get dictionary information for a table using table name as the reference
2460 
2461   DESCRIPTION
2462     Send GET_TABINFOREQ signal with the table name in the first
2463     long section part
2464 */
2465 
2466 NdbTableImpl *
getTable(const BaseString & name,bool fullyQualifiedNames)2467 NdbDictInterface::getTable(const BaseString& name, bool fullyQualifiedNames)
2468 {
2469   NdbApiSignal tSignal(m_reference);
2470   GetTabInfoReq* const req = CAST_PTR(GetTabInfoReq, tSignal.getDataPtrSend());
2471 
2472   const Uint32 namelen= name.length() + 1; // NULL terminated
2473   const Uint32 namelen_words= (namelen + 3) >> 2; // Size in words
2474 
2475   req->senderRef= m_reference;
2476   req->senderData= 0;
2477   req->requestType=
2478     GetTabInfoReq::RequestByName | GetTabInfoReq::LongSignalConf;
2479   req->tableNameLen= namelen;
2480   req->schemaTransId = m_tx.transId();
2481   tSignal.theReceiversBlockNumber= DBDICT;
2482   tSignal.theVerId_signalNumber= GSN_GET_TABINFOREQ;
2483   tSignal.theLength= GetTabInfoReq::SignalLength;
2484 
2485   // Copy name to m_buffer to get a word sized buffer
2486   m_buffer.clear();
2487   if (m_buffer.grow(namelen_words*4+4) ||
2488       m_buffer.append(name.c_str(), namelen))
2489   {
2490     m_error.code= 4000;
2491     return NULL;
2492   }
2493 
2494 #ifndef IGNORE_VALGRIND_WARNINGS
2495   Uint32 pad = 0;
2496   if (m_buffer.append(&pad, 4))
2497   {
2498     m_error.code= 4000;
2499     return NULL;
2500   }
2501 #endif
2502 
2503   LinearSectionPtr ptr[1];
2504   ptr[0].p= (Uint32*)m_buffer.get_data();
2505   ptr[0].sz= namelen_words;
2506 
2507   return getTable(&tSignal, ptr, 1, fullyQualifiedNames);
2508 }
2509 
2510 
2511 NdbTableImpl *
getTable(class NdbApiSignal * signal,LinearSectionPtr ptr[3],Uint32 noOfSections,bool fullyQualifiedNames)2512 NdbDictInterface::getTable(class NdbApiSignal * signal,
2513 			   LinearSectionPtr ptr[3],
2514 			   Uint32 noOfSections, bool fullyQualifiedNames)
2515 {
2516   int errCodes[] = {GetTabInfoRef::Busy, 0 };
2517   int r = dictSignal(signal, ptr, noOfSections,
2518 		     -1, // any node
2519 		     WAIT_GET_TAB_INFO_REQ,
2520 		     DICT_WAITFOR_TIMEOUT, 100, errCodes);
2521 
2522   if (r)
2523     return 0;
2524 
2525   NdbTableImpl * rt = 0;
2526   m_error.code = parseTableInfo(&rt,
2527 				(Uint32*)m_buffer.get_data(),
2528   				m_buffer.length() / 4,
2529 				fullyQualifiedNames);
2530   if(rt)
2531   {
2532     if (rt->buildColumnHash())
2533     {
2534       m_error.code = 4000;
2535       delete rt;
2536       return NULL;
2537      }
2538 
2539     if (rt->m_fragmentType == NdbDictionary::Object::HashMapPartition)
2540     {
2541       NdbHashMapImpl tmp;
2542       if (get_hashmap(tmp, rt->m_hash_map_id))
2543       {
2544         delete rt;
2545         return NULL;
2546       }
2547       for (Uint32 i = 0; i<tmp.m_map.size(); i++)
2548       {
2549         assert(tmp.m_map[i] <= 255);
2550         rt->m_hash_map.push_back(tmp.m_map[i]);
2551       }
2552     }
2553   }
2554 
2555   return rt;
2556 }
2557 
2558 void
execGET_TABINFO_CONF(const NdbApiSignal * signal,const LinearSectionPtr ptr[3])2559 NdbDictInterface::execGET_TABINFO_CONF(const NdbApiSignal * signal,
2560 				       const LinearSectionPtr ptr[3])
2561 {
2562   const GetTabInfoConf* conf = CAST_CONSTPTR(GetTabInfoConf, signal->getDataPtr());
2563   const Uint32 i = GetTabInfoConf::DICT_TAB_INFO;
2564   if(signal->isFirstFragment()){
2565     m_fragmentId = signal->getFragmentId();
2566     if (m_buffer.grow(4 * conf->totalLen))
2567     {
2568       m_error.code= 4000;
2569       goto end;
2570     }
2571   } else {
2572     if(m_fragmentId != signal->getFragmentId()){
2573       abort();
2574     }
2575   }
2576 
2577   if (m_buffer.append(ptr[i].p, 4 * ptr[i].sz))
2578   {
2579     m_error.code= 4000;
2580   }
2581 end:
2582   if(!signal->isLastFragment()){
2583     return;
2584   }
2585 
2586   m_impl->theWaiter.signal(NO_WAIT);
2587 }
2588 
2589 void
execGET_TABINFO_REF(const NdbApiSignal * signal,const LinearSectionPtr ptr[3])2590 NdbDictInterface::execGET_TABINFO_REF(const NdbApiSignal * signal,
2591 				      const LinearSectionPtr ptr[3])
2592 {
2593   const GetTabInfoRef* ref = CAST_CONSTPTR(GetTabInfoRef,
2594 					   signal->getDataPtr());
2595 
2596   if (likely(signal->getLength() == GetTabInfoRef::SignalLength))
2597   {
2598     m_error.code= ref->errorCode;
2599   }
2600   else
2601   {
2602     /* 6.3 <-> 7.0 upgrade only */
2603     assert (signal->getLength() == GetTabInfoRef::OriginalSignalLength);
2604     m_error.code = (*(signal->getDataPtr() +
2605                       GetTabInfoRef::OriginalErrorOffset));
2606   }
2607   m_impl->theWaiter.signal(NO_WAIT);
2608 }
2609 
2610 /*****************************************************************
2611  * Pack/Unpack tables
2612  */
2613 struct ApiKernelMapping {
2614   Int32 kernelConstant;
2615   Int32 apiConstant;
2616 };
2617 
2618 Uint32
getApiConstant(Int32 kernelConstant,const ApiKernelMapping map[],Uint32 def)2619 getApiConstant(Int32 kernelConstant, const ApiKernelMapping map[], Uint32 def)
2620 {
2621   int i = 0;
2622   while(map[i].kernelConstant != kernelConstant){
2623     if(map[i].kernelConstant == -1 &&
2624        map[i].apiConstant == -1){
2625       return def;
2626     }
2627     i++;
2628   }
2629   return map[i].apiConstant;
2630 }
2631 
2632 Uint32
getKernelConstant(Int32 apiConstant,const ApiKernelMapping map[],Uint32 def)2633 getKernelConstant(Int32 apiConstant, const ApiKernelMapping map[], Uint32 def)
2634 {
2635   int i = 0;
2636   while(map[i].apiConstant != apiConstant){
2637     if(map[i].kernelConstant == -1 &&
2638        map[i].apiConstant == -1){
2639       return def;
2640     }
2641     i++;
2642   }
2643   return map[i].kernelConstant;
2644 }
2645 
2646 static const
2647 ApiKernelMapping
2648 fragmentTypeMapping[] = {
2649   { DictTabInfo::AllNodesSmallTable,  NdbDictionary::Object::FragAllSmall },
2650   { DictTabInfo::AllNodesMediumTable, NdbDictionary::Object::FragAllMedium },
2651   { DictTabInfo::AllNodesLargeTable,  NdbDictionary::Object::FragAllLarge },
2652   { DictTabInfo::SingleFragment,      NdbDictionary::Object::FragSingle },
2653   { DictTabInfo::DistrKeyHash,      NdbDictionary::Object::DistrKeyHash },
2654   { DictTabInfo::DistrKeyLin,      NdbDictionary::Object::DistrKeyLin },
2655   { DictTabInfo::UserDefined,      NdbDictionary::Object::UserDefined },
2656   { DictTabInfo::HashMapPartition, NdbDictionary::Object::HashMapPartition },
2657   { -1, -1 }
2658 };
2659 
2660 static const
2661 ApiKernelMapping
2662 objectTypeMapping[] = {
2663   { DictTabInfo::SystemTable,        NdbDictionary::Object::SystemTable },
2664   { DictTabInfo::UserTable,          NdbDictionary::Object::UserTable },
2665   { DictTabInfo::UniqueHashIndex,    NdbDictionary::Object::UniqueHashIndex },
2666   { DictTabInfo::OrderedIndex,       NdbDictionary::Object::OrderedIndex },
2667   { DictTabInfo::HashIndexTrigger,   NdbDictionary::Object::HashIndexTrigger },
2668   { DictTabInfo::IndexTrigger,       NdbDictionary::Object::IndexTrigger },
2669   { DictTabInfo::SubscriptionTrigger,NdbDictionary::Object::SubscriptionTrigger },
2670   { DictTabInfo::ReadOnlyConstraint ,NdbDictionary::Object::ReadOnlyConstraint },
2671   { DictTabInfo::Tablespace,         NdbDictionary::Object::Tablespace },
2672   { DictTabInfo::LogfileGroup,       NdbDictionary::Object::LogfileGroup },
2673   { DictTabInfo::Datafile,           NdbDictionary::Object::Datafile },
2674   { DictTabInfo::Undofile,           NdbDictionary::Object::Undofile },
2675   { DictTabInfo::ReorgTrigger,       NdbDictionary::Object::ReorgTrigger },
2676   { -1, -1 }
2677 };
2678 
2679 static const
2680 ApiKernelMapping
2681 objectStateMapping[] = {
2682   { DictTabInfo::StateOffline,       NdbDictionary::Object::StateOffline },
2683   { DictTabInfo::StateBuilding,      NdbDictionary::Object::StateBuilding },
2684   { DictTabInfo::StateDropping,      NdbDictionary::Object::StateDropping },
2685   { DictTabInfo::StateOnline,        NdbDictionary::Object::StateOnline },
2686   { DictTabInfo::StateBackup,        NdbDictionary::Object::StateBackup },
2687   { DictTabInfo::StateBroken,        NdbDictionary::Object::StateBroken },
2688   { -1, -1 }
2689 };
2690 
2691 static const
2692 ApiKernelMapping
2693 objectStoreMapping[] = {
2694   { DictTabInfo::StoreNotLogged,     NdbDictionary::Object::StoreNotLogged },
2695   { DictTabInfo::StorePermanent,     NdbDictionary::Object::StorePermanent },
2696   { -1, -1 }
2697 };
2698 
2699 static const
2700 ApiKernelMapping
2701 indexTypeMapping[] = {
2702   { DictTabInfo::UniqueHashIndex,    NdbDictionary::Index::UniqueHashIndex },
2703   { DictTabInfo::OrderedIndex,       NdbDictionary::Index::OrderedIndex },
2704   { -1, -1 }
2705 };
2706 
2707 int
parseTableInfo(NdbTableImpl ** ret,const Uint32 * data,Uint32 len,bool fullyQualifiedNames,Uint32 version)2708 NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
2709 				 const Uint32 * data, Uint32 len,
2710 				 bool fullyQualifiedNames,
2711                                  Uint32 version)
2712 {
2713   SimplePropertiesLinearReader it(data, len);
2714   DictTabInfo::Table *tableDesc;
2715   SimpleProperties::UnpackStatus s;
2716   DBUG_ENTER("NdbDictInterface::parseTableInfo");
2717 
2718   tableDesc = (DictTabInfo::Table*)NdbMem_Allocate(sizeof(DictTabInfo::Table));
2719   if (!tableDesc)
2720   {
2721     DBUG_RETURN(4000);
2722   }
2723   tableDesc->init();
2724   s = SimpleProperties::unpack(it, tableDesc,
2725 			       DictTabInfo::TableMapping,
2726 			       DictTabInfo::TableMappingSize,
2727 			       true, true);
2728 
2729   if(s != SimpleProperties::Break){
2730     NdbMem_Free((void*)tableDesc);
2731     DBUG_RETURN(703);
2732   }
2733   const char * internalName = tableDesc->TableName;
2734   const char * externalName = Ndb::externalizeTableName(internalName, fullyQualifiedNames);
2735 
2736   NdbTableImpl * impl = new NdbTableImpl();
2737   impl->m_id = tableDesc->TableId;
2738   impl->m_version = tableDesc->TableVersion;
2739   impl->m_status = NdbDictionary::Object::Retrieved;
2740   if (!impl->m_internalName.assign(internalName) ||
2741       impl->updateMysqlName() ||
2742       !impl->m_externalName.assign(externalName) ||
2743       impl->m_frm.assign(tableDesc->FrmData, tableDesc->FrmLen) ||
2744       impl->m_range.assign((Int32*)tableDesc->RangeListData,
2745                            /* yuck */tableDesc->RangeListDataLen / 4))
2746   {
2747     DBUG_RETURN(4000);
2748   }
2749 
2750   {
2751     /**
2752      * NOTE: fragment data is currently an array of Uint16
2753      *       and len is specified in bytes (yuck)
2754      *       please change to Uint32 and len == count
2755      */
2756     Uint32 cnt = tableDesc->FragmentDataLen / 2;
2757     for (Uint32 i = 0; i<cnt; i++)
2758       if (impl->m_fd.push_back((Uint32)tableDesc->FragmentData[i]))
2759         DBUG_RETURN(4000);
2760   }
2761 
2762   impl->m_fragmentCount = tableDesc->FragmentCount;
2763 
2764   /*
2765     We specifically don't get tablespace data and range/list arrays here
2766     since those are known by the MySQL Server through analysing the
2767     frm file.
2768     Fragment Data contains the real node group mapping and the fragment
2769     identities used for each fragment. At the moment we have no need for
2770     this.
2771     Frm file is needed for autodiscovery.
2772   */
2773 
2774   impl->m_fragmentType = (NdbDictionary::Object::FragmentType)
2775     getApiConstant(tableDesc->FragmentType,
2776 		   fragmentTypeMapping,
2777 		   (Uint32)NdbDictionary::Object::FragUndefined);
2778 
2779   if (impl->m_fragmentType == NdbDictionary::Object::HashMapPartition)
2780   {
2781     impl->m_hash_map_id = tableDesc->HashMapObjectId;
2782     impl->m_hash_map_version = tableDesc->HashMapVersion;
2783   }
2784   else
2785   {
2786     impl->m_hash_map_id = ~0;
2787     impl->m_hash_map_version = ~0;
2788   }
2789 
2790   Uint64 max_rows = ((Uint64)tableDesc->MaxRowsHigh) << 32;
2791   max_rows += tableDesc->MaxRowsLow;
2792   impl->m_max_rows = max_rows;
2793   Uint64 min_rows = ((Uint64)tableDesc->MinRowsHigh) << 32;
2794   min_rows += tableDesc->MinRowsLow;
2795   impl->m_min_rows = min_rows;
2796   impl->m_default_no_part_flag = tableDesc->DefaultNoPartFlag;
2797   impl->m_linear_flag = tableDesc->LinearHashFlag;
2798   impl->m_logging = tableDesc->TableLoggedFlag;
2799   impl->m_temporary = tableDesc->TableTemporaryFlag;
2800   impl->m_row_gci = tableDesc->RowGCIFlag;
2801   impl->m_row_checksum = tableDesc->RowChecksumFlag;
2802   impl->m_force_var_part = tableDesc->ForceVarPartFlag;
2803   impl->m_kvalue = tableDesc->TableKValue;
2804   impl->m_minLoadFactor = tableDesc->MinLoadFactor;
2805   impl->m_maxLoadFactor = tableDesc->MaxLoadFactor;
2806   impl->m_single_user_mode = tableDesc->SingleUserMode;
2807   impl->m_storageType = tableDesc->TableStorageType;
2808   impl->m_extra_row_gci_bits = tableDesc->ExtraRowGCIBits;
2809   impl->m_extra_row_author_bits = tableDesc->ExtraRowAuthorBits;
2810 
2811   impl->m_indexType = (NdbDictionary::Object::Type)
2812     getApiConstant(tableDesc->TableType,
2813 		   indexTypeMapping,
2814 		   NdbDictionary::Object::TypeUndefined);
2815 
2816   bool columnsIndexSourced= false;
2817 
2818   if(impl->m_indexType == NdbDictionary::Object::TypeUndefined){
2819   } else {
2820     const char * externalPrimary =
2821       Ndb::externalizeTableName(tableDesc->PrimaryTable, fullyQualifiedNames);
2822     if (!impl->m_primaryTable.assign(externalPrimary))
2823     {
2824       DBUG_RETURN(4000);
2825     }
2826     columnsIndexSourced= true;
2827   }
2828 
2829   Uint32 i;
2830   for(i = 0; i < tableDesc->NoOfAttributes; i++) {
2831     DictTabInfo::Attribute attrDesc; attrDesc.init();
2832     s = SimpleProperties::unpack(it,
2833 				 &attrDesc,
2834 				 DictTabInfo::AttributeMapping,
2835 				 DictTabInfo::AttributeMappingSize,
2836 				 true, true);
2837     if(s != SimpleProperties::Break){
2838       delete impl;
2839       NdbMem_Free((void*)tableDesc);
2840       DBUG_RETURN(703);
2841     }
2842 
2843     NdbColumnImpl * col = new NdbColumnImpl();
2844     col->m_attrId = attrDesc.AttributeId;
2845     col->setName(attrDesc.AttributeName);
2846 
2847     // check type and compute attribute size and array size
2848     if (! attrDesc.translateExtType()) {
2849       delete col;
2850       delete impl;
2851       NdbMem_Free((void*)tableDesc);
2852       DBUG_RETURN(703);
2853     }
2854     col->m_type = (NdbDictionary::Column::Type)attrDesc.AttributeExtType;
2855     col->m_precision = (attrDesc.AttributeExtPrecision & 0xFFFF);
2856     col->m_scale = attrDesc.AttributeExtScale;
2857     col->m_length = attrDesc.AttributeExtLength;
2858     // charset in upper half of precision
2859     unsigned cs_number = (attrDesc.AttributeExtPrecision >> 16);
2860     // charset is defined exactly for char types
2861     if (col->getCharType() != (cs_number != 0)) {
2862       delete col;
2863       delete impl;
2864       NdbMem_Free((void*)tableDesc);
2865       DBUG_RETURN(703);
2866     }
2867     if (col->getCharType()) {
2868       col->m_cs = get_charset(cs_number, MYF(0));
2869       if (col->m_cs == NULL) {
2870         delete col;
2871         delete impl;
2872         NdbMem_Free((void*)tableDesc);
2873         DBUG_RETURN(743);
2874       }
2875     }
2876     col->m_orgAttrSize = attrDesc.AttributeSize;
2877     col->m_attrSize = (1 << attrDesc.AttributeSize) / 8;
2878     col->m_arraySize = attrDesc.AttributeArraySize;
2879     col->m_arrayType = attrDesc.AttributeArrayType;
2880     if(attrDesc.AttributeSize == 0)
2881     {
2882       col->m_attrSize = 4;
2883       col->m_arraySize = (attrDesc.AttributeArraySize + 31) >> 5;
2884     }
2885     col->m_storageType = attrDesc.AttributeStorageType;
2886     col->m_dynamic = (attrDesc.AttributeDynamic != 0);
2887     col->m_indexSourced= columnsIndexSourced;
2888 
2889     if (col->getBlobType()) {
2890       if (unlikely(col->m_arrayType) == NDB_ARRAYTYPE_FIXED)
2891         col->m_blobVersion = NDB_BLOB_V1;
2892       else if (col->m_arrayType == NDB_ARRAYTYPE_MEDIUM_VAR)
2893         col->m_blobVersion = NDB_BLOB_V2;
2894       else {
2895         delete impl;
2896         NdbMem_Free((void*)tableDesc);
2897         DBUG_RETURN(4263);
2898       }
2899     }
2900 
2901     col->m_pk = attrDesc.AttributeKeyFlag;
2902     col->m_distributionKey = (attrDesc.AttributeDKey != 0);
2903     col->m_nullable = attrDesc.AttributeNullableFlag;
2904     col->m_autoIncrement = (attrDesc.AttributeAutoIncrement != 0);
2905     col->m_autoIncrementInitialValue = ~0;
2906 
2907     if (attrDesc.AttributeDefaultValueLen)
2908     {
2909       assert(attrDesc.AttributeDefaultValueLen >= sizeof(Uint32)); /* AttributeHeader */
2910       const char* defPtr = (const char*) attrDesc.AttributeDefaultValue;
2911       Uint32 a = * (const Uint32*) defPtr;
2912       AttributeHeader ah(ntohl(a));
2913       Uint32 bytesize = ah.getByteSize();
2914       assert(attrDesc.AttributeDefaultValueLen >= sizeof(Uint32) + bytesize);
2915 
2916       if (bytesize)
2917       {
2918         if (col->m_defaultValue.assign(defPtr + sizeof(Uint32), bytesize))
2919         {
2920           delete col;
2921           delete impl;
2922           DBUG_RETURN(4000);
2923         }
2924 
2925         /* Table meta-info is normally stored in network byte order by
2926          * SimpleProperties
2927          * For the default value 'Blob' we do the work
2928          */
2929         /* In-place convert network -> host */
2930         NdbSqlUtil::convertByteOrder(attrDesc.AttributeExtType,
2931                                      attrDesc.AttributeSize,
2932                                      attrDesc.AttributeArrayType,
2933                                      attrDesc.AttributeArraySize,
2934                                      (uchar*) col->m_defaultValue.get_data(),
2935                                      bytesize);
2936 
2937         impl->m_has_default_values = true;
2938       }
2939     }
2940 
2941     col->m_column_no = impl->m_columns.size();
2942     impl->m_columns.push_back(col);
2943     it.next();
2944   }
2945 
2946   impl->computeAggregates();
2947 
2948   if(tableDesc->ReplicaDataLen > 0)
2949   {
2950     Uint16 replicaCount = ntohs(tableDesc->ReplicaData[0]);
2951     Uint16 fragCount = ntohs(tableDesc->ReplicaData[1]);
2952 
2953     assert(replicaCount <= 256);
2954 
2955     impl->m_replicaCount = (Uint8)replicaCount;
2956     impl->m_fragmentCount = fragCount;
2957     DBUG_PRINT("info", ("replicaCount=%x , fragCount=%x",replicaCount,fragCount));
2958     Uint32 pos = 2;
2959     for(i = 0; i < (Uint32) fragCount;i++)
2960     {
2961       pos++; // skip logpart
2962       for (Uint32 j = 0; j<(Uint32)replicaCount; j++)
2963       {
2964 	if (impl->m_fragments.push_back(ntohs(tableDesc->ReplicaData[pos++])))
2965 	{
2966           delete impl;
2967           DBUG_RETURN(4000);
2968         }
2969       }
2970     }
2971 
2972     Uint32 topBit = (1 << 31);
2973     for(; topBit && !(fragCount & topBit); ){
2974       topBit >>= 1;
2975     }
2976     impl->m_hashValueMask = topBit - 1;
2977     impl->m_hashpointerValue = fragCount - (impl->m_hashValueMask + 1);
2978   }
2979   else
2980   {
2981     impl->m_fragmentCount = tableDesc->FragmentCount;
2982     impl->m_replicaCount = 0;
2983     impl->m_hashValueMask = 0;
2984     impl->m_hashpointerValue = 0;
2985   }
2986 
2987   impl->m_tablespace_id = tableDesc->TablespaceId;
2988   impl->m_tablespace_version = tableDesc->TablespaceVersion;
2989 
2990   * ret = impl;
2991 
2992   NdbMem_Free((void*)tableDesc);
2993   if (version < MAKE_VERSION(5,1,3))
2994   {
2995     ;
2996   }
2997   else
2998   {
2999     DBUG_ASSERT(impl->m_fragmentCount > 0);
3000   }
3001   DBUG_RETURN(0);
3002 }
3003 
3004 /*****************************************************************
3005  * Create table and alter table
3006  */
3007 int
createTable(NdbTableImpl & t,NdbDictObjectImpl & objid)3008 NdbDictionaryImpl::createTable(NdbTableImpl &t, NdbDictObjectImpl & objid)
3009 {
3010   DBUG_ENTER("NdbDictionaryImpl::createTable");
3011 
3012   bool autoIncrement = false;
3013   Uint64 initialValue = 0;
3014   for (Uint32 i = 0; i < t.m_columns.size(); i++) {
3015     const NdbColumnImpl* c = t.m_columns[i];
3016     assert(c != NULL);
3017     if (c->m_autoIncrement) {
3018       if (autoIncrement) {
3019         m_error.code = 4335;
3020         DBUG_RETURN(-1);
3021       }
3022       autoIncrement = true;
3023       initialValue = c->m_autoIncrementInitialValue;
3024     }
3025 
3026     if (c->m_pk && (! c->m_defaultValue.empty())) {
3027       /* Default value for primary key column not supported */
3028       m_error.code = 792;
3029       DBUG_RETURN(-1);
3030     }
3031   }
3032 
3033   // create table
3034   if (m_receiver.createTable(m_ndb, t) != 0)
3035     DBUG_RETURN(-1);
3036   Uint32* data = (Uint32*)m_receiver.m_buffer.get_data();
3037   t.m_id = data[0];
3038   t.m_version = data[1];
3039   objid.m_id = data[0];
3040   objid.m_version = data[1];
3041 
3042   // update table def from DICT - by-pass cache
3043   NdbTableImpl* t2 =
3044     m_receiver.getTable(t.m_internalName, m_ndb.usingFullyQualifiedNames());
3045 
3046   // check if we got back same table
3047   if (t2 == NULL) {
3048     DBUG_PRINT("info", ("table %s dropped by another thread",
3049                         t.m_internalName.c_str()));
3050     m_error.code = 283;
3051     DBUG_RETURN(-1);
3052   }
3053   if (t.m_id != t2->m_id || t.m_version != t2->m_version) {
3054     DBUG_PRINT("info", ("table %s re-created by another thread",
3055                         t.m_internalName.c_str()));
3056     m_error.code = 283;
3057     delete t2;
3058     DBUG_RETURN(-1);
3059   }
3060 
3061   // auto-increment - use "t" because initial value is not in DICT
3062   {
3063     if (autoIncrement) {
3064       // XXX unlikely race condition - t.m_id may no longer be same table
3065       // the tuple id range is not used on input
3066       Ndb::TupleIdRange range;
3067       if (m_ndb.setTupleIdInNdb(&t, range, initialValue, false) == -1) {
3068         assert(m_ndb.theError.code != 0);
3069         m_error.code = m_ndb.theError.code;
3070         delete t2;
3071         DBUG_RETURN(-1);
3072       }
3073     }
3074   }
3075 
3076   // blob tables - use "t2" to get values set by kernel
3077   if (t.m_noOfBlobs != 0) {
3078 
3079     // fix up disk data in t2 columns
3080     Uint32 i;
3081     for (i = 0; i < t.m_columns.size(); i++) {
3082       const NdbColumnImpl* c = t.m_columns[i];
3083       NdbColumnImpl* c2 = t2->m_columns[i];
3084       if (c->getBlobType()) {
3085         // type was mangled before sending to DICT
3086         assert(c2->m_storageType == NDB_STORAGETYPE_MEMORY);
3087         c2->m_storageType = c->m_storageType;
3088       }
3089     }
3090 
3091     if (createBlobTables(*t2) != 0) {
3092       int save_code = m_error.code;
3093       (void)dropTableGlobal(*t2);
3094       m_error.code = save_code;
3095       delete t2;
3096       DBUG_RETURN(-1);
3097     }
3098   }
3099 
3100   // not entered in cache
3101   delete t2;
3102   DBUG_RETURN(0);
3103 }
3104 
3105 int
optimizeTable(const NdbTableImpl & t,NdbOptimizeTableHandleImpl & h)3106 NdbDictionaryImpl::optimizeTable(const NdbTableImpl &t,
3107                                  NdbOptimizeTableHandleImpl &h)
3108 {
3109   DBUG_ENTER("NdbDictionaryImpl::optimizeTableGlobal(const NdbTableImpl)");
3110   DBUG_RETURN(h.init(&m_ndb, t));
3111 }
3112 
3113 int
optimizeIndex(const NdbIndexImpl & index,NdbOptimizeIndexHandleImpl & h)3114 NdbDictionaryImpl::optimizeIndex(const NdbIndexImpl &index,
3115                                  NdbOptimizeIndexHandleImpl &h)
3116 {
3117   DBUG_ENTER("NdbDictionaryImpl::optimizeIndexGlobal(const NdbIndexImpl)");
3118   DBUG_RETURN(h.init(&m_ndb, index));
3119 }
3120 
3121 int
createBlobTables(const NdbTableImpl & t)3122 NdbDictionaryImpl::createBlobTables(const NdbTableImpl& t)
3123 {
3124   DBUG_ENTER("NdbDictionaryImpl::createBlobTables");
3125   for (unsigned i = 0; i < t.m_columns.size(); i++) {
3126     const NdbColumnImpl & c = *t.m_columns[i];
3127     if (! c.getBlobType() || c.getPartSize() == 0)
3128       continue;
3129     DBUG_PRINT("info", ("col: %s array type: %u storage type: %u",
3130                         c.m_name.c_str(), c.m_arrayType, c.m_storageType));
3131     NdbTableImpl bt;
3132     NdbError error;
3133     if (NdbBlob::getBlobTable(bt, &t, &c, error) == -1) {
3134       m_error.code = error.code;
3135       DBUG_RETURN(-1);
3136     }
3137     NdbDictionary::Column::StorageType
3138       d = NdbDictionary::Column::StorageTypeDisk;
3139     if (t.m_columns[i]->getStorageType() == d) {
3140       const char* colName = c.m_blobVersion == 1 ? "DATA" : "NDB$DATA";
3141       NdbColumnImpl* bc = bt.getColumn(colName);
3142       assert(bc != NULL);
3143       bc->setStorageType(d);
3144     }
3145     NdbDictionary::ObjectId objId; // ignore objid
3146     if (createTable(bt, NdbDictObjectImpl::getImpl(objId)) != 0) {
3147       DBUG_RETURN(-1);
3148     }
3149   }
3150   DBUG_RETURN(0);
3151 }
3152 
3153 int
createTable(Ndb & ndb,NdbTableImpl & impl)3154 NdbDictInterface::createTable(Ndb & ndb,
3155 			      NdbTableImpl & impl)
3156 {
3157   int ret;
3158 
3159   DBUG_ENTER("NdbDictInterface::createTable");
3160 
3161   if (impl.m_fragmentType == NdbDictionary::Object::HashMapPartition)
3162   {
3163     if (impl.m_hash_map_id == RNIL && impl.m_hash_map_version == ~(Uint32)0)
3164     {
3165       /**
3166        * Make sure that hashmap exists (i.e after upgrade or similar)
3167        */
3168       NdbHashMapImpl hashmap;
3169       ret = create_hashmap(hashmap, 0,
3170                            CreateHashMapReq::CreateDefault |
3171                            CreateHashMapReq::CreateIfNotExists);
3172       if (ret)
3173       {
3174         DBUG_RETURN(ret);
3175       }
3176     }
3177   }
3178 
3179   syncInternalName(ndb, impl);
3180 
3181   UtilBufferWriter w(m_buffer);
3182   ret= serializeTableDesc(ndb, impl, w);
3183   if(ret != 0)
3184   {
3185     DBUG_RETURN(ret);
3186   }
3187 
3188   DBUG_RETURN(sendCreateTable(impl, w));
3189 }
3190 
supportedAlterTable(NdbTableImpl & old_impl,NdbTableImpl & impl)3191 bool NdbDictionaryImpl::supportedAlterTable(NdbTableImpl &old_impl,
3192 					    NdbTableImpl &impl)
3193 {
3194   return m_receiver.supportedAlterTable(old_impl, impl);
3195 }
3196 
supportedAlterTable(const NdbTableImpl & old_impl,NdbTableImpl & impl)3197 bool NdbDictInterface::supportedAlterTable(const NdbTableImpl &old_impl,
3198 					   NdbTableImpl &impl)
3199 {
3200   Uint32 change_mask;
3201   return (compChangeMask(old_impl, impl, change_mask) == 0);
3202 }
3203 
alterTable(NdbTableImpl & old_impl,NdbTableImpl & impl)3204 int NdbDictionaryImpl::alterTable(NdbTableImpl &old_impl,
3205                                   NdbTableImpl &impl)
3206 {
3207   return alterTableGlobal(old_impl, impl);
3208 }
3209 
alterTableGlobal(NdbTableImpl & old_impl,NdbTableImpl & impl)3210 int NdbDictionaryImpl::alterTableGlobal(NdbTableImpl &old_impl,
3211                                         NdbTableImpl &impl)
3212 {
3213   DBUG_ENTER("NdbDictionaryImpl::alterTableGlobal");
3214   // Alter the table
3215   Uint32 changeMask = 0;
3216   int ret = m_receiver.alterTable(m_ndb, old_impl, impl, changeMask);
3217 #if ndb_bug41905
3218   old_impl.m_status = NdbDictionary::Object::Invalid;
3219 #endif
3220   if(ret == 0){
3221     NdbDictInterface::Tx::Op op;
3222     op.m_gsn = GSN_ALTER_TABLE_REQ;
3223     op.m_impl = &old_impl;
3224     if (m_tx.m_op.push_back(op) == -1) {
3225       m_error.code = 4000;
3226       DBUG_RETURN(-1);
3227     }
3228     m_globalHash->lock();
3229     ret = m_globalHash->inc_ref_count(op.m_impl);
3230     m_globalHash->unlock();
3231     if (ret != 0)
3232       m_error.code = 723;
3233 
3234     if (ret == 0 && AlterTableReq::getNameFlag(changeMask) != 0)
3235     {
3236       char db0[MAX_TAB_NAME_SIZE];
3237       char db1[MAX_TAB_NAME_SIZE];
3238       if (old_impl.getDbName(db0, sizeof(db0)) != 0)
3239       {
3240         m_error.code = 705;
3241         DBUG_RETURN(-1);
3242       }
3243       if (impl.getDbName(db1, sizeof(db0)) != 0)
3244       {
3245         m_error.code = 705;
3246         DBUG_RETURN(-1);
3247       }
3248 
3249       bool db_change = strcmp(db0, db1) != 0;
3250       if (old_impl.getSchemaName(db0, sizeof(db0)) != 0)
3251       {
3252         m_error.code = 705;
3253         DBUG_RETURN(-1);
3254       }
3255       if (impl.getSchemaName(db1, sizeof(db0)) != 0)
3256       {
3257         m_error.code = 705;
3258         DBUG_RETURN(-1);
3259       }
3260 
3261       bool schema_change = strcmp(db0, db1) != 0;
3262       if (db_change || schema_change)
3263       {
3264         if (renameBlobTables(old_impl, impl) != 0)
3265         {
3266           DBUG_RETURN(-1);
3267         }
3268       }
3269     }
3270     DBUG_RETURN(ret);
3271   }
3272   ERR_RETURN(getNdbError(), ret);
3273 }
3274 
3275 int
renameBlobTables(const NdbTableImpl & old_tab,const NdbTableImpl & new_tab)3276 NdbDictionaryImpl::renameBlobTables(const NdbTableImpl & old_tab,
3277                                     const NdbTableImpl & new_tab)
3278 {
3279   if (old_tab.m_noOfBlobs == 0)
3280     return 0;
3281 
3282   char db[MAX_TAB_NAME_SIZE];
3283   char schema[MAX_TAB_NAME_SIZE];
3284   new_tab.getDbName(db, sizeof(db));
3285   new_tab.getSchemaName(schema, sizeof(schema));
3286 
3287   for (unsigned i = 0; i < old_tab.m_columns.size(); i++)
3288   {
3289     NdbColumnImpl & c = *old_tab.m_columns[i];
3290     if (! c.getBlobType() || c.getPartSize() == 0)
3291       continue;
3292     NdbTableImpl* _bt = c.m_blobTable;
3293     if (_bt == NULL)
3294     {
3295       continue; // "force" mode on
3296     }
3297 
3298     NdbDictionary::Table& bt = * _bt->m_facade;
3299     NdbDictionary::Table new_bt(bt);
3300     new_bt.m_impl.setDbSchema(db, schema);
3301 
3302     Uint32 changeMask = 0;
3303     int ret = m_receiver.alterTable(m_ndb, bt.m_impl, new_bt.m_impl,changeMask);
3304     if (ret != 0)
3305     {
3306       return ret;
3307     }
3308     assert(AlterTableReq::getNameFlag(changeMask) != 0);
3309   }
3310   return 0;
3311 }
3312 
3313 int
alterTable(Ndb & ndb,const NdbTableImpl & old_impl,NdbTableImpl & impl,Uint32 & change_mask)3314 NdbDictInterface::alterTable(Ndb & ndb,
3315                              const NdbTableImpl &old_impl,
3316                              NdbTableImpl &impl,
3317                              Uint32 & change_mask)
3318 {
3319   int ret;
3320 
3321   DBUG_ENTER("NdbDictInterface::alterTable");
3322 
3323   syncInternalName(ndb, impl);
3324 
3325   /* Check that alter request is valid and compute stuff to alter. */
3326   ret= compChangeMask(old_impl, impl, change_mask);
3327   if(ret != 0)
3328     DBUG_RETURN(ret);
3329 
3330   UtilBufferWriter w(m_buffer);
3331   ret= serializeTableDesc(ndb, impl, w);
3332   if(ret != 0)
3333     DBUG_RETURN(ret);
3334 
3335   DBUG_RETURN(sendAlterTable(impl, change_mask, w));
3336 }
3337 
3338 void
syncInternalName(Ndb & ndb,NdbTableImpl & impl)3339 NdbDictInterface::syncInternalName(Ndb & ndb, NdbTableImpl &impl)
3340 {
3341   const BaseString internalName(
3342     ndb.internalize_table_name(impl.m_externalName.c_str()));
3343   impl.m_internalName.assign(internalName);
3344   impl.updateMysqlName();
3345 }
3346 
3347 /*
3348   Compare old and new Table descriptors.
3349   Set the corresponding flag for any (supported) difference.
3350   Error on any difference not supported for alter table.
3351 */
3352 int
compChangeMask(const NdbTableImpl & old_impl,const NdbTableImpl & impl,Uint32 & change_mask)3353 NdbDictInterface::compChangeMask(const NdbTableImpl &old_impl,
3354                                  const NdbTableImpl &impl,
3355                                  Uint32 &change_mask)
3356 {
3357   DBUG_ENTER("compChangeMask");
3358   bool found_varpart;
3359   change_mask= 0;
3360   Uint32 old_sz= old_impl.m_columns.size();
3361   Uint32 sz= impl.m_columns.size();
3362 
3363   /* These are the supported properties that may be altered. */
3364   DBUG_PRINT("info", ("old_impl.m_internalName='%s' impl.m_internalName='%s'",
3365                       old_impl.m_internalName.c_str(),
3366                       impl.m_internalName.c_str()));
3367   if(impl.m_internalName != old_impl.m_internalName)
3368   {
3369     bool old_blob = is_ndb_blob_table(old_impl.m_externalName.c_str());
3370     bool new_blob = is_ndb_blob_table(impl.m_externalName.c_str());
3371     if (unlikely(old_blob != new_blob))
3372     {
3373       /* Attempt to alter to/from Blob part table name */
3374       DBUG_PRINT("info", ("Attempt to alter to/from Blob part table name"));
3375       goto invalid_alter_table;
3376     }
3377     AlterTableReq::setNameFlag(change_mask, true);
3378   }
3379   if(!impl.m_frm.equal(old_impl.m_frm))
3380     AlterTableReq::setFrmFlag(change_mask, true);
3381   if(!impl.m_fd.equal(old_impl.m_fd))
3382     AlterTableReq::setFragDataFlag(change_mask, true);
3383   if(!impl.m_range.equal(old_impl.m_range))
3384     AlterTableReq::setRangeListFlag(change_mask, true);
3385 
3386   /* No other property can be changed in alter table. */
3387   if(impl.m_logging != old_impl.m_logging ||
3388      impl.m_temporary != old_impl.m_temporary ||
3389      impl.m_row_gci != old_impl.m_row_gci ||
3390      impl.m_row_checksum != old_impl.m_row_checksum ||
3391      impl.m_kvalue != old_impl.m_kvalue ||
3392      impl.m_minLoadFactor != old_impl.m_minLoadFactor ||
3393      impl.m_maxLoadFactor != old_impl.m_maxLoadFactor ||
3394      impl.m_primaryTableId != old_impl.m_primaryTableId ||
3395      impl.m_max_rows != old_impl.m_max_rows ||
3396      impl.m_min_rows != old_impl.m_min_rows ||
3397      impl.m_default_no_part_flag != old_impl.m_default_no_part_flag ||
3398      impl.m_linear_flag != old_impl.m_linear_flag ||
3399      impl.m_fragmentType != old_impl.m_fragmentType ||
3400      impl.m_tablespace_name != old_impl.m_tablespace_name ||
3401      impl.m_tablespace_id != old_impl.m_tablespace_id ||
3402      impl.m_tablespace_version != old_impl.m_tablespace_version ||
3403      impl.m_id != old_impl.m_id ||
3404      impl.m_version != old_impl.m_version ||
3405      sz < old_sz ||
3406      impl.m_extra_row_gci_bits != old_impl.m_extra_row_gci_bits ||
3407      impl.m_extra_row_author_bits != old_impl.m_extra_row_author_bits)
3408   {
3409     DBUG_PRINT("info", ("Old and new table not compatible"));
3410     goto invalid_alter_table;
3411   }
3412 
3413   if (impl.m_fragmentCount != old_impl.m_fragmentCount)
3414   {
3415     if (impl.m_fragmentType != NdbDictionary::Object::HashMapPartition)
3416       goto invalid_alter_table;
3417     AlterTableReq::setAddFragFlag(change_mask, true);
3418   }
3419 
3420   /*
3421     Check for new columns.
3422     We can add one or more new columns at the end, with some restrictions:
3423      - All existing columns must be unchanged.
3424      - The new column must be dynamic.
3425      - The new column must be nullable.
3426      - The new column must be memory based.
3427      - The new column can not be a primary key or distribution key.
3428      - There must already be at least one existing memory-stored dynamic or
3429        variable-sized column (so that the varpart is already allocated) or
3430        varPart must be forced
3431   */
3432   found_varpart= old_impl.getForceVarPart();
3433   for(Uint32 i= 0; i<old_sz; i++)
3434   {
3435     const NdbColumnImpl *col= impl.m_columns[i];
3436     if(!col->equal(*(old_impl.m_columns[i])))
3437     {
3438       DBUG_PRINT("info", ("Old and new column not equal"));
3439       goto invalid_alter_table;
3440     }
3441     if(col->m_storageType == NDB_STORAGETYPE_MEMORY &&
3442        (col->m_dynamic || col->m_arrayType != NDB_ARRAYTYPE_FIXED))
3443       found_varpart= true;
3444   }
3445 
3446   if(sz > old_sz)
3447   {
3448     if(!found_varpart)
3449     {
3450       DBUG_PRINT("info", ("No old dynamic column found"));
3451       goto invalid_alter_table;
3452     }
3453 
3454     for(Uint32 i=old_sz; i<sz; i++)
3455     {
3456       const NdbColumnImpl *col= impl.m_columns[i];
3457       if(!col->m_dynamic || !col->m_nullable ||
3458          col->m_storageType == NDB_STORAGETYPE_DISK ||
3459          col->m_pk ||
3460          col->m_distributionKey ||
3461          col->m_autoIncrement ||                   // ToDo: allow this?
3462 	 (col->getBlobType() && col->getPartSize())
3463          )
3464       {
3465         goto invalid_alter_table;
3466       }
3467     }
3468     AlterTableReq::setAddAttrFlag(change_mask, true);
3469   }
3470 
3471   DBUG_RETURN(0);
3472 
3473  invalid_alter_table:
3474   m_error.code = 741;                           // "Unsupported alter table"
3475   DBUG_RETURN(-1);
3476 }
3477 
3478 int
serializeTableDesc(Ndb & ndb,NdbTableImpl & impl,UtilBufferWriter & w)3479 NdbDictInterface::serializeTableDesc(Ndb & ndb,
3480 				     NdbTableImpl & impl,
3481 				     UtilBufferWriter & w)
3482 {
3483   unsigned i, err;
3484   DBUG_ENTER("NdbDictInterface::serializeTableDesc");
3485 
3486   impl.computeAggregates();
3487 
3488   if((unsigned)impl.getNoOfPrimaryKeys() > NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY){
3489     m_error.code= 4317;
3490     DBUG_RETURN(-1);
3491   }
3492   unsigned sz = impl.m_columns.size();
3493   if (sz > NDB_MAX_ATTRIBUTES_IN_TABLE){
3494     m_error.code= 4318;
3495     DBUG_RETURN(-1);
3496   }
3497 
3498   /*
3499      TODO RONM: Here I need to insert checks for fragment array and
3500      range or list array
3501   */
3502 
3503   //validate();
3504   //aggregate();
3505 
3506   DictTabInfo::Table *tmpTab;
3507 
3508   tmpTab = (DictTabInfo::Table*)NdbMem_Allocate(sizeof(DictTabInfo::Table));
3509   if (!tmpTab)
3510   {
3511     m_error.code = 4000;
3512     DBUG_RETURN(-1);
3513   }
3514   tmpTab->init();
3515   BaseString::snprintf(tmpTab->TableName, sizeof(tmpTab->TableName),
3516                        "%s", impl.m_internalName.c_str());
3517 
3518   Uint32 distKeys= 0;
3519   for(i = 0; i<sz; i++) {
3520     const NdbColumnImpl * col = impl.m_columns[i];
3521     if (col == NULL) {
3522       m_error.code = 4272;
3523       NdbMem_Free((void*)tmpTab);
3524       DBUG_RETURN(-1);
3525     }
3526     if (col->m_distributionKey)
3527     {
3528       distKeys++;
3529       if (!col->m_pk)
3530       {
3531         m_error.code = 4327;
3532         NdbMem_Free((void*)tmpTab);
3533         DBUG_RETURN(-1);
3534       }
3535     }
3536   }
3537   if (distKeys == impl.m_noOfKeys)
3538     distKeys= 0;
3539   impl.m_noOfDistributionKeys= distKeys;
3540 
3541 
3542   // Check max length of frm data
3543   if (impl.m_frm.length() > MAX_FRM_DATA_SIZE){
3544     m_error.code= 1229;
3545     NdbMem_Free((void*)tmpTab);
3546     DBUG_RETURN(-1);
3547   }
3548   /*
3549     TODO RONM: This needs to change to dynamic arrays instead
3550     Frm Data, FragmentData, TablespaceData, RangeListData, TsNameData
3551   */
3552   tmpTab->FrmLen = impl.m_frm.length();
3553   memcpy(tmpTab->FrmData, impl.m_frm.get_data(), impl.m_frm.length());
3554 
3555   {
3556     /**
3557      * NOTE: fragment data is currently an array of Uint16
3558      *       and len is specified in bytes (yuck)
3559      *       please change to Uint32 and len == count
3560      */
3561     const Uint32* src = impl.m_fd.getBase();
3562     tmpTab->FragmentDataLen = 2*impl.m_fd.size();
3563     for (Uint32 i = 0; i<impl.m_fd.size(); i++)
3564       tmpTab->FragmentData[i] = (Uint16)src[i];
3565   }
3566 
3567   {
3568     /**
3569      * NOTE: len is specified in bytes (yuck)
3570      *       please change to len == count
3571      */
3572     tmpTab->RangeListDataLen = 4*impl.m_range.size();
3573     memcpy(tmpTab->RangeListData, impl.m_range.getBase(),4*impl.m_range.size());
3574   }
3575 
3576   tmpTab->FragmentCount= impl.m_fragmentCount;
3577   tmpTab->TableLoggedFlag = impl.m_logging;
3578   tmpTab->TableTemporaryFlag = impl.m_temporary;
3579   tmpTab->RowGCIFlag = impl.m_row_gci;
3580   tmpTab->RowChecksumFlag = impl.m_row_checksum;
3581   tmpTab->TableKValue = impl.m_kvalue;
3582   tmpTab->MinLoadFactor = impl.m_minLoadFactor;
3583   tmpTab->MaxLoadFactor = impl.m_maxLoadFactor;
3584   tmpTab->TableType = DictTabInfo::UserTable;
3585   tmpTab->PrimaryTableId = impl.m_primaryTableId;
3586   tmpTab->NoOfAttributes = sz;
3587   tmpTab->MaxRowsHigh = (Uint32)(impl.m_max_rows >> 32);
3588   tmpTab->MaxRowsLow = (Uint32)(impl.m_max_rows & 0xFFFFFFFF);
3589   tmpTab->MinRowsHigh = (Uint32)(impl.m_min_rows >> 32);
3590   tmpTab->MinRowsLow = (Uint32)(impl.m_min_rows & 0xFFFFFFFF);
3591   tmpTab->DefaultNoPartFlag = impl.m_default_no_part_flag;
3592   tmpTab->LinearHashFlag = impl.m_linear_flag;
3593   tmpTab->SingleUserMode = impl.m_single_user_mode;
3594   tmpTab->ForceVarPartFlag = impl.m_force_var_part;
3595   tmpTab->ExtraRowGCIBits = impl.m_extra_row_gci_bits;
3596   tmpTab->ExtraRowAuthorBits = impl.m_extra_row_author_bits;
3597 
3598   tmpTab->FragmentType = getKernelConstant(impl.m_fragmentType,
3599  					   fragmentTypeMapping,
3600 					   DictTabInfo::AllNodesSmallTable);
3601   tmpTab->TableVersion = rand();
3602 
3603   tmpTab->HashMapObjectId = impl.m_hash_map_id;
3604   tmpTab->HashMapVersion = impl.m_hash_map_version;
3605   tmpTab->TableStorageType = impl.m_storageType;
3606 
3607   const char *tablespace_name= impl.m_tablespace_name.c_str();
3608 loop:
3609   if(impl.m_tablespace_version != ~(Uint32)0)
3610   {
3611     tmpTab->TablespaceId = impl.m_tablespace_id;
3612     tmpTab->TablespaceVersion = impl.m_tablespace_version;
3613   }
3614   else if(strlen(tablespace_name))
3615   {
3616     NdbTablespaceImpl tmp;
3617     if(get_filegroup(tmp, NdbDictionary::Object::Tablespace,
3618 		     tablespace_name) == 0)
3619     {
3620       tmpTab->TablespaceId = tmp.m_id;
3621       tmpTab->TablespaceVersion = tmp.m_version;
3622     }
3623     else
3624     {
3625       // error set by get filegroup
3626       if (m_error.code == 723)
3627 	m_error.code = 755;
3628 
3629       NdbMem_Free((void*)tmpTab);
3630       DBUG_RETURN(-1);
3631     }
3632   }
3633   else
3634   {
3635     for(i = 0; i<sz; i++)
3636     {
3637       if(impl.m_columns[i]->m_storageType == NDB_STORAGETYPE_DISK)
3638       {
3639 	tablespace_name = "DEFAULT-TS";
3640 	goto loop;
3641       }
3642     }
3643   }
3644 
3645   SimpleProperties::UnpackStatus s;
3646   w.reset();
3647   s = SimpleProperties::pack(w,
3648 			     tmpTab,
3649 			     DictTabInfo::TableMapping,
3650 			     DictTabInfo::TableMappingSize, true);
3651 
3652   if(s != SimpleProperties::Eof){
3653     abort();
3654   }
3655   NdbMem_Free((void*)tmpTab);
3656 
3657   DBUG_PRINT("info",("impl.m_noOfDistributionKeys: %d impl.m_noOfKeys: %d distKeys: %d",
3658 		     impl.m_noOfDistributionKeys, impl.m_noOfKeys, distKeys));
3659   if (distKeys == impl.m_noOfKeys)
3660     distKeys= 0;
3661   impl.m_noOfDistributionKeys= distKeys;
3662 
3663   for(i = 0; i<sz; i++){
3664     const NdbColumnImpl * col = impl.m_columns[i];
3665     if(col == 0)
3666       continue;
3667 
3668     DBUG_PRINT("info",("column: %s(%d) col->m_distributionKey: %d"
3669                        " array type: %u storage type: %u",
3670 		       col->m_name.c_str(), i, col->m_distributionKey,
3671                        col->m_arrayType, col->m_storageType));
3672     DictTabInfo::Attribute tmpAttr; tmpAttr.init();
3673     BaseString::snprintf(tmpAttr.AttributeName, sizeof(tmpAttr.AttributeName),
3674 	     "%s", col->m_name.c_str());
3675     tmpAttr.AttributeId = col->m_attrId;
3676     tmpAttr.AttributeKeyFlag = col->m_pk;
3677     tmpAttr.AttributeNullableFlag = col->m_nullable;
3678     tmpAttr.AttributeDKey = distKeys ? col->m_distributionKey : 0;
3679 
3680     tmpAttr.AttributeExtType = (Uint32)col->m_type;
3681     tmpAttr.AttributeExtPrecision = ((unsigned)col->m_precision & 0xFFFF);
3682     tmpAttr.AttributeExtScale = col->m_scale;
3683     tmpAttr.AttributeExtLength = col->m_length;
3684     tmpAttr.AttributeArrayType = col->m_arrayType;
3685 
3686     if(col->m_pk)
3687       tmpAttr.AttributeStorageType = NDB_STORAGETYPE_MEMORY;
3688     else
3689       tmpAttr.AttributeStorageType = col->m_storageType;
3690     tmpAttr.AttributeDynamic = (col->m_dynamic ? 1 : 0);
3691 
3692     if (col->getBlobType()) {
3693       tmpAttr.AttributeArrayType = col->m_arrayType;
3694       tmpAttr.AttributeStorageType = NDB_STORAGETYPE_MEMORY;
3695     }
3696 
3697     // check type and compute attribute size and array size
3698     if (! tmpAttr.translateExtType()) {
3699       m_error.code= 703;
3700       DBUG_RETURN(-1);
3701     }
3702     // charset is defined exactly for char types
3703     if (col->getCharType() != (col->m_cs != NULL)) {
3704       m_error.code= 703;
3705       DBUG_RETURN(-1);
3706     }
3707     // primary key type check
3708     if (col->m_pk &&
3709         (err = NdbSqlUtil::check_column_for_pk(col->m_type, col->m_cs)))
3710     {
3711       m_error.code= err;
3712       DBUG_RETURN(-1);
3713     }
3714     // all PK types now allowed as dist key
3715     // charset in upper half of precision
3716     if (col->getCharType()) {
3717       tmpAttr.AttributeExtPrecision |= (col->m_cs->number << 16);
3718     }
3719 
3720     tmpAttr.AttributeAutoIncrement = col->m_autoIncrement;
3721     {
3722       Uint32 ah;
3723       Uint32 byteSize = col->m_defaultValue.length();
3724       assert(byteSize <= NDB_MAX_TUPLE_SIZE);
3725 
3726       if (byteSize)
3727       {
3728         if (unlikely(! ndb_native_default_support(ndb.getMinDbNodeVersion())))
3729         {
3730           /* We can't create a table with native defaults with
3731            * this kernel version
3732            * Schema feature requires data node upgrade
3733            */
3734           m_error.code = 794;
3735           DBUG_RETURN(-1);
3736         }
3737       }
3738 
3739       //The AttributeId of a column isn't decided now, so 0 is used.
3740       AttributeHeader::init(&ah, 0, byteSize);
3741 
3742       /* Table meta-info is normally stored in network byte order
3743        * by SimpleProperties
3744        * For the default value 'Blob' we do the work
3745        */
3746       Uint32 a = htonl(ah);
3747       memcpy(tmpAttr.AttributeDefaultValue, &a, sizeof(Uint32));
3748       memcpy(tmpAttr.AttributeDefaultValue + sizeof(Uint32),
3749              col->m_defaultValue.get_data(), byteSize);
3750       Uint32 defValByteLen = ((col->m_defaultValue.length() + 3) / 4) * 4;
3751       tmpAttr.AttributeDefaultValueLen = defValByteLen + sizeof(Uint32);
3752 
3753       if (defValByteLen)
3754       {
3755         /* In-place host->network conversion */
3756         NdbSqlUtil::convertByteOrder(tmpAttr.AttributeExtType,
3757                                      tmpAttr.AttributeSize,
3758                                      tmpAttr.AttributeArrayType,
3759                                      tmpAttr.AttributeArraySize,
3760                                      tmpAttr.AttributeDefaultValue +
3761                                      sizeof(Uint32),
3762                                      defValByteLen);
3763       }
3764     }
3765     s = SimpleProperties::pack(w,
3766 			       &tmpAttr,
3767 			       DictTabInfo::AttributeMapping,
3768 			       DictTabInfo::AttributeMappingSize, true);
3769     w.add(DictTabInfo::AttributeEnd, 1);
3770   }
3771 
3772   DBUG_RETURN(0);
3773 }
3774 
3775 int
sendAlterTable(const NdbTableImpl & impl,Uint32 change_mask,UtilBufferWriter & w)3776 NdbDictInterface::sendAlterTable(const NdbTableImpl &impl,
3777                                  Uint32 change_mask,
3778                                  UtilBufferWriter &w)
3779 {
3780   LinearSectionPtr ptr[1];
3781   ptr[0].p = (Uint32*)m_buffer.get_data();
3782   ptr[0].sz = m_buffer.length() / 4;
3783   NdbApiSignal tSignal(m_reference);
3784   tSignal.theReceiversBlockNumber = DBDICT;
3785   tSignal.theVerId_signalNumber   = GSN_ALTER_TABLE_REQ;
3786   tSignal.theLength = AlterTableReq::SignalLength;
3787 
3788   AlterTableReq * req = CAST_PTR(AlterTableReq, tSignal.getDataPtrSend());
3789 
3790   req->clientRef = m_reference;
3791   req->clientData = 0;
3792   req->transId = m_tx.transId();
3793   req->transKey = m_tx.transKey();
3794   req->requestInfo = 0;
3795   req->requestInfo |= m_tx.requestFlags();
3796   req->tableId = impl.m_id;
3797   req->tableVersion = impl.m_version;
3798   req->changeMask = change_mask;
3799 
3800   int errCodes[] = { AlterTableRef::NotMaster, AlterTableRef::Busy, 0 };
3801   int ret= dictSignal(&tSignal, ptr, 1,
3802                       0,                        // master
3803                       WAIT_ALTER_TAB_REQ,
3804                       DICT_WAITFOR_TIMEOUT, 100,
3805                       errCodes);
3806 
3807   if(m_error.code == AlterTableRef::InvalidTableVersion) {
3808     // Clear caches and try again
3809     return(INCOMPATIBLE_VERSION);
3810   }
3811 
3812   return ret;
3813 }
3814 
3815 int
sendCreateTable(const NdbTableImpl & impl,UtilBufferWriter & w)3816 NdbDictInterface::sendCreateTable(const NdbTableImpl &impl,
3817                                   UtilBufferWriter &w)
3818 {
3819   LinearSectionPtr ptr[1];
3820   ptr[0].p = (Uint32*)m_buffer.get_data();
3821   ptr[0].sz = m_buffer.length() / 4;
3822   NdbApiSignal tSignal(m_reference);
3823   tSignal.theReceiversBlockNumber = DBDICT;
3824   tSignal.theVerId_signalNumber   = GSN_CREATE_TABLE_REQ;
3825   tSignal.theLength = CreateTableReq::SignalLength;
3826 
3827   CreateTableReq * req = CAST_PTR(CreateTableReq, tSignal.getDataPtrSend());
3828   req->clientRef = m_reference;
3829   req->clientData = 0;
3830   req->requestInfo = 0;
3831   req->requestInfo |= m_tx.requestFlags();
3832   req->transId = m_tx.transId();
3833   req->transKey = m_tx.transKey();
3834 
3835   int errCodes[]= { CreateTableRef::Busy, CreateTableRef::NotMaster, 0 };
3836   int ret= dictSignal(&tSignal, ptr, 1,
3837                       0,                        // master node
3838                       WAIT_CREATE_INDX_REQ,
3839                       DICT_WAITFOR_TIMEOUT, 100,
3840                       errCodes);
3841 
3842   return ret;
3843 }
3844 
3845 void
execCREATE_TABLE_CONF(const NdbApiSignal * signal,const LinearSectionPtr ptr[3])3846 NdbDictInterface::execCREATE_TABLE_CONF(const NdbApiSignal * signal,
3847 					const LinearSectionPtr ptr[3])
3848 {
3849   const CreateTableConf* const conf=
3850     CAST_CONSTPTR(CreateTableConf, signal->getDataPtr());
3851   m_buffer.grow(4 * 2); // 2 words
3852   Uint32* data = (Uint32*)m_buffer.get_data();
3853   data[0] = conf->tableId;
3854   data[1] = conf->tableVersion;
3855   m_impl->theWaiter.signal(NO_WAIT);
3856 }
3857 
3858 void
execCREATE_TABLE_REF(const NdbApiSignal * sig,const LinearSectionPtr ptr[3])3859 NdbDictInterface::execCREATE_TABLE_REF(const NdbApiSignal * sig,
3860 				       const LinearSectionPtr ptr[3])
3861 {
3862   const CreateTableRef* ref = CAST_CONSTPTR(CreateTableRef, sig->getDataPtr());
3863   m_error.code= ref->errorCode;
3864   m_masterNodeId = ref->masterNodeId;
3865   m_impl->theWaiter.signal(NO_WAIT);
3866 }
3867 
3868 void
execALTER_TABLE_CONF(const NdbApiSignal * signal,const LinearSectionPtr ptr[3])3869 NdbDictInterface::execALTER_TABLE_CONF(const NdbApiSignal * signal,
3870                                        const LinearSectionPtr ptr[3])
3871 {
3872   m_impl->theWaiter.signal(NO_WAIT);
3873 }
3874 
3875 void
execALTER_TABLE_REF(const NdbApiSignal * sig,const LinearSectionPtr ptr[3])3876 NdbDictInterface::execALTER_TABLE_REF(const NdbApiSignal * sig,
3877 				      const LinearSectionPtr ptr[3])
3878 {
3879   const AlterTableRef * ref = CAST_CONSTPTR(AlterTableRef, sig->getDataPtr());
3880   m_error.code= ref->errorCode;
3881   m_masterNodeId = ref->masterNodeId;
3882   m_impl->theWaiter.signal(NO_WAIT);
3883 }
3884 
3885 /*****************************************************************
3886  * Drop table
3887  */
3888 int
dropTable(const char * name)3889 NdbDictionaryImpl::dropTable(const char * name)
3890 {
3891   DBUG_ENTER("NdbDictionaryImpl::dropTable");
3892   DBUG_PRINT("enter",("name: %s", name));
3893   ASSERT_NOT_MYSQLD;
3894   NdbTableImpl * tab = getTable(name);
3895   if(tab == 0){
3896     DBUG_RETURN(-1);
3897   }
3898   int ret = dropTable(* tab);
3899   // If table stored in cache is incompatible with the one in the kernel
3900   // we must clear the cache and try again
3901   if (ret == INCOMPATIBLE_VERSION) {
3902     const BaseString internalTableName(m_ndb.internalize_table_name(name));
3903     DBUG_PRINT("info",("INCOMPATIBLE_VERSION internal_name: %s", internalTableName.c_str()));
3904     m_localHash.drop(internalTableName.c_str());
3905     m_globalHash->lock();
3906     m_globalHash->release(tab, 1);
3907     m_globalHash->unlock();
3908     DBUG_RETURN(dropTable(name));
3909   }
3910 
3911   DBUG_RETURN(ret);
3912 }
3913 
3914 int
dropTable(NdbTableImpl & impl)3915 NdbDictionaryImpl::dropTable(NdbTableImpl & impl)
3916 {
3917   int res;
3918   const char * name = impl.getName();
3919   if(impl.m_status == NdbDictionary::Object::New){
3920     return dropTable(name);
3921   }
3922 
3923   if (impl.m_indexType != NdbDictionary::Object::TypeUndefined)
3924   {
3925     m_receiver.m_error.code= 1228;
3926     return -1;
3927   }
3928 
3929   List list;
3930   if ((res = listIndexes(list, impl.m_id)) == -1){
3931     return -1;
3932   }
3933   for (unsigned i = 0; i < list.count; i++) {
3934     const List::Element& element = list.elements[i];
3935     // note can also return -2 in error case(INCOMPATIBLE_VERSION),
3936     // hence compare with != 0
3937     if ((res = dropIndex(element.name, name)) != 0)
3938     {
3939       return -1;
3940     }
3941   }
3942 
3943   if (impl.m_noOfBlobs != 0) {
3944     if (dropBlobTables(impl) != 0){
3945       return -1;
3946     }
3947   }
3948 
3949   int ret = m_receiver.dropTable(impl);
3950   if(ret == 0 || m_error.code == 709 || m_error.code == 723){
3951     const char * internalTableName = impl.m_internalName.c_str();
3952 
3953 
3954     m_localHash.drop(internalTableName);
3955     m_globalHash->lock();
3956     m_globalHash->release(&impl, 1);
3957     m_globalHash->unlock();
3958 
3959     return 0;
3960   }
3961 
3962   return ret;
3963 }
3964 
3965 int
dropTableGlobal(NdbTableImpl & impl)3966 NdbDictionaryImpl::dropTableGlobal(NdbTableImpl & impl)
3967 {
3968   int res;
3969   DBUG_ENTER("NdbDictionaryImpl::dropTableGlobal");
3970   DBUG_ASSERT(impl.m_status != NdbDictionary::Object::New);
3971   DBUG_ASSERT(impl.m_indexType == NdbDictionary::Object::TypeUndefined);
3972 
3973   List list;
3974   if ((res = listIndexes(list, impl.m_id)) == -1){
3975     ERR_RETURN(getNdbError(), -1);
3976   }
3977   for (unsigned i = 0; i < list.count; i++) {
3978     const List::Element& element = list.elements[i];
3979     NdbIndexImpl *idx= getIndexGlobal(element.name, impl);
3980     if (idx == NULL)
3981     {
3982       ERR_RETURN(getNdbError(), -1);
3983     }
3984     // note can also return -2 in error case(INCOMPATIBLE_VERSION),
3985     // hence compare with != 0
3986     if ((res = dropIndexGlobal(*idx)) != 0)
3987     {
3988       releaseIndexGlobal(*idx, 1);
3989       ERR_RETURN(getNdbError(), -1);
3990     }
3991     releaseIndexGlobal(*idx, 1);
3992   }
3993 
3994   if (impl.m_noOfBlobs != 0) {
3995     if (dropBlobTables(impl) != 0){
3996       ERR_RETURN(getNdbError(), -1);
3997     }
3998   }
3999 
4000   int ret = m_receiver.dropTable(impl);
4001   impl.m_status = NdbDictionary::Object::Invalid;
4002   if(ret == 0 || m_error.code == 709 || m_error.code == 723)
4003   {
4004     DBUG_RETURN(0);
4005   }
4006 
4007   ERR_RETURN(getNdbError(), ret);
4008 }
4009 
4010 int
dropBlobTables(NdbTableImpl & t)4011 NdbDictionaryImpl::dropBlobTables(NdbTableImpl & t)
4012 {
4013   DBUG_ENTER("NdbDictionaryImpl::dropBlobTables");
4014   for (unsigned i = 0; i < t.m_columns.size(); i++) {
4015     NdbColumnImpl & c = *t.m_columns[i];
4016     if (! c.getBlobType() || c.getPartSize() == 0)
4017       continue;
4018     NdbTableImpl* bt = c.m_blobTable;
4019     if (bt == NULL) {
4020       DBUG_PRINT("info", ("col %s: blob table pointer is NULL",
4021                           c.m_name.c_str()));
4022       continue; // "force" mode on
4023     }
4024     // drop directly - by-pass cache
4025     int ret = m_receiver.dropTable(*c.m_blobTable);
4026     if (ret != 0) {
4027       DBUG_PRINT("info", ("col %s: blob table %s: error %d",
4028                  c.m_name.c_str(), bt->m_internalName.c_str(), m_error.code));
4029       if (! (ret == 709 || ret == 723)) // "force" mode on
4030         ERR_RETURN(getNdbError(), -1);
4031     }
4032     // leave c.m_blobTable defined
4033   }
4034   DBUG_RETURN(0);
4035 }
4036 
4037 int
dropTable(const NdbTableImpl & impl)4038 NdbDictInterface::dropTable(const NdbTableImpl & impl)
4039 {
4040   NdbApiSignal tSignal(m_reference);
4041   tSignal.theReceiversBlockNumber = DBDICT;
4042   tSignal.theVerId_signalNumber   = GSN_DROP_TABLE_REQ;
4043   tSignal.theLength = DropTableReq::SignalLength;
4044 
4045   DropTableReq * req = CAST_PTR(DropTableReq, tSignal.getDataPtrSend());
4046   req->clientRef = m_reference;
4047   req->clientData = 0;
4048   req->transId = m_tx.transId();
4049   req->transKey = m_tx.transKey();
4050   req->requestInfo = 0;
4051   req->requestInfo |= m_tx.requestFlags();
4052   req->tableId = impl.m_id;
4053   req->tableVersion = impl.m_version;
4054 
4055   int errCodes[] =
4056     { DropTableRef::NoDropTableRecordAvailable,
4057       DropTableRef::NotMaster,
4058       DropTableRef::Busy, 0 };
4059   int r = dictSignal(&tSignal, 0, 0,
4060 		     0, // master
4061 		     WAIT_DROP_TAB_REQ,
4062 		     DICT_WAITFOR_TIMEOUT, 100,
4063 		     errCodes);
4064   if(m_error.code == DropTableRef::InvalidTableVersion) {
4065     // Clear caches and try again
4066     return INCOMPATIBLE_VERSION;
4067   }
4068   return r;
4069 }
4070 
4071 void
execDROP_TABLE_CONF(const NdbApiSignal * signal,const LinearSectionPtr ptr[3])4072 NdbDictInterface::execDROP_TABLE_CONF(const NdbApiSignal * signal,
4073 				      const LinearSectionPtr ptr[3])
4074 {
4075   DBUG_ENTER("NdbDictInterface::execDROP_TABLE_CONF");
4076   //DropTableConf* const conf = CAST_CONSTPTR(DropTableConf, signal->getDataPtr());
4077 
4078   m_impl->theWaiter.signal(NO_WAIT);
4079   DBUG_VOID_RETURN;
4080 }
4081 
4082 void
execDROP_TABLE_REF(const NdbApiSignal * signal,const LinearSectionPtr ptr[3])4083 NdbDictInterface::execDROP_TABLE_REF(const NdbApiSignal * signal,
4084 				     const LinearSectionPtr ptr[3])
4085 {
4086   DBUG_ENTER("NdbDictInterface::execDROP_TABLE_REF");
4087   const DropTableRef* ref = CAST_CONSTPTR(DropTableRef, signal->getDataPtr());
4088   m_error.code= ref->errorCode;
4089   m_masterNodeId = ref->masterNodeId;
4090   m_impl->theWaiter.signal(NO_WAIT);
4091   DBUG_VOID_RETURN;
4092 }
4093 
4094 int
invalidateObject(NdbTableImpl & impl)4095 NdbDictionaryImpl::invalidateObject(NdbTableImpl & impl)
4096 {
4097   const char * internalTableName = impl.m_internalName.c_str();
4098   DBUG_ENTER("NdbDictionaryImpl::invalidateObject");
4099   DBUG_PRINT("enter", ("internal_name: %s", internalTableName));
4100 
4101   m_localHash.drop(internalTableName);
4102   m_globalHash->lock();
4103   m_globalHash->release(&impl, 1);
4104   m_globalHash->unlock();
4105   DBUG_RETURN(0);
4106 }
4107 
4108 int
removeCachedObject(NdbTableImpl & impl)4109 NdbDictionaryImpl::removeCachedObject(NdbTableImpl & impl)
4110 {
4111   const char * internalTableName = impl.m_internalName.c_str();
4112   DBUG_ENTER("NdbDictionaryImpl::removeCachedObject");
4113   DBUG_PRINT("enter", ("internal_name: %s", internalTableName));
4114 
4115   m_localHash.drop(internalTableName);
4116   m_globalHash->lock();
4117   m_globalHash->release(&impl);
4118   m_globalHash->unlock();
4119   DBUG_RETURN(0);
4120 }
4121 
4122 int
create_index_obj_from_table(NdbIndexImpl ** dst,NdbTableImpl * tab,const NdbTableImpl * prim)4123 NdbDictInterface::create_index_obj_from_table(NdbIndexImpl** dst,
4124 					      NdbTableImpl* tab,
4125 					      const NdbTableImpl* prim)
4126 {
4127   DBUG_ENTER("NdbDictInterface::create_index_obj_from_table");
4128   NdbIndexImpl *idx = new NdbIndexImpl();
4129   if (idx == NULL)
4130   {
4131     errno = ENOMEM;
4132     DBUG_RETURN(-1);
4133   }
4134   idx->m_version = tab->m_version;
4135   idx->m_status = tab->m_status;
4136   idx->m_id = tab->m_id;
4137   if (!idx->m_externalName.assign(tab->getName()) ||
4138       !idx->m_tableName.assign(prim->m_externalName))
4139   {
4140     delete idx;
4141     errno = ENOMEM;
4142     DBUG_RETURN(-1);
4143   }
4144   NdbDictionary::Object::Type type = idx->m_type = tab->m_indexType;
4145   idx->m_logging = tab->m_logging;
4146   idx->m_temporary = tab->m_temporary;
4147 
4148   const Uint32 distKeys = prim->m_noOfDistributionKeys;
4149   Uint32 keyCount =
4150     (type == NdbDictionary::Object::UniqueHashIndex) ?
4151     tab->m_noOfKeys : (distKeys ? distKeys : prim->m_noOfKeys);
4152   const Uint32 fullKeyCount = keyCount;
4153 
4154   unsigned i;
4155   // skip last attribute (NDB$PK or NDB$TNODE)
4156   for(i = 0; i+1<tab->m_columns.size(); i++){
4157     NdbColumnImpl* org = tab->m_columns[i];
4158 
4159     NdbColumnImpl* col = new NdbColumnImpl;
4160     if (col == NULL)
4161     {
4162       errno = ENOMEM;
4163       delete idx;
4164       DBUG_RETURN(-1);
4165     }
4166     // Copy column definition
4167     *col = * org;
4168     if (idx->m_columns.push_back(col))
4169     {
4170       delete col;
4171       delete idx;
4172       DBUG_RETURN(-1);
4173     }
4174 
4175     /**
4176      * reverse map
4177      */
4178     const NdbColumnImpl* primCol = prim->getColumn(col->getName());
4179     if (primCol == 0)
4180     {
4181       delete idx;
4182       DBUG_RETURN(-1);
4183     }
4184 
4185     int key_id = primCol->getColumnNo();
4186     int fill = -1;
4187     idx->m_key_ids.fill(key_id, fill);
4188     idx->m_key_ids[key_id] = i;
4189     col->m_keyInfoPos = key_id;
4190 
4191     if(type == NdbDictionary::Object::OrderedIndex &&
4192        (primCol->m_distributionKey ||
4193 	(distKeys == 0 && primCol->getPrimaryKey())))
4194     {
4195       keyCount--;
4196       org->m_distributionKey = 1;
4197     }
4198     else if (type == NdbDictionary::Object::UniqueHashIndex)
4199     {
4200       keyCount--;
4201       org->m_distributionKey = 1;
4202     }
4203   }
4204 
4205   if(keyCount == 0)
4206   {
4207     tab->m_noOfDistributionKeys = fullKeyCount;
4208   }
4209   else
4210   {
4211     for(i = 0; i+1<tab->m_columns.size(); i++)
4212       tab->m_columns[i]->m_distributionKey = 0;
4213   }
4214 
4215   idx->m_table_id = prim->getObjectId();
4216   idx->m_table_version = prim->getObjectVersion();
4217 
4218   * dst = idx;
4219   DBUG_PRINT("exit", ("m_id: %d  m_version: %d", idx->m_id, idx->m_version));
4220   DBUG_RETURN(0);
4221 }
4222 
4223 /*****************************************************************
4224  * Create index
4225  */
4226 int
createIndex(NdbIndexImpl & ix,bool offline)4227 NdbDictionaryImpl::createIndex(NdbIndexImpl &ix, bool offline)
4228 {
4229   ASSERT_NOT_MYSQLD;
4230   NdbTableImpl* tab = getTable(ix.getTable());
4231   if(tab == 0){
4232     m_error.code = 4249;
4233     return -1;
4234   }
4235 
4236   return m_receiver.createIndex(m_ndb, ix, * tab, offline);
4237 }
4238 
4239 int
createIndex(NdbIndexImpl & ix,NdbTableImpl & tab,bool offline)4240 NdbDictionaryImpl::createIndex(NdbIndexImpl &ix, NdbTableImpl &tab,
4241                                bool offline)
4242 {
4243   return m_receiver.createIndex(m_ndb, ix, tab, offline);
4244 }
4245 
4246 int
createIndex(Ndb & ndb,const NdbIndexImpl & impl,const NdbTableImpl & table,bool offline)4247 NdbDictInterface::createIndex(Ndb & ndb,
4248 			      const NdbIndexImpl & impl,
4249 			      const NdbTableImpl & table,
4250                               bool offline)
4251 {
4252   //validate();
4253   //aggregate();
4254   unsigned i, err;
4255   UtilBufferWriter w(m_buffer);
4256   const size_t len = strlen(impl.m_externalName.c_str()) + 1;
4257   if(len > MAX_TAB_NAME_SIZE) {
4258     m_error.code = 4241;
4259     return -1;
4260   }
4261   const BaseString internalName(
4262     ndb.internalize_index_name(&table, impl.getName()));
4263   w.add(DictTabInfo::TableName, internalName.c_str());
4264   w.add(DictTabInfo::TableLoggedFlag, impl.m_logging);
4265   w.add(DictTabInfo::TableTemporaryFlag, impl.m_temporary);
4266 
4267   NdbApiSignal tSignal(m_reference);
4268   tSignal.theReceiversBlockNumber = DBDICT;
4269   tSignal.theVerId_signalNumber   = GSN_CREATE_INDX_REQ;
4270   tSignal.theLength = CreateIndxReq::SignalLength;
4271 
4272   CreateIndxReq * const req = CAST_PTR(CreateIndxReq, tSignal.getDataPtrSend());
4273   req->clientRef = m_reference;
4274   req->clientData = 0;
4275   req->transId = m_tx.transId();
4276   req->transKey = m_tx.transKey();
4277   req->requestInfo = offline ? CreateIndxReq::RF_BUILD_OFFLINE : 0;
4278   req->requestInfo |= m_tx.requestFlags();
4279 
4280   Uint32 it = getKernelConstant(impl.m_type,
4281 				indexTypeMapping,
4282 				DictTabInfo::UndefTableType);
4283 
4284   if(it == DictTabInfo::UndefTableType){
4285     m_error.code = 4250;
4286     return -1;
4287   }
4288   req->indexType = it;
4289 
4290   req->tableId = table.m_id;
4291   req->tableVersion = table.m_version;
4292   req->online = true;
4293   IndexAttributeList attributeList;
4294   attributeList.sz = impl.m_columns.size();
4295   for(i = 0; i<attributeList.sz; i++){
4296     const NdbColumnImpl* col =
4297       table.getColumn(impl.m_columns[i]->m_name.c_str());
4298     if(col == 0){
4299       m_error.code = 4247;
4300       return -1;
4301     }
4302     // Copy column definition  XXX must be wrong, overwrites
4303     *impl.m_columns[i] = *col;
4304 
4305     // index key type check
4306     if ((it == DictTabInfo::UniqueHashIndex &&
4307          (err = NdbSqlUtil::check_column_for_hash_index(col->m_type, col->m_cs)))
4308         ||
4309         (it == DictTabInfo::OrderedIndex &&
4310          (err = NdbSqlUtil::check_column_for_ordered_index(col->m_type, col->m_cs))))
4311     {
4312       m_error.code = err;
4313       return -1;
4314     }
4315     // API uses external column number to talk to DICT
4316     attributeList.id[i] = col->m_column_no;
4317   }
4318   LinearSectionPtr ptr[2];
4319   ptr[0].p = (Uint32*)&attributeList;
4320   ptr[0].sz = 1 + attributeList.sz;
4321   ptr[1].p = (Uint32*)m_buffer.get_data();
4322   ptr[1].sz = m_buffer.length() >> 2;                //BUG?
4323 
4324   int errCodes[] = { CreateIndxRef::Busy, CreateIndxRef::NotMaster, 0 };
4325   return dictSignal(&tSignal, ptr, 2,
4326 		    0, // master
4327 		    WAIT_CREATE_INDX_REQ,
4328 		    DICT_WAITFOR_TIMEOUT, 100,
4329 		    errCodes);
4330 }
4331 
4332 void
execCREATE_INDX_CONF(const NdbApiSignal * signal,const LinearSectionPtr ptr[3])4333 NdbDictInterface::execCREATE_INDX_CONF(const NdbApiSignal * signal,
4334 				       const LinearSectionPtr ptr[3])
4335 {
4336   m_impl->theWaiter.signal(NO_WAIT);
4337 }
4338 
4339 void
execCREATE_INDX_REF(const NdbApiSignal * sig,const LinearSectionPtr ptr[3])4340 NdbDictInterface::execCREATE_INDX_REF(const NdbApiSignal * sig,
4341 				      const LinearSectionPtr ptr[3])
4342 {
4343   const CreateIndxRef* ref = CAST_CONSTPTR(CreateIndxRef, sig->getDataPtr());
4344   m_error.code = ref->errorCode;
4345   if (m_error.code == ref->NotMaster)
4346     m_masterNodeId = ref->masterNodeId;
4347   m_impl->theWaiter.signal(NO_WAIT);
4348 }
4349 
4350 // INDEX_STAT
4351 
4352 int
updateIndexStat(const NdbIndexImpl & index,const NdbTableImpl & table)4353 NdbDictionaryImpl::updateIndexStat(const NdbIndexImpl& index,
4354                                    const NdbTableImpl& table)
4355 {
4356   Uint32 rt = IndexStatReq::RT_UPDATE_STAT;
4357   return m_receiver.doIndexStatReq(m_ndb, index, table, rt);
4358 }
4359 
4360 int
updateIndexStat(Uint32 indexId,Uint32 indexVersion,Uint32 tableId)4361 NdbDictionaryImpl::updateIndexStat(Uint32 indexId,
4362                                    Uint32 indexVersion,
4363                                    Uint32 tableId)
4364 {
4365   Uint32 rt = IndexStatReq::RT_UPDATE_STAT;
4366   return m_receiver.doIndexStatReq(m_ndb, indexId, indexVersion, tableId, rt);
4367 }
4368 
4369 int
deleteIndexStat(const NdbIndexImpl & index,const NdbTableImpl & table)4370 NdbDictionaryImpl::deleteIndexStat(const NdbIndexImpl& index,
4371                                    const NdbTableImpl& table)
4372 {
4373   Uint32 rt = IndexStatReq::RT_DELETE_STAT;
4374   return m_receiver.doIndexStatReq(m_ndb, index, table, rt);
4375 }
4376 
4377 int
deleteIndexStat(Uint32 indexId,Uint32 indexVersion,Uint32 tableId)4378 NdbDictionaryImpl::deleteIndexStat(Uint32 indexId,
4379                                    Uint32 indexVersion,
4380                                    Uint32 tableId)
4381 {
4382   Uint32 rt = IndexStatReq::RT_DELETE_STAT;
4383   return m_receiver.doIndexStatReq(m_ndb, indexId, indexVersion, tableId, rt);
4384 }
4385 
4386 int
doIndexStatReq(Ndb & ndb,const NdbIndexImpl & index,const NdbTableImpl & table,Uint32 rt)4387 NdbDictInterface::doIndexStatReq(Ndb& ndb,
4388                                  const NdbIndexImpl& index,
4389                                  const NdbTableImpl& table,
4390                                  Uint32 rt)
4391 {
4392   return doIndexStatReq(ndb, index.m_id, index.m_version, table.m_id, rt);
4393 }
4394 
4395 int
doIndexStatReq(Ndb & ndb,Uint32 indexId,Uint32 indexVersion,Uint32 tableId,Uint32 requestType)4396 NdbDictInterface::doIndexStatReq(Ndb& ndb,
4397                                  Uint32 indexId,
4398                                  Uint32 indexVersion,
4399                                  Uint32 tableId,
4400                                  Uint32 requestType)
4401 {
4402   NdbApiSignal tSignal(m_reference);
4403   tSignal.theReceiversBlockNumber = DBDICT;
4404   tSignal.theVerId_signalNumber = GSN_INDEX_STAT_REQ;
4405   tSignal.theLength = IndexStatReq::SignalLength;
4406 
4407   IndexStatReq* req = CAST_PTR(IndexStatReq, tSignal.getDataPtrSend());
4408   req->clientRef = m_reference;
4409   req->clientData = 0;
4410   req->transId = m_tx.transId();
4411   req->transKey = m_tx.transKey();
4412   req->requestInfo = requestType;
4413   req->requestFlag = 0;
4414   req->indexId = indexId;
4415   req->indexVersion = indexVersion;
4416   req->tableId = tableId;
4417 
4418   int errCodes[] = { IndexStatRef::Busy, IndexStatRef::NotMaster, 0 };
4419   return dictSignal(&tSignal, 0, 0,
4420                     0,
4421                     WAIT_CREATE_INDX_REQ,
4422                     DICT_WAITFOR_TIMEOUT, 100,
4423                     errCodes);
4424 }
4425 
4426 void
execINDEX_STAT_CONF(const NdbApiSignal * signal,const LinearSectionPtr ptr[3])4427 NdbDictInterface::execINDEX_STAT_CONF(const NdbApiSignal * signal,
4428 				      const LinearSectionPtr ptr[3])
4429 {
4430   m_impl->theWaiter.signal(NO_WAIT);
4431 }
4432 
4433 void
execINDEX_STAT_REF(const NdbApiSignal * signal,const LinearSectionPtr ptr[3])4434 NdbDictInterface::execINDEX_STAT_REF(const NdbApiSignal * signal,
4435 				     const LinearSectionPtr ptr[3])
4436 {
4437   const IndexStatRef* ref = CAST_CONSTPTR(IndexStatRef, signal->getDataPtr());
4438   m_error.code = ref->errorCode;
4439   if (m_error.code == ref->NotMaster)
4440     m_masterNodeId = ref->masterNodeId;
4441   m_impl->theWaiter.signal(NO_WAIT);
4442 }
4443 
4444 /*****************************************************************
4445  * Drop index
4446  */
4447 int
dropIndex(const char * indexName,const char * tableName)4448 NdbDictionaryImpl::dropIndex(const char * indexName,
4449 			     const char * tableName)
4450 {
4451   ASSERT_NOT_MYSQLD;
4452   NdbIndexImpl * idx = getIndex(indexName, tableName);
4453   if (idx == 0) {
4454     m_error.code = 4243;
4455     return -1;
4456   }
4457   int ret = dropIndex(*idx, tableName);
4458   // If index stored in cache is incompatible with the one in the kernel
4459   // we must clear the cache and try again
4460   if (ret == INCOMPATIBLE_VERSION) {
4461     const BaseString internalIndexName((tableName)
4462       ?
4463       m_ndb.internalize_index_name(getTable(tableName), indexName)
4464       :
4465       m_ndb.internalize_table_name(indexName)); // Index is also a table
4466 
4467     m_localHash.drop(internalIndexName.c_str());
4468     m_globalHash->lock();
4469     m_globalHash->release(idx->m_table, 1);
4470     m_globalHash->unlock();
4471     return dropIndex(indexName, tableName);
4472   }
4473 
4474   return ret;
4475 }
4476 
4477 int
dropIndex(NdbIndexImpl & impl,const char * tableName)4478 NdbDictionaryImpl::dropIndex(NdbIndexImpl & impl, const char * tableName)
4479 {
4480   const char * indexName = impl.getName();
4481   if (tableName || m_ndb.usingFullyQualifiedNames()) {
4482     NdbTableImpl * timpl = impl.m_table;
4483 
4484     if (timpl == 0) {
4485       m_error.code = 709;
4486       return -1;
4487     }
4488 
4489     const BaseString internalIndexName((tableName)
4490       ?
4491       m_ndb.internalize_index_name(getTable(tableName), indexName)
4492       :
4493       m_ndb.internalize_table_name(indexName)); // Index is also a table
4494 
4495     if(impl.m_status == NdbDictionary::Object::New){
4496       return dropIndex(indexName, tableName);
4497     }
4498 
4499     int ret= dropIndexGlobal(impl);
4500     if (ret == 0)
4501     {
4502       m_globalHash->lock();
4503       m_globalHash->release(impl.m_table, 1);
4504       m_globalHash->unlock();
4505       m_localHash.drop(internalIndexName.c_str());
4506     }
4507     return ret;
4508   }
4509 
4510   m_error.code = 4243;
4511   return -1;
4512 }
4513 
4514 int
dropIndexGlobal(NdbIndexImpl & impl)4515 NdbDictionaryImpl::dropIndexGlobal(NdbIndexImpl & impl)
4516 {
4517   DBUG_ENTER("NdbDictionaryImpl::dropIndexGlobal");
4518   int ret = m_receiver.dropIndex(impl, *impl.m_table);
4519   impl.m_status = NdbDictionary::Object::Invalid;
4520   if(ret == 0)
4521   {
4522     DBUG_RETURN(0);
4523   }
4524   ERR_RETURN(getNdbError(), ret);
4525 }
4526 
4527 int
dropIndex(const NdbIndexImpl & impl,const NdbTableImpl & timpl)4528 NdbDictInterface::dropIndex(const NdbIndexImpl & impl,
4529 			    const NdbTableImpl & timpl)
4530 {
4531   DBUG_ENTER("NdbDictInterface::dropIndex");
4532   DBUG_PRINT("enter", ("indexId: %d  indexVersion: %d",
4533                        timpl.m_id, timpl.m_version));
4534   NdbApiSignal tSignal(m_reference);
4535   tSignal.theReceiversBlockNumber = DBDICT;
4536   tSignal.theVerId_signalNumber   = GSN_DROP_INDX_REQ;
4537   tSignal.theLength = DropIndxReq::SignalLength;
4538 
4539   DropIndxReq * const req = CAST_PTR(DropIndxReq, tSignal.getDataPtrSend());
4540   req->clientRef = m_reference;
4541   req->clientData = 0;
4542   req->transId = m_tx.transId();
4543   req->transKey = m_tx.transKey();
4544   req->requestInfo = 0;
4545   req->requestInfo |= m_tx.requestFlags();
4546   req->indexId = timpl.m_id;
4547   req->indexVersion = timpl.m_version;
4548 
4549   int errCodes[] = { DropIndxRef::Busy, DropIndxRef::NotMaster, 0 };
4550   int r = dictSignal(&tSignal, 0, 0,
4551 		     0, // master
4552 		     WAIT_DROP_INDX_REQ,
4553 		     DICT_WAITFOR_TIMEOUT, 100,
4554 		     errCodes);
4555   if(m_error.code == DropIndxRef::InvalidIndexVersion) {
4556     // Clear caches and try again
4557     ERR_RETURN(m_error, INCOMPATIBLE_VERSION);
4558   }
4559   ERR_RETURN(m_error, r);
4560 }
4561 
4562 void
execDROP_INDX_CONF(const NdbApiSignal * signal,const LinearSectionPtr ptr[3])4563 NdbDictInterface::execDROP_INDX_CONF(const NdbApiSignal * signal,
4564 				       const LinearSectionPtr ptr[3])
4565 {
4566   m_impl->theWaiter.signal(NO_WAIT);
4567 }
4568 
4569 void
execDROP_INDX_REF(const NdbApiSignal * signal,const LinearSectionPtr ptr[3])4570 NdbDictInterface::execDROP_INDX_REF(const NdbApiSignal * signal,
4571 				      const LinearSectionPtr ptr[3])
4572 {
4573   const DropIndxRef* ref = CAST_CONSTPTR(DropIndxRef, signal->getDataPtr());
4574   m_error.code = ref->errorCode;
4575   if (m_error.code == ref->NotMaster)
4576     m_masterNodeId = ref->masterNodeId;
4577   m_impl->theWaiter.signal(NO_WAIT);
4578 }
4579 
4580 /*****************************************************************
4581  * Create event
4582  */
4583 
4584 int
createEvent(NdbEventImpl & evnt)4585 NdbDictionaryImpl::createEvent(NdbEventImpl & evnt)
4586 {
4587   DBUG_ENTER("NdbDictionaryImpl::createEvent");
4588   int i;
4589   NdbTableImpl* tab= evnt.m_tableImpl;
4590   if (tab == 0)
4591   {
4592     tab= getTable(evnt.getTableName());
4593     if(tab == 0){
4594       DBUG_PRINT("info",("NdbDictionaryImpl::createEvent: table not found: %s",
4595 			 evnt.getTableName()));
4596       ERR_RETURN(getNdbError(), -1);
4597     }
4598     evnt.setTable(tab);
4599   }
4600 
4601   DBUG_PRINT("info",("Table: id: %d version: %d", tab->m_id, tab->m_version));
4602 
4603   NdbTableImpl &table = *evnt.m_tableImpl;
4604 
4605   int attributeList_sz = evnt.m_attrIds.size();
4606 
4607   for (i = 0; i < attributeList_sz; i++) {
4608     NdbColumnImpl *col_impl = table.getColumn(evnt.m_attrIds[i]);
4609     if (col_impl) {
4610       evnt.m_facade->addColumn(*(col_impl->m_facade));
4611     } else {
4612       ndbout_c("Attr id %u in table %s not found", evnt.m_attrIds[i],
4613 	       evnt.getTableName());
4614       m_error.code= 4713;
4615       ERR_RETURN(getNdbError(), -1);
4616     }
4617   }
4618 
4619   evnt.m_attrIds.clear();
4620 
4621   attributeList_sz = evnt.m_columns.size();
4622 
4623   DBUG_PRINT("info",("Event on tableId=%d, tableVersion=%d, event name %s, no of columns %d",
4624 		     table.m_id, table.m_version,
4625 		     evnt.m_name.c_str(),
4626 		     evnt.m_columns.size()));
4627 
4628   int pk_count = 0;
4629   evnt.m_attrListBitmask.clear();
4630 
4631   for(i = 0; i<attributeList_sz; i++){
4632     const NdbColumnImpl* col =
4633       table.getColumn(evnt.m_columns[i]->m_name.c_str());
4634     if(col == 0){
4635       m_error.code= 4247;
4636       ERR_RETURN(getNdbError(), -1);
4637     }
4638     // Copy column definition
4639     *evnt.m_columns[i] = *col;
4640 
4641     if(col->m_pk){
4642       pk_count++;
4643     }
4644 
4645     evnt.m_attrListBitmask.set(col->m_attrId);
4646   }
4647 
4648   // Sort index attributes according to primary table (using insertion sort)
4649   for(i = 1; i < attributeList_sz; i++) {
4650     NdbColumnImpl* temp = evnt.m_columns[i];
4651     unsigned int j = i;
4652     while((j > 0) && (evnt.m_columns[j - 1]->m_attrId > temp->m_attrId)) {
4653       evnt.m_columns[j] = evnt.m_columns[j - 1];
4654       j--;
4655     }
4656     evnt.m_columns[j] = temp;
4657   }
4658   // Check for illegal duplicate attributes
4659   for(i = 1; i<attributeList_sz; i++) {
4660     if (evnt.m_columns[i-1]->m_attrId == evnt.m_columns[i]->m_attrId) {
4661       m_error.code= 4258;
4662       ERR_RETURN(getNdbError(), -1);
4663     }
4664   }
4665 
4666   // NdbDictInterface m_receiver;
4667   if (m_receiver.createEvent(m_ndb, evnt, 0 /* getFlag unset */) != 0)
4668     ERR_RETURN(getNdbError(), -1);
4669 
4670   // Create blob events
4671   if (evnt.m_mergeEvents && createBlobEvents(evnt) != 0) {
4672     int save_code = m_error.code;
4673     (void)dropEvent(evnt.m_name.c_str(), 0);
4674     m_error.code = save_code;
4675     ERR_RETURN(getNdbError(), -1);
4676   }
4677   DBUG_RETURN(0);
4678 }
4679 
4680 int
createBlobEvents(NdbEventImpl & evnt)4681 NdbDictionaryImpl::createBlobEvents(NdbEventImpl& evnt)
4682 {
4683   DBUG_ENTER("NdbDictionaryImpl::createBlobEvents");
4684   NdbTableImpl& t = *evnt.m_tableImpl;
4685   Uint32 n = t.m_noOfBlobs;
4686   Uint32 i;
4687   for (i = 0; i < evnt.m_columns.size() && n > 0; i++) {
4688     NdbColumnImpl & c = *evnt.m_columns[i];
4689     if (! c.getBlobType() || c.getPartSize() == 0)
4690       continue;
4691     n--;
4692     NdbEventImpl blob_evnt;
4693     NdbBlob::getBlobEvent(blob_evnt, &evnt, &c);
4694     if (createEvent(blob_evnt) != 0)
4695       ERR_RETURN(getNdbError(), -1);
4696   }
4697   DBUG_RETURN(0);
4698 }
4699 
4700 int
createEvent(class Ndb & ndb,NdbEventImpl & evnt,int getFlag)4701 NdbDictInterface::createEvent(class Ndb & ndb,
4702 			      NdbEventImpl & evnt,
4703 			      int getFlag)
4704 {
4705   DBUG_ENTER("NdbDictInterface::createEvent");
4706   DBUG_PRINT("enter",("getFlag=%d",getFlag));
4707 
4708   NdbApiSignal tSignal(m_reference);
4709   tSignal.theReceiversBlockNumber = DBDICT;
4710   tSignal.theVerId_signalNumber   = GSN_CREATE_EVNT_REQ;
4711   if (getFlag)
4712     tSignal.theLength = CreateEvntReq::SignalLengthGet;
4713   else
4714     tSignal.theLength = CreateEvntReq::SignalLengthCreate;
4715 
4716   CreateEvntReq * const req = CAST_PTR(CreateEvntReq, tSignal.getDataPtrSend());
4717 
4718   req->setUserRef(m_reference);
4719   req->setUserData(0);
4720 
4721   Uint32 seccnt = 1;
4722   LinearSectionPtr ptr[2];
4723 
4724   if (getFlag) {
4725     // getting event from Dictionary
4726     req->setRequestType(CreateEvntReq::RT_USER_GET);
4727   } else {
4728     DBUG_PRINT("info",("tableId: %u tableVersion: %u",
4729 		       evnt.m_tableImpl->m_id,
4730                        evnt.m_tableImpl->m_version));
4731     // creating event in Dictionary
4732     req->setRequestType(CreateEvntReq::RT_USER_CREATE);
4733     req->setTableId(evnt.m_tableImpl->m_id);
4734     req->setTableVersion(evnt.m_tableImpl->m_version);
4735     req->setAttrListBitmask(evnt.m_attrListBitmask);
4736     req->setEventType(evnt.mi_type);
4737     req->clearFlags();
4738     if (evnt.m_rep & NdbDictionary::Event::ER_ALL)
4739       req->setReportAll();
4740     if (evnt.m_rep & NdbDictionary::Event::ER_SUBSCRIBE)
4741       req->setReportSubscribe();
4742     if (evnt.m_rep & NdbDictionary::Event::ER_DDL)
4743     {
4744       req->setReportDDL();
4745     }
4746     else
4747     {
4748       req->clearReportDDL();
4749     }
4750     ptr[1].p = evnt.m_attrListBitmask.rep.data;
4751     ptr[1].sz = evnt.m_attrListBitmask.getSizeInWords();
4752     seccnt++;
4753   }
4754 
4755   UtilBufferWriter w(m_buffer);
4756 
4757   const size_t len = strlen(evnt.m_name.c_str()) + 1;
4758   if(len > MAX_TAB_NAME_SIZE) {
4759     m_error.code= 4241;
4760     ERR_RETURN(getNdbError(), -1);
4761   }
4762 
4763   w.add(SimpleProperties::StringValue, evnt.m_name.c_str());
4764 
4765   if (getFlag == 0)
4766   {
4767     const BaseString internal_tabname(
4768       ndb.internalize_table_name(evnt.m_tableName.c_str()));
4769     w.add(SimpleProperties::StringValue,
4770 	 internal_tabname.c_str());
4771   }
4772 
4773   ptr[0].p = (Uint32*)m_buffer.get_data();
4774   ptr[0].sz = (m_buffer.length()+3) >> 2;
4775 
4776   int ret = dictSignal(&tSignal,ptr, seccnt,
4777 		       0, // master
4778 		       WAIT_CREATE_INDX_REQ,
4779 		       DICT_WAITFOR_TIMEOUT, 100,
4780 		       0, -1);
4781 
4782   if (ret) {
4783     ERR_RETURN(getNdbError(), ret);
4784   }
4785 
4786   char *dataPtr = (char *)m_buffer.get_data();
4787   unsigned int lenCreateEvntConf = *((unsigned int *)dataPtr);
4788   dataPtr += sizeof(lenCreateEvntConf);
4789   CreateEvntConf const * evntConf = (CreateEvntConf *)dataPtr;
4790   dataPtr += lenCreateEvntConf;
4791 
4792   //  NdbEventImpl *evntImpl = (NdbEventImpl *)evntConf->getUserData();
4793 
4794   evnt.m_eventId = evntConf->getEventId();
4795   evnt.m_eventKey = evntConf->getEventKey();
4796   evnt.m_table_id = evntConf->getTableId();
4797   evnt.m_table_version = evntConf->getTableVersion();
4798 
4799   if (getFlag) {
4800     evnt.m_attrListBitmask = evntConf->getAttrListBitmask();
4801     evnt.mi_type           = evntConf->getEventType();
4802     evnt.setTable(dataPtr);
4803     if (!m_tableData.empty())
4804     {
4805       Uint32 len = m_tableData.length();
4806       assert((len & 3) == 0);
4807       len /= 4;
4808       if (len <= evnt.m_attrListBitmask.getSizeInWords())
4809       {
4810         evnt.m_attrListBitmask.clear();
4811         memcpy(evnt.m_attrListBitmask.rep.data, m_tableData.get_data(), 4*len);
4812       }
4813       else
4814       {
4815         memcpy(evnt.m_attrListBitmask.rep.data, m_tableData.get_data(),
4816                4*evnt.m_attrListBitmask.getSizeInWords());
4817       }
4818     }
4819   } else {
4820     if ((Uint32) evnt.m_tableImpl->m_id         != evntConf->getTableId() ||
4821 	evnt.m_tableImpl->m_version    != evntConf->getTableVersion() ||
4822 	//evnt.m_attrListBitmask != evntConf->getAttrListBitmask() ||
4823 	evnt.mi_type           != evntConf->getEventType()) {
4824       ndbout_c("ERROR*************");
4825       m_buffer.clear();
4826       m_tableData.clear();
4827       ERR_RETURN(getNdbError(), 1);
4828     }
4829   }
4830 
4831   m_buffer.clear();
4832   m_tableData.clear();
4833 
4834   DBUG_RETURN(0);
4835 }
4836 
4837 int
executeSubscribeEvent(NdbEventOperationImpl & ev_op,Uint32 & buckets)4838 NdbDictionaryImpl::executeSubscribeEvent(NdbEventOperationImpl & ev_op,
4839                                          Uint32 & buckets)
4840 {
4841   // NdbDictInterface m_receiver;
4842   return m_receiver.executeSubscribeEvent(m_ndb, ev_op, buckets);
4843 }
4844 
4845 int
executeSubscribeEvent(class Ndb & ndb,NdbEventOperationImpl & ev_op,Uint32 & buckets)4846 NdbDictInterface::executeSubscribeEvent(class Ndb & ndb,
4847 					NdbEventOperationImpl & ev_op,
4848                                         Uint32 & buckets)
4849 {
4850   DBUG_ENTER("NdbDictInterface::executeSubscribeEvent");
4851   NdbApiSignal tSignal(m_reference);
4852   tSignal.theReceiversBlockNumber = DBDICT;
4853   tSignal.theVerId_signalNumber   = GSN_SUB_START_REQ;
4854   tSignal.theLength = SubStartReq::SignalLength;
4855 
4856   SubStartReq * req = CAST_PTR(SubStartReq, tSignal.getDataPtrSend());
4857 
4858   req->subscriptionId   = ev_op.m_eventImpl->m_eventId;
4859   req->subscriptionKey  = ev_op.m_eventImpl->m_eventKey;
4860   req->part             = SubscriptionData::TableData;
4861   req->subscriberData   = ev_op.m_oid;
4862   req->subscriberRef    = m_reference;
4863 
4864   DBUG_PRINT("info",("GSN_SUB_START_REQ subscriptionId=%d,subscriptionKey=%d,"
4865 		     "subscriberData=%d",req->subscriptionId,
4866 		     req->subscriptionKey,req->subscriberData));
4867 
4868   int errCodes[] = { SubStartRef::Busy,
4869                      SubStartRef::BusyWithNR,
4870                      SubStartRef::NotMaster,
4871                      0 };
4872   int ret = dictSignal(&tSignal,NULL,0,
4873                        0 /*use masternode id*/,
4874                        WAIT_CREATE_INDX_REQ /*WAIT_CREATE_EVNT_REQ*/,
4875                        -1, 100,
4876                        errCodes, -1);
4877   if (ret == 0)
4878   {
4879     buckets = m_data.m_sub_start_conf.m_buckets;
4880   }
4881 
4882   DBUG_RETURN(ret);
4883 }
4884 
4885 int
stopSubscribeEvent(NdbEventOperationImpl & ev_op)4886 NdbDictionaryImpl::stopSubscribeEvent(NdbEventOperationImpl & ev_op)
4887 {
4888   // NdbDictInterface m_receiver;
4889   return m_receiver.stopSubscribeEvent(m_ndb, ev_op);
4890 }
4891 
4892 int
stopSubscribeEvent(class Ndb & ndb,NdbEventOperationImpl & ev_op)4893 NdbDictInterface::stopSubscribeEvent(class Ndb & ndb,
4894 				     NdbEventOperationImpl & ev_op)
4895 {
4896   DBUG_ENTER("NdbDictInterface::stopSubscribeEvent");
4897 
4898   NdbApiSignal tSignal(m_reference);
4899   //  tSignal.theReceiversBlockNumber = SUMA;
4900   tSignal.theReceiversBlockNumber = DBDICT;
4901   tSignal.theVerId_signalNumber   = GSN_SUB_STOP_REQ;
4902   tSignal.theLength = SubStopReq::SignalLength;
4903 
4904   SubStopReq * req = CAST_PTR(SubStopReq, tSignal.getDataPtrSend());
4905 
4906   req->subscriptionId  = ev_op.m_eventImpl->m_eventId;
4907   req->subscriptionKey = ev_op.m_eventImpl->m_eventKey;
4908   req->subscriberData  = ev_op.m_oid;
4909   req->part            = (Uint32) SubscriptionData::TableData;
4910   req->subscriberRef   = m_reference;
4911   req->requestInfo     = 0;
4912 
4913   DBUG_PRINT("info",("GSN_SUB_STOP_REQ subscriptionId=%d,subscriptionKey=%d,"
4914 		     "subscriberData=%d",req->subscriptionId,
4915 		     req->subscriptionKey,req->subscriberData));
4916 
4917   int errCodes[] = { SubStartRef::Busy,
4918                      SubStartRef::BusyWithNR,
4919                      SubStartRef::NotMaster,
4920                      0 };
4921   int ret= dictSignal(&tSignal,NULL,0,
4922                       0 /*use masternode id*/,
4923                       WAIT_CREATE_INDX_REQ /*WAIT_SUB_STOP__REQ*/,
4924                       -1, 100,
4925                       errCodes, -1);
4926   if (ret == 0)
4927   {
4928     Uint32 *data = (Uint32*)m_buffer.get_data();
4929     ev_op.m_stop_gci = data[1] | (Uint64(data[0]) << 32);
4930   }
4931   DBUG_RETURN(ret);
4932 }
4933 
4934 NdbEventImpl *
getEvent(const char * eventName,NdbTableImpl * tab)4935 NdbDictionaryImpl::getEvent(const char * eventName, NdbTableImpl* tab)
4936 {
4937   DBUG_ENTER("NdbDictionaryImpl::getEvent");
4938   DBUG_PRINT("enter",("eventName= %s", eventName));
4939 
4940   NdbEventImpl *ev =  new NdbEventImpl();
4941   if (ev == NULL) {
4942     DBUG_RETURN(NULL);
4943   }
4944 
4945   ev->setName(eventName);
4946 
4947   int ret = m_receiver.createEvent(m_ndb, *ev, 1 /* getFlag set */);
4948 
4949   if (ret) {
4950     delete ev;
4951     DBUG_RETURN(NULL);
4952   }
4953 
4954   // We only have the table name with internal name
4955   DBUG_PRINT("info",("table %s", ev->getTableName()));
4956   if (tab == NULL)
4957   {
4958     tab= fetchGlobalTableImplRef(InitTable(ev->getTableName()));
4959     if (tab == 0)
4960     {
4961       DBUG_PRINT("error",("unable to find table %s", ev->getTableName()));
4962       delete ev;
4963       DBUG_RETURN(NULL);
4964     }
4965     if ((tab->m_status != NdbDictionary::Object::Retrieved) ||
4966         ((Uint32) tab->m_id != ev->m_table_id) ||
4967         (table_version_major(tab->m_version) !=
4968          table_version_major(ev->m_table_version)))
4969     {
4970       DBUG_PRINT("info", ("mismatch on verison in cache"));
4971       releaseTableGlobal(*tab, 1);
4972       tab= fetchGlobalTableImplRef(InitTable(ev->getTableName()));
4973       if (tab == 0)
4974       {
4975         DBUG_PRINT("error",("unable to find table %s", ev->getTableName()));
4976         delete ev;
4977         DBUG_RETURN(NULL);
4978       }
4979     }
4980     ev->setTable(tab);
4981     releaseTableGlobal(*tab, 0);
4982   }
4983   else
4984     ev->setTable(tab);
4985   tab = 0;
4986 
4987   ev->setTable(m_ndb.externalizeTableName(ev->getTableName()));
4988   // get the columns from the attrListBitmask
4989   NdbTableImpl &table = *ev->m_tableImpl;
4990   AttributeMask & mask = ev->m_attrListBitmask;
4991   unsigned attributeList_sz = mask.count();
4992 
4993   DBUG_PRINT("info",("Table: id: %d version: %d",
4994                      table.m_id, table.m_version));
4995 
4996   if ((Uint32) table.m_id != ev->m_table_id ||
4997       table_version_major(table.m_version) !=
4998       table_version_major(ev->m_table_version))
4999   {
5000     m_error.code = 241;
5001     delete ev;
5002     DBUG_RETURN(NULL);
5003   }
5004 
5005   if ( attributeList_sz > (uint) table.getNoOfColumns() )
5006   {
5007     m_error.code = 241;
5008     DBUG_PRINT("error",("Invalid version, too many columns"));
5009     delete ev;
5010     DBUG_RETURN(NULL);
5011   }
5012 
5013   assert( (int)attributeList_sz <= table.getNoOfColumns() );
5014   for(unsigned id= 0; ev->m_columns.size() < attributeList_sz; id++) {
5015     if ( id >= (uint) table.getNoOfColumns())
5016     {
5017       m_error.code = 241;
5018       DBUG_PRINT("error",("Invalid version, column %d out of range", id));
5019       delete ev;
5020       DBUG_RETURN(NULL);
5021     }
5022     if (!mask.get(id))
5023       continue;
5024 
5025     const NdbColumnImpl* col = table.getColumn(id);
5026     DBUG_PRINT("info",("column %d %s", id, col->getName()));
5027     NdbColumnImpl* new_col = new NdbColumnImpl;
5028     // Copy column definition
5029     *new_col = *col;
5030     ev->m_columns.push_back(new_col);
5031   }
5032   DBUG_RETURN(ev);
5033 }
5034 
5035 // ev is main event and has been retrieved previously
5036 NdbEventImpl *
getBlobEvent(const NdbEventImpl & ev,uint col_no)5037 NdbDictionaryImpl::getBlobEvent(const NdbEventImpl& ev, uint col_no)
5038 {
5039   DBUG_ENTER("NdbDictionaryImpl::getBlobEvent");
5040   DBUG_PRINT("enter", ("ev=%s col=%u", ev.m_name.c_str(), col_no));
5041 
5042   NdbTableImpl* tab = ev.m_tableImpl;
5043   assert(tab != NULL && col_no < tab->m_columns.size());
5044   NdbColumnImpl* col = tab->m_columns[col_no];
5045   assert(col != NULL && col->getBlobType() && col->getPartSize() != 0);
5046   NdbTableImpl* blob_tab = col->m_blobTable;
5047   assert(blob_tab != NULL);
5048   char bename[MAX_TAB_NAME_SIZE];
5049   NdbBlob::getBlobEventName(bename, &ev, col);
5050 
5051   NdbEventImpl* blob_ev = getEvent(bename, blob_tab);
5052   DBUG_RETURN(blob_ev);
5053 }
5054 
5055 void
execCREATE_EVNT_CONF(const NdbApiSignal * signal,const LinearSectionPtr ptr[3])5056 NdbDictInterface::execCREATE_EVNT_CONF(const NdbApiSignal * signal,
5057 				       const LinearSectionPtr ptr[3])
5058 {
5059   DBUG_ENTER("NdbDictInterface::execCREATE_EVNT_CONF");
5060 
5061   m_buffer.clear();
5062   m_tableData.clear();
5063   unsigned int len = signal->getLength() << 2;
5064   m_buffer.append((char *)&len, sizeof(len));
5065   m_buffer.append(signal->getDataPtr(), len);
5066 
5067   if (signal->m_noOfSections > 0) {
5068     m_buffer.append((char *)ptr[0].p, strlen((char *)ptr[0].p)+1);
5069   }
5070   if (signal->m_noOfSections > 1)
5071   {
5072     m_tableData.append(ptr[1].p, 4 * ptr[1].sz);
5073   }
5074 
5075   const CreateEvntConf * const createEvntConf=
5076     CAST_CONSTPTR(CreateEvntConf, signal->getDataPtr());
5077 
5078   Uint32 subscriptionId = createEvntConf->getEventId();
5079   Uint32 subscriptionKey = createEvntConf->getEventKey();
5080 
5081   DBUG_PRINT("info",("nodeid=%d,subscriptionId=%d,subscriptionKey=%d",
5082 		     refToNode(signal->theSendersBlockRef),
5083 		     subscriptionId,subscriptionKey));
5084   m_impl->theWaiter.signal(NO_WAIT);
5085   DBUG_VOID_RETURN;
5086 }
5087 
5088 void
execCREATE_EVNT_REF(const NdbApiSignal * signal,const LinearSectionPtr ptr[3])5089 NdbDictInterface::execCREATE_EVNT_REF(const NdbApiSignal * signal,
5090 				      const LinearSectionPtr ptr[3])
5091 {
5092   DBUG_ENTER("NdbDictInterface::execCREATE_EVNT_REF");
5093 
5094   const CreateEvntRef* const ref=
5095     CAST_CONSTPTR(CreateEvntRef, signal->getDataPtr());
5096   m_error.code= ref->getErrorCode();
5097   DBUG_PRINT("error",("error=%d,line=%d,node=%d",ref->getErrorCode(),
5098 		      ref->getErrorLine(),ref->getErrorNode()));
5099   if (m_error.code == CreateEvntRef::NotMaster)
5100     m_masterNodeId = ref->getMasterNode();
5101   m_impl->theWaiter.signal(NO_WAIT);
5102   DBUG_VOID_RETURN;
5103 }
5104 
5105 void
execSUB_STOP_CONF(const NdbApiSignal * signal,const LinearSectionPtr ptr[3])5106 NdbDictInterface::execSUB_STOP_CONF(const NdbApiSignal * signal,
5107 				      const LinearSectionPtr ptr[3])
5108 {
5109   DBUG_ENTER("NdbDictInterface::execSUB_STOP_CONF");
5110   const SubStopConf * const subStopConf=
5111     CAST_CONSTPTR(SubStopConf, signal->getDataPtr());
5112 
5113   Uint32 subscriptionId = subStopConf->subscriptionId;
5114   Uint32 subscriptionKey = subStopConf->subscriptionKey;
5115   Uint32 subscriberData = subStopConf->subscriberData;
5116 
5117   DBUG_PRINT("info",("subscriptionId=%d,subscriptionKey=%d,subscriberData=%d",
5118 		     subscriptionId,subscriptionKey,subscriberData));
5119 
5120   Uint32 gci_hi= 0;
5121   Uint32 gci_lo= 0;
5122   if (SubStopConf::SignalLength >= SubStopConf::SignalLengthWithGci)
5123   {
5124     gci_hi= subStopConf->gci_hi;
5125     gci_lo= subStopConf->gci_lo;
5126   }
5127 
5128   m_buffer.grow(4 * 2); // 2 words
5129   Uint32* data = (Uint32*)m_buffer.get_data();
5130   data[0] = gci_hi;
5131   data[1] = gci_lo;
5132 
5133   m_impl->theWaiter.signal(NO_WAIT);
5134   DBUG_VOID_RETURN;
5135 }
5136 
5137 void
execSUB_STOP_REF(const NdbApiSignal * signal,const LinearSectionPtr ptr[3])5138 NdbDictInterface::execSUB_STOP_REF(const NdbApiSignal * signal,
5139 				     const LinearSectionPtr ptr[3])
5140 {
5141   DBUG_ENTER("NdbDictInterface::execSUB_STOP_REF");
5142   const SubStopRef * const subStopRef=
5143     CAST_CONSTPTR(SubStopRef, signal->getDataPtr());
5144 
5145   Uint32 subscriptionId = subStopRef->subscriptionId;
5146   Uint32 subscriptionKey = subStopRef->subscriptionKey;
5147   Uint32 subscriberData = subStopRef->subscriberData;
5148   m_error.code= subStopRef->errorCode;
5149 
5150   DBUG_PRINT("error",("subscriptionId=%d,subscriptionKey=%d,subscriberData=%d,error=%d",
5151 		      subscriptionId,subscriptionKey,subscriberData,m_error.code));
5152   if (m_error.code == SubStopRef::NotMaster &&
5153       signal->getLength() >= SubStopRef::SL_MasterNode)
5154   {
5155     m_masterNodeId = subStopRef->m_masterNodeId;
5156   }
5157   m_impl->theWaiter.signal(NO_WAIT);
5158   DBUG_VOID_RETURN;
5159 }
5160 
5161 void
execSUB_START_CONF(const NdbApiSignal * signal,const LinearSectionPtr ptr[3])5162 NdbDictInterface::execSUB_START_CONF(const NdbApiSignal * signal,
5163 				     const LinearSectionPtr ptr[3])
5164 {
5165   DBUG_ENTER("NdbDictInterface::execSUB_START_CONF");
5166   const SubStartConf * const subStartConf=
5167     CAST_CONSTPTR(SubStartConf, signal->getDataPtr());
5168 
5169   Uint32 subscriptionId = subStartConf->subscriptionId;
5170   Uint32 subscriptionKey = subStartConf->subscriptionKey;
5171   SubscriptionData::Part part =
5172     (SubscriptionData::Part)subStartConf->part;
5173   Uint32 subscriberData = subStartConf->subscriberData;
5174 
5175   switch(part) {
5176   case SubscriptionData::MetaData: {
5177     DBUG_PRINT("error",("SubscriptionData::MetaData"));
5178     m_error.code= 1;
5179     break;
5180   }
5181   case SubscriptionData::TableData: {
5182     DBUG_PRINT("info",("SubscriptionData::TableData"));
5183     break;
5184   }
5185   default: {
5186     DBUG_PRINT("error",("wrong data"));
5187     m_error.code= 2;
5188     break;
5189   }
5190   }
5191 
5192   if (signal->getLength() == SubStartConf::SignalLength)
5193   {
5194     m_data.m_sub_start_conf.m_buckets = subStartConf->bucketCount;
5195   }
5196   else
5197   {
5198     /* 6.3 <-> 7.0 upgrade
5199      * 6.3 doesn't send required bucketCount.
5200      * ~0 indicates no bucketCount received
5201      */
5202     m_data.m_sub_start_conf.m_buckets = ~0;
5203   }
5204   DBUG_PRINT("info",("subscriptionId=%d,subscriptionKey=%d,subscriberData=%d",
5205 		     subscriptionId,subscriptionKey,subscriberData));
5206   m_impl->theWaiter.signal(NO_WAIT);
5207   DBUG_VOID_RETURN;
5208 }
5209 
5210 void
execSUB_START_REF(const NdbApiSignal * signal,const LinearSectionPtr ptr[3])5211 NdbDictInterface::execSUB_START_REF(const NdbApiSignal * signal,
5212 				    const LinearSectionPtr ptr[3])
5213 {
5214   DBUG_ENTER("NdbDictInterface::execSUB_START_REF");
5215   const SubStartRef * const subStartRef=
5216     CAST_CONSTPTR(SubStartRef, signal->getDataPtr());
5217   m_error.code= subStartRef->errorCode;
5218   if (m_error.code == SubStartRef::NotMaster)
5219     m_masterNodeId = subStartRef->m_masterNodeId;
5220   m_impl->theWaiter.signal(NO_WAIT);
5221   DBUG_VOID_RETURN;
5222 }
5223 
5224 /*****************************************************************
5225  * Drop event
5226  */
5227 int
dropEvent(const char * eventName,int force)5228 NdbDictionaryImpl::dropEvent(const char * eventName, int force)
5229 {
5230   DBUG_ENTER("NdbDictionaryImpl::dropEvent");
5231   DBUG_PRINT("enter", ("name:%s  force: %d", eventName, force));
5232 
5233   NdbEventImpl *evnt = NULL;
5234   if (!force)
5235   {
5236     evnt = getEvent(eventName); // allocated
5237     if (evnt == NULL)
5238     {
5239       if (m_error.code != 723 && // no such table
5240           m_error.code != 241)   // invalid table
5241       {
5242         DBUG_PRINT("info", ("no table err=%d", m_error.code));
5243         DBUG_RETURN(-1);
5244       }
5245       DBUG_PRINT("info", ("no table err=%d, drop by name alone", m_error.code));
5246     }
5247   }
5248   if (evnt == NULL)
5249   {
5250     evnt = new NdbEventImpl();
5251     evnt->setName(eventName);
5252   }
5253   int ret = dropEvent(*evnt);
5254   delete evnt;
5255   DBUG_RETURN(ret);
5256 }
5257 
5258 int
dropEvent(const NdbEventImpl & evnt)5259 NdbDictionaryImpl::dropEvent(const NdbEventImpl& evnt)
5260 {
5261   if (dropBlobEvents(evnt) != 0)
5262     return -1;
5263   if (m_receiver.dropEvent(evnt) != 0)
5264     return -1;
5265   return 0;
5266 }
5267 
5268 int
dropBlobEvents(const NdbEventImpl & evnt)5269 NdbDictionaryImpl::dropBlobEvents(const NdbEventImpl& evnt)
5270 {
5271   DBUG_ENTER("NdbDictionaryImpl::dropBlobEvents");
5272   if (evnt.m_tableImpl != 0) {
5273     const NdbTableImpl& t = *evnt.m_tableImpl;
5274     Uint32 n = t.m_noOfBlobs;
5275     Uint32 i;
5276     for (i = 0; i < evnt.m_columns.size() && n > 0; i++) {
5277       const NdbColumnImpl& c = *evnt.m_columns[i];
5278       if (! c.getBlobType() || c.getPartSize() == 0)
5279         continue;
5280       n--;
5281       NdbEventImpl* blob_evnt = getBlobEvent(evnt, i);
5282       if (blob_evnt == NULL)
5283         continue;
5284       (void)dropEvent(*blob_evnt);
5285       delete blob_evnt;
5286     }
5287   }
5288   else
5289   {
5290     DBUG_PRINT("info", ("no table definition, listing events"));
5291     char bename[MAX_TAB_NAME_SIZE];
5292     int val;
5293     // XXX should get name from NdbBlob
5294     sprintf(bename, "NDB$BLOBEVENT_%s_%s", evnt.getName(), "%d");
5295     List list;
5296     if (listEvents(list))
5297       DBUG_RETURN(-1);
5298     for (unsigned i = 0; i < list.count; i++)
5299     {
5300       NdbDictionary::Dictionary::List::Element& elt = list.elements[i];
5301       switch (elt.type)
5302       {
5303       case NdbDictionary::Object::TableEvent:
5304         if (sscanf(elt.name, bename, &val) == 1)
5305         {
5306           DBUG_PRINT("info", ("found blob event %s, removing...", elt.name));
5307           NdbEventImpl* bevnt = new NdbEventImpl();
5308           bevnt->setName(elt.name);
5309           (void)m_receiver.dropEvent(*bevnt);
5310           delete bevnt;
5311         }
5312         else
5313           DBUG_PRINT("info", ("found event %s, skipping...", elt.name));
5314         break;
5315       default:
5316         break;
5317       }
5318     }
5319   }
5320   DBUG_RETURN(0);
5321 }
5322 
5323 int
dropEvent(const NdbEventImpl & evnt)5324 NdbDictInterface::dropEvent(const NdbEventImpl &evnt)
5325 {
5326   NdbApiSignal tSignal(m_reference);
5327   tSignal.theReceiversBlockNumber = DBDICT;
5328   tSignal.theVerId_signalNumber   = GSN_DROP_EVNT_REQ;
5329   tSignal.theLength = DropEvntReq::SignalLength;
5330 
5331   DropEvntReq * const req = CAST_PTR(DropEvntReq, tSignal.getDataPtrSend());
5332 
5333   req->setUserRef(m_reference);
5334   req->setUserData(0);
5335 
5336   UtilBufferWriter w(m_buffer);
5337 
5338   w.add(SimpleProperties::StringValue, evnt.m_name.c_str());
5339 
5340   LinearSectionPtr ptr[1];
5341   ptr[0].p = (Uint32*)m_buffer.get_data();
5342   ptr[0].sz = (m_buffer.length()+3) >> 2;
5343 
5344   return dictSignal(&tSignal,ptr, 1,
5345 		    0 /*use masternode id*/,
5346 		    WAIT_CREATE_INDX_REQ,
5347 		    -1, 100,
5348 		    0, -1);
5349 }
5350 
5351 void
execDROP_EVNT_CONF(const NdbApiSignal * signal,const LinearSectionPtr ptr[3])5352 NdbDictInterface::execDROP_EVNT_CONF(const NdbApiSignal * signal,
5353 				     const LinearSectionPtr ptr[3])
5354 {
5355   DBUG_ENTER("NdbDictInterface::execDROP_EVNT_CONF");
5356   m_impl->theWaiter.signal(NO_WAIT);
5357   DBUG_VOID_RETURN;
5358 }
5359 
5360 void
execDROP_EVNT_REF(const NdbApiSignal * signal,const LinearSectionPtr ptr[3])5361 NdbDictInterface::execDROP_EVNT_REF(const NdbApiSignal * signal,
5362 				    const LinearSectionPtr ptr[3])
5363 {
5364   DBUG_ENTER("NdbDictInterface::execDROP_EVNT_REF");
5365   const DropEvntRef* const ref=
5366     CAST_CONSTPTR(DropEvntRef, signal->getDataPtr());
5367   m_error.code= ref->getErrorCode();
5368 
5369   DBUG_PRINT("info",("ErrorCode=%u Errorline=%u ErrorNode=%u",
5370 	     ref->getErrorCode(), ref->getErrorLine(), ref->getErrorNode()));
5371   if (m_error.code == DropEvntRef::NotMaster)
5372     m_masterNodeId = ref->getMasterNode();
5373   m_impl->theWaiter.signal(NO_WAIT);
5374   DBUG_VOID_RETURN;
5375 }
5376 
scanEventTable(Ndb * pNdb,const NdbDictionary::Table * pTab,NdbDictionary::Dictionary::List & list)5377 static int scanEventTable(Ndb* pNdb,
5378                           const NdbDictionary::Table* pTab,
5379                           NdbDictionary::Dictionary::List &list)
5380 {
5381   int                  retryAttempt = 0;
5382   const int            retryMax = 100;
5383   NdbTransaction       *pTrans = NULL;
5384   NdbScanOperation     *pOp = NULL;
5385   NdbRecAttr *event_name, *event_id;
5386   NdbError err;
5387   const Uint32 codeWords= 1;
5388   Uint32 codeSpace[ codeWords ];
5389   NdbInterpretedCode code(pTab,
5390                           &codeSpace[0],
5391                           codeWords);
5392   if ((code.interpret_exit_last_row() != 0) ||
5393       (code.finalise() != 0))
5394   {
5395     return code.getNdbError().code;
5396   }
5397 
5398   while (true)
5399   {
5400     NdbDictionary::Dictionary::List tmp_list;
5401 
5402     if (retryAttempt)
5403     {
5404       if (retryAttempt >= retryMax)
5405       {
5406         ndbout << "ERROR: has retried this operation " << retryAttempt
5407                << " times, failing!" << endl;
5408         goto error;
5409       }
5410       if (pTrans)
5411         pNdb->closeTransaction(pTrans);
5412       NdbSleep_MilliSleep(50);
5413     }
5414     retryAttempt++;
5415     pTrans = pNdb->startTransaction();
5416     if (pTrans == NULL)
5417     {
5418       if (pNdb->getNdbError().status == NdbError::TemporaryError)
5419         continue;
5420       goto error;
5421     }
5422 
5423     Uint64 row_count = 0;
5424     {
5425       if ((pOp = pTrans->getNdbScanOperation(pTab)) == NULL)
5426         goto error;
5427       if (pOp->readTuples(NdbScanOperation::LM_CommittedRead, 0, 1) != 0)
5428         goto error;
5429       if (pOp->setInterpretedCode(&code) != 0)
5430         goto error;
5431 
5432       Uint64 tmp;
5433       pOp->getValue(NdbDictionary::Column::ROW_COUNT, (char*)&tmp);
5434       if (pTrans->execute(NdbTransaction::NoCommit) == -1)
5435         goto error;
5436 
5437       int eof;
5438       while ((eof = pOp->nextResult(true)) == 0)
5439         row_count += tmp;
5440 
5441       if (eof == -1)
5442       {
5443         if (pTrans->getNdbError().status == NdbError::TemporaryError)
5444           continue;
5445         goto error;
5446       }
5447     }
5448 
5449     if ((pOp = pTrans->getNdbScanOperation(pTab)) == NULL)
5450       goto error;
5451 
5452     if (pOp->readTuples(NdbScanOperation::LM_CommittedRead, 0, 1) != 0)
5453       goto error;
5454 
5455     if ((event_id   = pOp->getValue(6)) == 0 ||
5456         (event_name = pOp->getValue(0u)) == 0)
5457       goto error;
5458 
5459     if (pTrans->execute(NdbTransaction::NoCommit) == -1)
5460     {
5461       const NdbError err = pTrans->getNdbError();
5462       if (err.status == NdbError::TemporaryError)
5463         continue;
5464       goto error;
5465     }
5466 
5467     /* Cannot handle > 2^32 yet (limit on tmp_list.count is unsigned int) */
5468     assert((row_count & 0xffffffff) == row_count);
5469 
5470     tmp_list.count = (unsigned int)row_count;
5471     tmp_list.elements =
5472       new NdbDictionary::Dictionary::List::Element[(unsigned int)row_count];
5473 
5474     int eof;
5475     unsigned rows = 0;
5476     while((eof = pOp->nextResult()) == 0)
5477     {
5478       if (rows < tmp_list.count)
5479       {
5480         NdbDictionary::Dictionary::List::Element &el = tmp_list.elements[rows];
5481         el.id = event_id->u_32_value();
5482         el.type = NdbDictionary::Object::TableEvent;
5483         el.state = NdbDictionary::Object::StateOnline;
5484         el.store = NdbDictionary::Object::StorePermanent;
5485         Uint32 len = (Uint32)strlen(event_name->aRef());
5486         el.name = new char[len+1];
5487         memcpy(el.name, event_name->aRef(), len);
5488         el.name[len] = 0;
5489       }
5490       rows++;
5491     }
5492     if (eof == -1)
5493     {
5494       if (pTrans->getNdbError().status == NdbError::TemporaryError)
5495         continue;
5496       goto error;
5497     }
5498 
5499     pNdb->closeTransaction(pTrans);
5500 
5501     if (rows < tmp_list.count)
5502       tmp_list.count = rows;
5503 
5504     list = tmp_list;
5505     tmp_list.count = 0;
5506     tmp_list.elements = NULL;
5507 
5508     return 0;
5509   }
5510 error:
5511   int error_code;
5512   if (pTrans)
5513   {
5514     error_code = pTrans->getNdbError().code;
5515     pNdb->closeTransaction(pTrans);
5516   }
5517   else
5518     error_code = pNdb->getNdbError().code;
5519 
5520   return error_code;
5521 }
5522 
5523 int
listEvents(List & list)5524 NdbDictionaryImpl::listEvents(List& list)
5525 {
5526   int error_code;
5527 
5528   BaseString currentDb(m_ndb.getDatabaseName());
5529   BaseString currentSchema(m_ndb.getDatabaseSchemaName());
5530 
5531   m_ndb.setDatabaseName("sys");
5532   m_ndb.setDatabaseSchemaName("def");
5533   {
5534     const NdbDictionary::Table* pTab =
5535       m_facade->getTableGlobal("NDB$EVENTS_0");
5536 
5537     if(pTab == NULL)
5538       error_code = m_facade->getNdbError().code;
5539     else
5540     {
5541       error_code = scanEventTable(&m_ndb, pTab, list);
5542       m_facade->removeTableGlobal(*pTab, 0);
5543     }
5544   }
5545 
5546   m_ndb.setDatabaseName(currentDb.c_str());
5547   m_ndb.setDatabaseSchemaName(currentSchema.c_str());
5548   if (error_code)
5549   {
5550     m_error.code = error_code;
5551     return -1;
5552   }
5553   return 0;
5554 }
5555 
5556 /*****************************************************************
5557  * List objects or indexes
5558  */
5559 int
listObjects(List & list,NdbDictionary::Object::Type type,bool fullyQualified)5560 NdbDictionaryImpl::listObjects(List& list,
5561                                NdbDictionary::Object::Type type,
5562                                bool fullyQualified)
5563 {
5564   int ret;
5565   List list1, list2;
5566   if (type == NdbDictionary::Object::TableEvent)
5567     return listEvents(list);
5568 
5569   if (type == NdbDictionary::Object::TypeUndefined)
5570   {
5571     ret = listEvents(list2);
5572     if (ret)
5573       return ret;
5574   }
5575 
5576   ListTablesReq req;
5577   req.init();
5578   req.setTableId(0);
5579   req.setTableType(getKernelConstant(type, objectTypeMapping, 0));
5580   req.setListNames(true);
5581   if (!list2.count)
5582     return m_receiver.listObjects(list, req, fullyQualified);
5583   ret = m_receiver.listObjects(list1, req, fullyQualified);
5584   if (ret)
5585     return ret;
5586   list.count = list1.count + list2.count;
5587   list.elements = new NdbDictionary::Dictionary::List::Element[list.count];
5588   unsigned i;
5589   const NdbDictionary::Dictionary::List::Element null_el;
5590   for (i = 0; i < list1.count; i++)
5591   {
5592     NdbDictionary::Dictionary::List::Element &el = list1.elements[i];
5593     list.elements[i] = el;
5594     el = null_el;
5595   }
5596   for (i = 0; i < list2.count; i++)
5597   {
5598     NdbDictionary::Dictionary::List::Element &el = list2.elements[i];
5599     list.elements[i + list1.count] = el;
5600     el = null_el;
5601   }
5602   return 0;
5603 }
5604 
5605 int
listIndexes(List & list,Uint32 indexId)5606 NdbDictionaryImpl::listIndexes(List& list, Uint32 indexId)
5607 {
5608   ListTablesReq req;
5609   req.init();
5610   req.setTableId(indexId);
5611   req.setTableType(0);
5612   req.setListNames(true);
5613   req.setListIndexes(true);
5614   return m_receiver.listObjects(list, req, m_ndb.usingFullyQualifiedNames());
5615 }
5616 
5617 int
listObjects(NdbDictionary::Dictionary::List & list,ListTablesReq & ltreq,bool fullyQualifiedNames)5618 NdbDictInterface::listObjects(NdbDictionary::Dictionary::List& list,
5619                               ListTablesReq& ltreq, bool fullyQualifiedNames)
5620 {
5621   bool listTablesLongSignal = false;
5622   NdbApiSignal tSignal(m_reference);
5623   ListTablesReq* const req = CAST_PTR(ListTablesReq, tSignal.getDataPtrSend());
5624   memcpy(req, &ltreq, sizeof(ListTablesReq));
5625   req->senderRef = m_reference;
5626   req->senderData = 0;
5627   if (ltreq.getTableId() > 4096)
5628   {
5629     /*
5630       Enforce new long signal format,
5631       if this is not supported by the
5632       called node the request will fail
5633      */
5634     listTablesLongSignal = true;
5635   }
5636 
5637   /*
5638     Set table id and type according to old format
5639     in case sent to old nodes (during upgrade).
5640   */
5641   req->oldSetTableId(ltreq.getTableId());
5642   req->oldSetTableType(ltreq.getTableType());
5643 
5644   tSignal.theReceiversBlockNumber = DBDICT;
5645   tSignal.theVerId_signalNumber = GSN_LIST_TABLES_REQ;
5646   tSignal.theLength = ListTablesReq::SignalLength;
5647   if (listObjects(&tSignal, listTablesLongSignal) != 0)
5648     return -1;
5649 
5650   if (listTablesLongSignal)
5651   {
5652     return unpackListTables(list, fullyQualifiedNames);
5653   }
5654   else
5655   {
5656     return unpackOldListTables(list, fullyQualifiedNames);
5657   }
5658 }
5659 
5660 int
unpackListTables(NdbDictionary::Dictionary::List & list,bool fullyQualifiedNames)5661 NdbDictInterface::unpackListTables(NdbDictionary::Dictionary::List& list,
5662                                    bool fullyQualifiedNames)
5663 {
5664   Uint32 count = 0;
5665   Uint32* tableData = (Uint32*)m_tableData.get_data();
5666   Uint32* tableNames = (Uint32*)m_tableNames.get_data();
5667   const Uint32 listTablesDataSizeInWords = (sizeof(ListTablesData) + 3) / 4;
5668   list.count = m_noOfTables;
5669   list.elements = new NdbDictionary::Dictionary::List::Element[m_noOfTables];
5670 
5671   while (count < m_noOfTables)
5672   {
5673     NdbDictionary::Dictionary::List::Element& element = list.elements[count];
5674     ListTablesData _ltd;
5675     ListTablesData * ltd = &_ltd;
5676     memcpy(ltd, tableData, 4 * listTablesDataSizeInWords);
5677     tableData += listTablesDataSizeInWords;
5678     element.id = ltd->getTableId();
5679     element.type = (NdbDictionary::Object::Type)
5680       getApiConstant(ltd->getTableType(), objectTypeMapping, 0);
5681     element.state = (NdbDictionary::Object::State)
5682       getApiConstant(ltd->getTableState(), objectStateMapping, 0);
5683     element.store = (NdbDictionary::Object::Store)
5684       getApiConstant(ltd->getTableStore(), objectStoreMapping, 0);
5685     element.temp = ltd->getTableTemp();
5686     // table or index name
5687     BaseString databaseName;
5688     BaseString schemaName;
5689     BaseString objectName;
5690     if (!databaseName || !schemaName || !objectName)
5691     {
5692       m_error.code= 4000;
5693       return -1;
5694     }
5695     Uint32 size = tableNames[0];
5696     Uint32 wsize = (size + 3) / 4;
5697     tableNames++;
5698     if ((element.type == NdbDictionary::Object::UniqueHashIndex) ||
5699 	(element.type == NdbDictionary::Object::OrderedIndex)) {
5700       char * indexName = new char[size];
5701       if (indexName == NULL)
5702       {
5703         m_error.code= 4000;
5704         return -1;
5705       }
5706       memcpy(indexName, (char *) tableNames, size);
5707       if (!(databaseName = Ndb::getDatabaseFromInternalName(indexName)) ||
5708           !(schemaName = Ndb::getSchemaFromInternalName(indexName)))
5709       {
5710         delete [] indexName;
5711         m_error.code= 4000;
5712         return -1;
5713       }
5714       objectName = BaseString(Ndb::externalizeIndexName(indexName,
5715                                                         fullyQualifiedNames));
5716       delete [] indexName;
5717     } else if ((element.type == NdbDictionary::Object::SystemTable) ||
5718 	       (element.type == NdbDictionary::Object::UserTable)) {
5719       char * tableName = new char[size];
5720       if (tableName == NULL)
5721       {
5722         m_error.code= 4000;
5723         return -1;
5724       }
5725       memcpy(tableName, (char *) tableNames, size);
5726       if (!(databaseName = Ndb::getDatabaseFromInternalName(tableName)) ||
5727           !(schemaName = Ndb::getSchemaFromInternalName(tableName)))
5728       {
5729         delete [] tableName;
5730         m_error.code= 4000;
5731         return -1;
5732       }
5733       objectName = BaseString(Ndb::externalizeTableName(tableName,
5734                                                         fullyQualifiedNames));
5735       delete [] tableName;
5736     }
5737     else {
5738       char * otherName = new char[size];
5739       if (otherName == NULL)
5740       {
5741         m_error.code= 4000;
5742         return -1;
5743       }
5744       memcpy(otherName, (char *) tableNames, size);
5745       if (!(objectName = BaseString(otherName)))
5746       {
5747         m_error.code= 4000;
5748         return -1;
5749       }
5750       delete [] otherName;
5751     }
5752     if (!(element.database = new char[databaseName.length() + 1]) ||
5753         !(element.schema = new char[schemaName.length() + 1]) ||
5754         !(element.name = new char[objectName.length() + 1]))
5755     {
5756       m_error.code= 4000;
5757       return -1;
5758     }
5759     strcpy(element.database, databaseName.c_str());
5760     strcpy(element.schema, schemaName.c_str());
5761     strcpy(element.name, objectName.c_str());
5762     count++;
5763     tableNames += wsize;
5764   }
5765 
5766   return 0;
5767 }
5768 
5769 int
unpackOldListTables(NdbDictionary::Dictionary::List & list,bool fullyQualifiedNames)5770 NdbDictInterface::unpackOldListTables(NdbDictionary::Dictionary::List& list,
5771                                       bool fullyQualifiedNames)
5772 {
5773   // count
5774   const Uint32* data = (const Uint32*)m_buffer.get_data();
5775   const unsigned length = m_buffer.length() / 4;
5776   list.count = 0;
5777   bool ok = true;
5778   unsigned pos, count;
5779   pos = count = 0;
5780   while (pos < length) {
5781     // table id - name length - name
5782     pos++;
5783     if (pos >= length) {
5784       ok = false;
5785       break;
5786     }
5787     Uint32 n = (data[pos++] + 3) >> 2;
5788     pos += n;
5789     if (pos > length) {
5790       ok = false;
5791       break;
5792     }
5793     count++;
5794   }
5795   if (! ok) {
5796     // bad signal data
5797     m_error.code= 4213;
5798     return -1;
5799   }
5800   list.count = count;
5801   list.elements = new NdbDictionary::Dictionary::List::Element[count];
5802   pos = count = 0;
5803   while (pos < length) {
5804     NdbDictionary::Dictionary::List::Element& element = list.elements[count];
5805     Uint32 d = data[pos++];
5806     element.id = OldListTablesConf::getTableId(d);
5807     element.type = (NdbDictionary::Object::Type)
5808       getApiConstant(OldListTablesConf::getTableType(d), objectTypeMapping, 0);
5809     element.state = (NdbDictionary::Object::State)
5810       getApiConstant(OldListTablesConf::getTableState(d), objectStateMapping, 0);
5811     element.store = (NdbDictionary::Object::Store)
5812       getApiConstant(OldListTablesConf::getTableStore(d), objectStoreMapping, 0);
5813     element.temp = OldListTablesConf::getTableTemp(d);
5814     // table or index name
5815     Uint32 n = (data[pos++] + 3) >> 2;
5816     BaseString databaseName;
5817     BaseString schemaName;
5818     BaseString objectName;
5819     if (!databaseName || !schemaName || !objectName)
5820     {
5821       m_error.code= 4000;
5822       return -1;
5823     }
5824     if ((element.type == NdbDictionary::Object::UniqueHashIndex) ||
5825 	(element.type == NdbDictionary::Object::OrderedIndex)) {
5826       char * indexName = new char[n << 2];
5827       if (indexName == NULL)
5828       {
5829         m_error.code= 4000;
5830         return -1;
5831       }
5832       memcpy(indexName, &data[pos], n << 2);
5833       if (!(databaseName = Ndb::getDatabaseFromInternalName(indexName)) ||
5834           !(schemaName = Ndb::getSchemaFromInternalName(indexName)))
5835       {
5836         delete [] indexName;
5837         m_error.code= 4000;
5838         return -1;
5839       }
5840       objectName = BaseString(Ndb::externalizeIndexName(indexName, fullyQualifiedNames));
5841       delete [] indexName;
5842     } else if ((element.type == NdbDictionary::Object::SystemTable) ||
5843 	       (element.type == NdbDictionary::Object::UserTable)) {
5844       char * tableName = new char[n << 2];
5845       if (tableName == NULL)
5846       {
5847         m_error.code= 4000;
5848         return -1;
5849       }
5850       memcpy(tableName, &data[pos], n << 2);
5851       if (!(databaseName = Ndb::getDatabaseFromInternalName(tableName)) ||
5852           !(schemaName = Ndb::getSchemaFromInternalName(tableName)))
5853       {
5854         delete [] tableName;
5855         m_error.code= 4000;
5856         return -1;
5857       }
5858       objectName = BaseString(Ndb::externalizeTableName(tableName, fullyQualifiedNames));
5859       delete [] tableName;
5860     }
5861     else {
5862       char * otherName = new char[n << 2];
5863       if (otherName == NULL)
5864       {
5865         m_error.code= 4000;
5866         return -1;
5867       }
5868       memcpy(otherName, &data[pos], n << 2);
5869       if (!(objectName = BaseString(otherName)))
5870       {
5871         m_error.code= 4000;
5872         return -1;
5873       }
5874       delete [] otherName;
5875     }
5876     if (!(element.database = new char[databaseName.length() + 1]) ||
5877         !(element.schema = new char[schemaName.length() + 1]) ||
5878         !(element.name = new char[objectName.length() + 1]))
5879     {
5880       m_error.code= 4000;
5881       return -1;
5882     }
5883     strcpy(element.database, databaseName.c_str());
5884     strcpy(element.schema, schemaName.c_str());
5885     strcpy(element.name, objectName.c_str());
5886     pos += n;
5887     count++;
5888   }
5889   return 0;
5890 }
5891 
5892 int
listObjects(NdbApiSignal * signal,bool & listTablesLongSignal)5893 NdbDictInterface::listObjects(NdbApiSignal* signal,
5894                               bool& listTablesLongSignal)
5895 {
5896   const Uint32 RETRIES = 100;
5897   for (Uint32 i = 0; i < RETRIES; i++) {
5898     m_buffer.clear();
5899     // begin protected
5900     /*
5901       The PollGuard has an implicit call of unlock_and_signal through the
5902       ~PollGuard method. This method is called implicitly by the compiler
5903       in all places where the object is out of context due to a return,
5904       break, continue or simply end of statement block
5905     */
5906     PollGuard poll_guard(* m_impl);
5907     Uint16 aNodeId = getTransporter()->get_an_alive_node();
5908     if (aNodeId == 0) {
5909       m_error.code= 4009;
5910       return -1;
5911     }
5912     NodeInfo info = m_impl->getNodeInfo(aNodeId).m_info;
5913     if (ndbd_LIST_TABLES_CONF_long_signal(info.m_version))
5914     {
5915       /*
5916         Called node will return a long signal
5917        */
5918       listTablesLongSignal = true;
5919     }
5920     else if (listTablesLongSignal)
5921     {
5922       /*
5923         We are requesting info from a table with table id > 4096
5924         and older versions don't support that, bug#36044
5925       */
5926       m_error.code= 4105;
5927       return -1;
5928     }
5929 
5930     if (m_impl->sendSignal(signal, aNodeId) != 0) {
5931       continue;
5932     }
5933     m_impl->incClientStat(Ndb::WaitMetaRequestCount, 1);
5934     m_error.code= 0;
5935     int ret_val= poll_guard.wait_n_unlock(DICT_WAITFOR_TIMEOUT,
5936                                           aNodeId, WAIT_LIST_TABLES_CONF,
5937                                           true);
5938     // end protected
5939     if (ret_val == 0 && m_error.code == 0)
5940       return 0;
5941     if (ret_val == -2) //WAIT_NODE_FAILURE
5942       continue;
5943     return -1;
5944   }
5945   return -1;
5946 }
5947 
5948 void
execLIST_TABLES_CONF(const NdbApiSignal * signal,const LinearSectionPtr ptr[3])5949 NdbDictInterface::execLIST_TABLES_CONF(const NdbApiSignal* signal,
5950                                        const LinearSectionPtr ptr[3])
5951 {
5952   Uint16 nodeId = refToNode(signal->theSendersBlockRef);
5953   NodeInfo info = m_impl->getNodeInfo(nodeId).m_info;
5954   if (!ndbd_LIST_TABLES_CONF_long_signal(info.m_version))
5955   {
5956     /*
5957       Sender doesn't support new signal format
5958      */
5959     NdbDictInterface::execOLD_LIST_TABLES_CONF(signal, ptr);
5960     return;
5961   }
5962 
5963   if (signal->isFirstFragment())
5964   {
5965     m_fragmentId = signal->getFragmentId();
5966     m_noOfTables = 0;
5967     m_tableData.clear();
5968     m_tableNames.clear();
5969   }
5970   else
5971   {
5972     if (m_fragmentId != signal->getFragmentId())
5973     {
5974       abort();
5975     }
5976   }
5977 
5978   /*
5979     Save the count
5980    */
5981   const ListTablesConf* const conf=
5982     CAST_CONSTPTR(ListTablesConf, signal->getDataPtr());
5983   m_noOfTables+= conf->noOfTables;
5984 
5985   bool fragmented = signal->isFragmented();
5986   Uint32 sigLen = signal->getLength() - 1;
5987   const Uint32 secs = signal->m_noOfSections;
5988   const Uint32 directMap[3] = {0,1,2};
5989   const Uint32 * const secNos =
5990     (fragmented) ?
5991     &signal->getDataPtr()[sigLen - secs]
5992     : (const Uint32 *) &directMap;
5993 
5994   for(Uint32 i = 0; i<secs; i++)
5995   {
5996     Uint32 sectionNo = secNos[i];
5997     switch (sectionNo) {
5998     case(ListTablesConf::TABLE_DATA):
5999       if (m_tableData.append(ptr[i].p, 4 * ptr[i].sz))
6000       {
6001         m_error.code= 4000;
6002         goto end;
6003       }
6004       break;
6005     case(ListTablesConf::TABLE_NAMES):
6006       if (m_tableNames.append(ptr[i].p, 4 * ptr[i].sz))
6007       {
6008         m_error.code= 4000;
6009         goto end;
6010       }
6011       break;
6012     default:
6013       abort();
6014     }
6015   }
6016 
6017  end:
6018   if(!signal->isLastFragment()){
6019     return;
6020   }
6021 
6022   m_impl->theWaiter.signal(NO_WAIT);
6023 }
6024 
6025 
6026 void
execOLD_LIST_TABLES_CONF(const NdbApiSignal * signal,const LinearSectionPtr ptr[3])6027 NdbDictInterface::execOLD_LIST_TABLES_CONF(const NdbApiSignal* signal,
6028                                            const LinearSectionPtr ptr[3])
6029 {
6030   const unsigned off = OldListTablesConf::HeaderLength;
6031   const unsigned len = (signal->getLength() - off);
6032   if (m_buffer.append(signal->getDataPtr() + off, len << 2))
6033   {
6034     m_error.code= 4000;
6035   }
6036   if (signal->getLength() < OldListTablesConf::SignalLength) {
6037     // last signal has less than full length
6038     m_impl->theWaiter.signal(NO_WAIT);
6039   }
6040 }
6041 
6042 int
forceGCPWait(int type)6043 NdbDictionaryImpl::forceGCPWait(int type)
6044 {
6045   return m_receiver.forceGCPWait(type);
6046 }
6047 
6048 int
forceGCPWait(int type)6049 NdbDictInterface::forceGCPWait(int type)
6050 {
6051   NdbApiSignal tSignal(m_reference);
6052   if (type == 0 || type == 2)
6053   {
6054     WaitGCPReq* const req = CAST_PTR(WaitGCPReq, tSignal.getDataPtrSend());
6055     req->senderRef = m_reference;
6056     req->senderData = 0;
6057     req->requestType =
6058       type == 0 ?
6059       WaitGCPReq::CompleteForceStart : WaitGCPReq::RestartGCI;
6060 
6061     tSignal.theReceiversBlockNumber = DBDIH;
6062     tSignal.theVerId_signalNumber = GSN_WAIT_GCP_REQ;
6063     tSignal.theLength = WaitGCPReq::SignalLength;
6064 
6065     const Uint32 RETRIES = 100;
6066     for (Uint32 i = 0; i < RETRIES; i++)
6067     {
6068       PollGuard pg(* m_impl);
6069       Uint16 aNodeId = getTransporter()->get_an_alive_node();
6070       if (aNodeId == 0) {
6071         m_error.code= 4009;
6072         return -1;
6073       }
6074       if (m_impl->sendSignal(&tSignal, aNodeId) != 0)
6075       {
6076         continue;
6077       }
6078 
6079       m_error.code= 0;
6080 
6081       m_impl->incClientStat(Ndb::WaitMetaRequestCount, 1);
6082       int ret_val= pg.wait_n_unlock(DICT_WAITFOR_TIMEOUT,
6083                                     aNodeId, WAIT_LIST_TABLES_CONF);
6084       // end protected
6085       if (ret_val == 0 && m_error.code == 0)
6086         return 0;
6087       if (ret_val == -2) //WAIT_NODE_FAILURE
6088         continue;
6089       return -1;
6090     }
6091     return -1;
6092   }
6093   else if (type == 1)
6094   {
6095     tSignal.getDataPtrSend()[0] = 6099;
6096     tSignal.theReceiversBlockNumber = DBDIH;
6097     tSignal.theVerId_signalNumber = GSN_DUMP_STATE_ORD;
6098     tSignal.theLength = 1;
6099 
6100     const Uint32 RETRIES = 100;
6101     for (Uint32 i = 0; i < RETRIES; i++)
6102     {
6103       m_impl->lock();
6104       Uint16 aNodeId = getTransporter()->get_an_alive_node();
6105       if (aNodeId == 0) {
6106         m_error.code= 4009;
6107         m_impl->unlock();
6108         return -1;
6109       }
6110       if (m_impl->sendSignal(&tSignal, aNodeId) != 0) {
6111         m_impl->unlock();
6112         continue;
6113       }
6114 
6115       m_impl->do_forceSend();
6116       m_impl->unlock();
6117     }
6118     return m_error.code == 0 ? 0 : -1;
6119   }
6120   else
6121   {
6122     m_error.code = 4003;
6123   }
6124   return -1;
6125 }
6126 
6127 int
getRestartGCI(Uint32 * gci)6128 NdbDictionaryImpl::getRestartGCI(Uint32 * gci)
6129 {
6130   int res = m_receiver.forceGCPWait(2);
6131   if (res == 0 && gci != 0)
6132   {
6133     * gci = m_receiver.m_data.m_wait_gcp_conf.gci_hi;
6134   }
6135   return res;
6136 }
6137 
6138 void
execWAIT_GCP_CONF(const NdbApiSignal * signal,const LinearSectionPtr ptr[3])6139 NdbDictInterface::execWAIT_GCP_CONF(const NdbApiSignal* signal,
6140 				    const LinearSectionPtr ptr[3])
6141 {
6142   const WaitGCPConf* conf = CAST_CONSTPTR(WaitGCPConf, signal->getDataPtr());
6143 
6144   m_data.m_wait_gcp_conf.gci_lo = conf->gci_lo;
6145   m_data.m_wait_gcp_conf.gci_hi = conf->gci_hi;
6146   m_impl->theWaiter.signal(NO_WAIT);
6147 }
6148 
6149 void
execWAIT_GCP_REF(const NdbApiSignal * signal,const LinearSectionPtr ptr[3])6150 NdbDictInterface::execWAIT_GCP_REF(const NdbApiSignal* signal,
6151                                    const LinearSectionPtr ptr[3])
6152 {
6153   const WaitGCPRef* ref = CAST_CONSTPTR(WaitGCPRef, signal->getDataPtr());
6154   m_error.code = ref->errorCode;
6155 
6156   m_impl->theWaiter.signal(NO_WAIT);
6157 }
6158 
NdbFilegroupImpl(NdbDictionary::Object::Type t)6159 NdbFilegroupImpl::NdbFilegroupImpl(NdbDictionary::Object::Type t)
6160   : NdbDictObjectImpl(t)
6161 {
6162   m_extent_size = 0;
6163   m_undo_buffer_size = 0;
6164   m_logfile_group_id = RNIL;
6165   m_logfile_group_version = ~0;
6166 }
6167 
NdbTablespaceImpl()6168 NdbTablespaceImpl::NdbTablespaceImpl() :
6169   NdbDictionary::Tablespace(* this),
6170   NdbFilegroupImpl(NdbDictionary::Object::Tablespace), m_facade(this)
6171 {
6172 }
6173 
NdbTablespaceImpl(NdbDictionary::Tablespace & f)6174 NdbTablespaceImpl::NdbTablespaceImpl(NdbDictionary::Tablespace & f) :
6175   NdbDictionary::Tablespace(* this),
6176   NdbFilegroupImpl(NdbDictionary::Object::Tablespace), m_facade(&f)
6177 {
6178 }
6179 
~NdbTablespaceImpl()6180 NdbTablespaceImpl::~NdbTablespaceImpl(){
6181 }
6182 
6183 int
assign(const NdbTablespaceImpl & org)6184 NdbTablespaceImpl::assign(const NdbTablespaceImpl& org)
6185 {
6186   m_id = org.m_id;
6187   m_version = org.m_version;
6188   m_status = org.m_status;
6189   m_type = org.m_type;
6190 
6191   if (!m_name.assign(org.m_name))
6192     return -1;
6193   m_grow_spec = org.m_grow_spec;
6194   m_extent_size = org.m_extent_size;
6195   m_undo_free_words = org.m_undo_free_words;
6196   m_logfile_group_id = org.m_logfile_group_id;
6197   m_logfile_group_version = org.m_logfile_group_version;
6198   if (!m_logfile_group_name.assign(org.m_logfile_group_name))
6199     return -1;
6200   m_undo_free_words = org.m_undo_free_words;
6201   return 0;
6202 }
6203 
NdbLogfileGroupImpl()6204 NdbLogfileGroupImpl::NdbLogfileGroupImpl() :
6205   NdbDictionary::LogfileGroup(* this),
6206   NdbFilegroupImpl(NdbDictionary::Object::LogfileGroup), m_facade(this)
6207 {
6208 }
6209 
NdbLogfileGroupImpl(NdbDictionary::LogfileGroup & f)6210 NdbLogfileGroupImpl::NdbLogfileGroupImpl(NdbDictionary::LogfileGroup & f) :
6211   NdbDictionary::LogfileGroup(* this),
6212   NdbFilegroupImpl(NdbDictionary::Object::LogfileGroup), m_facade(&f)
6213 {
6214 }
6215 
~NdbLogfileGroupImpl()6216 NdbLogfileGroupImpl::~NdbLogfileGroupImpl(){
6217 }
6218 
6219 int
assign(const NdbLogfileGroupImpl & org)6220 NdbLogfileGroupImpl::assign(const NdbLogfileGroupImpl& org)
6221 {
6222   m_id = org.m_id;
6223   m_version = org.m_version;
6224   m_status = org.m_status;
6225   m_type = org.m_type;
6226 
6227   if (!m_name.assign(org.m_name))
6228     return -1;
6229   m_grow_spec = org.m_grow_spec;
6230   m_extent_size = org.m_extent_size;
6231   m_undo_free_words = org.m_undo_free_words;
6232   m_logfile_group_id = org.m_logfile_group_id;
6233   m_logfile_group_version = org.m_logfile_group_version;
6234   if (!m_logfile_group_name.assign(org.m_logfile_group_name))
6235     return -1;
6236   m_undo_free_words = org.m_undo_free_words;
6237   return 0;
6238 }
6239 
NdbFileImpl(NdbDictionary::Object::Type t)6240 NdbFileImpl::NdbFileImpl(NdbDictionary::Object::Type t)
6241   : NdbDictObjectImpl(t)
6242 {
6243   m_size = 0;
6244   m_free = 0;
6245   m_filegroup_id = RNIL;
6246   m_filegroup_version = ~0;
6247 }
6248 
NdbDatafileImpl()6249 NdbDatafileImpl::NdbDatafileImpl() :
6250   NdbDictionary::Datafile(* this),
6251   NdbFileImpl(NdbDictionary::Object::Datafile), m_facade(this)
6252 {
6253 }
6254 
NdbDatafileImpl(NdbDictionary::Datafile & f)6255 NdbDatafileImpl::NdbDatafileImpl(NdbDictionary::Datafile & f) :
6256   NdbDictionary::Datafile(* this),
6257   NdbFileImpl(NdbDictionary::Object::Datafile), m_facade(&f)
6258 {
6259 }
6260 
~NdbDatafileImpl()6261 NdbDatafileImpl::~NdbDatafileImpl(){
6262 }
6263 
6264 int
assign(const NdbDatafileImpl & org)6265 NdbDatafileImpl::assign(const NdbDatafileImpl& org)
6266 {
6267   m_id = org.m_id;
6268   m_version = org.m_version;
6269   m_status = org.m_status;
6270   m_type = org.m_type;
6271 
6272   m_size = org.m_size;
6273   m_free = org.m_free;
6274   m_filegroup_id = org.m_filegroup_id;
6275   m_filegroup_version = org.m_filegroup_version;
6276   if (!m_path.assign(org.m_path) ||
6277       !m_filegroup_name.assign(org.m_filegroup_name))
6278     return -1;
6279   return 0;
6280 }
6281 
NdbUndofileImpl()6282 NdbUndofileImpl::NdbUndofileImpl() :
6283   NdbDictionary::Undofile(* this),
6284   NdbFileImpl(NdbDictionary::Object::Undofile), m_facade(this)
6285 {
6286 }
6287 
NdbUndofileImpl(NdbDictionary::Undofile & f)6288 NdbUndofileImpl::NdbUndofileImpl(NdbDictionary::Undofile & f) :
6289   NdbDictionary::Undofile(* this),
6290   NdbFileImpl(NdbDictionary::Object::Undofile), m_facade(&f)
6291 {
6292 }
6293 
~NdbUndofileImpl()6294 NdbUndofileImpl::~NdbUndofileImpl(){
6295 }
6296 
6297 int
assign(const NdbUndofileImpl & org)6298 NdbUndofileImpl::assign(const NdbUndofileImpl& org)
6299 {
6300   m_id = org.m_id;
6301   m_version = org.m_version;
6302   m_status = org.m_status;
6303   m_type = org.m_type;
6304 
6305   m_size = org.m_size;
6306   m_free = org.m_free;
6307   m_filegroup_id = org.m_filegroup_id;
6308   m_filegroup_version = org.m_filegroup_version;
6309   if (!m_path.assign(org.m_path) ||
6310       !m_filegroup_name.assign(org.m_filegroup_name))
6311     return 4000;
6312   return 0;
6313 }
6314 
6315 int
createDatafile(const NdbDatafileImpl & file,bool force,NdbDictObjectImpl * obj)6316 NdbDictionaryImpl::createDatafile(const NdbDatafileImpl & file,
6317 				  bool force,
6318 				  NdbDictObjectImpl* obj)
6319 
6320 {
6321   DBUG_ENTER("NdbDictionaryImpl::createDatafile");
6322   NdbFilegroupImpl tmp(NdbDictionary::Object::Tablespace);
6323   if(file.m_filegroup_version != ~(Uint32)0){
6324     tmp.m_id = file.m_filegroup_id;
6325     tmp.m_version = file.m_filegroup_version;
6326     DBUG_RETURN(m_receiver.create_file(file, tmp, force, obj));
6327   }
6328 
6329 
6330   if(m_receiver.get_filegroup(tmp, NdbDictionary::Object::Tablespace,
6331 			      file.m_filegroup_name.c_str()) == 0){
6332     DBUG_RETURN(m_receiver.create_file(file, tmp, force, obj));
6333   }
6334   DBUG_RETURN(-1);
6335 }
6336 
6337 int
dropDatafile(const NdbDatafileImpl & file)6338 NdbDictionaryImpl::dropDatafile(const NdbDatafileImpl & file){
6339   return m_receiver.drop_file(file);
6340 }
6341 
6342 int
createUndofile(const NdbUndofileImpl & file,bool force,NdbDictObjectImpl * obj)6343 NdbDictionaryImpl::createUndofile(const NdbUndofileImpl & file,
6344 				  bool force,
6345 				  NdbDictObjectImpl* obj)
6346 {
6347   DBUG_ENTER("NdbDictionaryImpl::createUndofile");
6348   NdbFilegroupImpl tmp(NdbDictionary::Object::LogfileGroup);
6349   if(file.m_filegroup_version != ~(Uint32)0){
6350     tmp.m_id = file.m_filegroup_id;
6351     tmp.m_version = file.m_filegroup_version;
6352     DBUG_RETURN(m_receiver.create_file(file, tmp, force, obj));
6353   }
6354 
6355 
6356   if(m_receiver.get_filegroup(tmp, NdbDictionary::Object::LogfileGroup,
6357 			      file.m_filegroup_name.c_str()) == 0){
6358     DBUG_RETURN(m_receiver.create_file(file, tmp, force, obj));
6359   }
6360   DBUG_PRINT("info", ("Failed to find filegroup"));
6361   m_error.code = 789;
6362   DBUG_RETURN(-1);
6363 }
6364 
6365 int
dropUndofile(const NdbUndofileImpl & file)6366 NdbDictionaryImpl::dropUndofile(const NdbUndofileImpl & file)
6367 {
6368   return m_receiver.drop_file(file);
6369 }
6370 
6371 int
createTablespace(const NdbTablespaceImpl & fg,NdbDictObjectImpl * obj)6372 NdbDictionaryImpl::createTablespace(const NdbTablespaceImpl & fg,
6373 				    NdbDictObjectImpl* obj)
6374 {
6375   return m_receiver.create_filegroup(fg, obj);
6376 }
6377 
6378 int
dropTablespace(const NdbTablespaceImpl & fg)6379 NdbDictionaryImpl::dropTablespace(const NdbTablespaceImpl & fg)
6380 {
6381   return m_receiver.drop_filegroup(fg);
6382 }
6383 
6384 int
createLogfileGroup(const NdbLogfileGroupImpl & fg,NdbDictObjectImpl * obj)6385 NdbDictionaryImpl::createLogfileGroup(const NdbLogfileGroupImpl & fg,
6386 				      NdbDictObjectImpl* obj)
6387 {
6388   return m_receiver.create_filegroup(fg, obj);
6389 }
6390 
6391 int
dropLogfileGroup(const NdbLogfileGroupImpl & fg)6392 NdbDictionaryImpl::dropLogfileGroup(const NdbLogfileGroupImpl & fg)
6393 {
6394   return m_receiver.drop_filegroup(fg);
6395 }
6396 
6397 static int
cmp_ndbrec_attr(const void * a,const void * b)6398 cmp_ndbrec_attr(const void *a, const void *b)
6399 {
6400   const NdbRecord::Attr *r1= (const NdbRecord::Attr *)a;
6401   const NdbRecord::Attr *r2= (const NdbRecord::Attr *)b;
6402   if(r1->attrId < r2->attrId)
6403     return -1;
6404   else if(r1->attrId == r2->attrId)
6405     return 0;
6406   else
6407     return 1;
6408 }
6409 
6410 struct BitRange{
6411   Uint64 start; /* First occupied bit */
6412   Uint64 end; /* Last occupied bit */
6413 };
6414 
6415 static int
cmp_bitrange(const void * a,const void * b)6416 cmp_bitrange(const void* a, const void* b)
6417 {
6418   /* Sort them by start bit */
6419   const BitRange& brA= *(const BitRange*)a;
6420   const BitRange& brB= *(const BitRange*)b;
6421 
6422   if (brA.start < brB.start)
6423     return -1;
6424   else if (brA.start == brB.start)
6425     return 0;
6426   else
6427     return 1;
6428 }
6429 
6430 bool
validateRecordSpec(const NdbDictionary::RecordSpecification * recSpec,Uint32 length,Uint32 flags)6431 NdbDictionaryImpl::validateRecordSpec(const NdbDictionary::RecordSpecification *recSpec,
6432                                       Uint32 length,
6433                                       Uint32 flags)
6434 {
6435   /* We check that there's no overlap between any of the data values
6436    * or Null bits
6437    */
6438 
6439   /* Column data + NULL bits with at least 1 non nullable PK */
6440   const Uint32 MaxRecordElements= (2* NDB_MAX_ATTRIBUTES_IN_TABLE) - 1;
6441   Uint32 numElements= 0;
6442   BitRange bitRanges[ MaxRecordElements ];
6443 
6444   if (length > NDB_MAX_ATTRIBUTES_IN_TABLE)
6445   {
6446     m_error.code= 4548;
6447     return false;
6448   }
6449 
6450   /* Populate bitRanges array with ranges of bits occupied by
6451    * data values and null bits
6452    */
6453   for (Uint32 rs=0; rs < length; rs++)
6454   {
6455     const NdbDictionary::Column* col= recSpec[rs].column;
6456     Uint64 elementByteOffset= recSpec[rs].offset;
6457     Uint64 elementByteLength= col->getSizeInBytes();
6458     Uint64 nullLength= col->getNullable() ? 1 : 0;
6459 
6460     /* Blobs 'data' just occupies the size of an NdbBlob ptr */
6461     const NdbDictionary::Column::Type type= col->getType();
6462     const bool isBlob=
6463       (type == NdbDictionary::Column::Blob) ||
6464       (type == NdbDictionary::Column::Text);
6465 
6466     if (isBlob)
6467     {
6468       elementByteLength= sizeof(NdbBlob*);
6469     }
6470 
6471     if ((type == NdbDictionary::Column::Bit) &&
6472         (flags & NdbDictionary::RecMysqldBitfield))
6473     {
6474       /* MySQLD Bit format puts 'fractional' part of bit types
6475        * in with the null bits - so there's 1 optional Null
6476        * bit followed by n (max 7) databits, at position
6477        * given by the nullbit offsets.  Then the rest of
6478        * the bytes go at the normal offset position.
6479        */
6480       Uint32 bitLength= col->getLength();
6481       Uint32 fractionalBits= bitLength % 8;
6482       nullLength+= fractionalBits;
6483       elementByteLength= bitLength / 8;
6484     }
6485 
6486     /* Does the element itself have any bytes?
6487      * (MySQLD bit format may have all data as 'null bits'
6488      */
6489     if (elementByteLength)
6490     {
6491       bitRanges[numElements].start= 8 * elementByteOffset;
6492       bitRanges[numElements].end= (8 * (elementByteOffset + elementByteLength)) - 1;
6493 
6494       numElements++;
6495     }
6496 
6497     if (nullLength)
6498     {
6499       bitRanges[numElements].start=
6500         (8* recSpec[rs].nullbit_byte_offset) +
6501         recSpec[rs].nullbit_bit_in_byte;
6502       bitRanges[numElements].end= bitRanges[numElements].start +
6503         (nullLength -1);
6504 
6505       numElements++;
6506     }
6507   }
6508 
6509   /* Now sort the 'elements' by start bit */
6510   qsort(bitRanges,
6511         numElements,
6512         sizeof(BitRange),
6513         cmp_bitrange);
6514 
6515   Uint64 endOfPreviousRange= bitRanges[0].end;
6516 
6517   /* Now check that there's no overlaps */
6518   for (Uint32 rangeNum= 1; rangeNum < numElements; rangeNum++)
6519   {
6520     if (unlikely((bitRanges[rangeNum].start <= endOfPreviousRange)))
6521     {
6522       /* Oops, this range overlaps with previous one */
6523       m_error.code= 4547;
6524       return false;
6525     }
6526     endOfPreviousRange= bitRanges[rangeNum].end;
6527   }
6528 
6529   /* All relevant ranges are distinct */
6530   return true;
6531 }
6532 
6533 
6534 /* ndb_set_record_specification
6535  * This procedure sets the contents of the passed RecordSpecification
6536  * for the given column in the given table.
6537  * The column is placed at the storageOffset given, and a new
6538  * storageOffset, beyond the end of this column, is returned.
6539  * Null bits are stored at the start of the row in consecutive positions.
6540  * The caller must ensure that enough space exists for all of the nullable
6541  * columns, before the first bit of data.
6542  * The new storageOffset is returned.
6543  */
6544 static Uint32
ndb_set_record_specification(Uint32 storageOffset,Uint32 field_num,Uint32 & nullableColNum,NdbDictionary::RecordSpecification * spec,NdbColumnImpl * col)6545 ndb_set_record_specification(Uint32 storageOffset,
6546                              Uint32 field_num,
6547                              Uint32& nullableColNum,
6548                              NdbDictionary::RecordSpecification *spec,
6549                              NdbColumnImpl *col)
6550 {
6551   spec->column= col->m_facade;
6552 
6553   spec->offset= storageOffset;
6554   /* For Blobs we just need the NdbBlob* */
6555   const Uint32 sizeOfElement= col->getBlobType() ?
6556     sizeof(NdbBlob*) :
6557     spec->column->getSizeInBytes();
6558 
6559   if (spec->column->getNullable())
6560   {
6561     spec->nullbit_byte_offset= (nullableColNum >> 3);
6562     spec->nullbit_bit_in_byte= (nullableColNum & 7);
6563     nullableColNum ++;
6564   }
6565   else
6566   {
6567     /* For non-nullable columns, use visibly bad offsets */
6568     spec->nullbit_byte_offset= ~0;
6569     spec->nullbit_bit_in_byte= ~0;
6570   }
6571 
6572   return storageOffset + sizeOfElement;
6573 }
6574 
6575 
6576 /* This method creates an NdbRecord for the given table or index which
6577  * contains all columns (except pseudo columns).
6578  * For a table, only the tableOrIndex parameter should be supplied.
6579  * For an index, the index 'table object' should be supplied as the
6580  * tableOrIndex parameter, and the underlying indexed table object
6581  * should be supplied as the baseTableForIndex parameter.
6582  * The underlying table object is required to get the correct column
6583  * objects to build the NdbRecord object.
6584  * The record is created with all null bits packed together starting
6585  * from the first word, in attrId order, followed by all attributes
6586  * in attribute order.
6587  */
6588 int
createDefaultNdbRecord(NdbTableImpl * tableOrIndex,const NdbTableImpl * baseTableForIndex)6589 NdbDictionaryImpl::createDefaultNdbRecord(NdbTableImpl *tableOrIndex,
6590                                           const NdbTableImpl *baseTableForIndex)
6591 {
6592   /* We create a full NdbRecord for the columns in the table
6593    */
6594   DBUG_ENTER("NdbDictionaryImpl::createNdbRecords()");
6595   NdbDictionary::RecordSpecification spec[NDB_MAX_ATTRIBUTES_IN_TABLE];
6596   NdbRecord *rec;
6597   Uint32 i;
6598   Uint32 numCols= tableOrIndex->m_columns.size();
6599   // Reserve space for Null bits at the start
6600   Uint32 baseTabCols= numCols;
6601   unsigned char* pkMask= NULL;
6602   bool isIndex= false;
6603 
6604   if (baseTableForIndex != NULL)
6605   {
6606     /* Check we've really got an index */
6607     assert((tableOrIndex->m_indexType == NdbDictionary::Object::OrderedIndex ||
6608             tableOrIndex->m_indexType == NdbDictionary::Object::UniqueHashIndex));
6609 
6610     /* Update baseTabCols to real number of cols in indexed table */
6611     baseTabCols= baseTableForIndex->m_columns.size();
6612 
6613     /* Ignore extra info column at end of index table */
6614     numCols--;
6615 
6616     isIndex= true;
6617 
6618     // Could do further string checks to make sure the base table and
6619     // index are related
6620   }
6621   else
6622   {
6623     /* Check we've not got an index */
6624     assert((tableOrIndex->m_indexType != NdbDictionary::Object::OrderedIndex &&
6625             tableOrIndex->m_indexType != NdbDictionary::Object::UniqueHashIndex));
6626   }
6627 
6628   Uint32 nullableCols= 0;
6629   /* Determine number of nullable columns */
6630   for (i=0; i<numCols; i++)
6631   {
6632     /* As the Index NdbRecord is built using Columns from the base table,
6633      * it will get/set Null according to their Nullability.
6634      * If this is an index, then we need to take the 'Nullability' from
6635      * the base table column objects - unique index table column objects
6636      * will not be nullable as they are part of the key.
6637      */
6638     const NdbColumnImpl* col= NULL;
6639 
6640     if (isIndex)
6641     {
6642       Uint32 baseTableColNum=
6643         tableOrIndex->m_index->m_columns[i]->m_keyInfoPos;
6644       col= baseTableForIndex->m_columns[baseTableColNum];
6645     }
6646     else
6647     {
6648       col= tableOrIndex->m_columns[i];
6649     }
6650 
6651     if (col->m_nullable)
6652       nullableCols ++;
6653   }
6654 
6655   /* Offset of first byte of data in the NdbRecord */
6656   Uint32 offset= (nullableCols+7) / 8;
6657 
6658   /* Allocate and zero column presence bitmasks */
6659   Uint32 bitMaskBytes= (baseTabCols + 7) / 8;
6660   pkMask=    (unsigned char*) calloc(1, bitMaskBytes);
6661 
6662   if (pkMask == NULL)
6663   {
6664     /* Memory allocation problem */
6665     m_error.code= 4000;
6666     return -1;
6667   }
6668 
6669   Uint32 nullableColNum= 0;
6670 
6671   /* Build record specification array for this table. */
6672   for (i= 0; i < numCols; i++)
6673   {
6674     /* Have to use columns from 'real' table for indexes as described
6675      * in NdbRecord documentation
6676      */
6677     NdbColumnImpl *col= NULL;
6678 
6679     if (isIndex)
6680     {
6681       /* From index table, get m_index pointer to NdbIndexImpl object.
6682        * m_index has m_key_ids[] array mapping index column numbers to
6683        * real table column numbers.
6684        * Use this number to get the correct column object from the
6685        * base table structure
6686        * No need to worry about Blobs here as Blob columns can't be
6687        * indexed
6688        */
6689       Uint32 baseTableColNum=
6690         tableOrIndex->m_index->m_columns[i]->m_keyInfoPos;
6691       col= baseTableForIndex->m_columns[baseTableColNum];
6692 
6693       /* Set pk bitmask bit based on the base-table col number of this
6694        * column
6695        */
6696       assert( baseTableColNum < baseTabCols);
6697       pkMask[ baseTableColNum >> 3 ] |= ( 1 << ( baseTableColNum & 7 ));
6698     }
6699     else
6700     {
6701       col= tableOrIndex->m_columns[i];
6702 
6703       if (col->m_pk)
6704       {
6705         /* Set pk bitmask bit based on the col number of this column */
6706         pkMask[ i >> 3 ] |= ( 1 << (i & 7));
6707       }
6708 
6709       /* If this column's a Blob then we need to create
6710        * a default NdbRecord for the Blob table too
6711        * (unless it's a really small one with no parts table).
6712        */
6713       if (col->getBlobType() && col->getPartSize() != 0)
6714       {
6715         if (likely(col->m_blobTable != NULL))
6716         {
6717           int res= createDefaultNdbRecord(col->m_blobTable, NULL);
6718           if (res != 0)
6719           {
6720             free(pkMask);
6721             DBUG_RETURN(-1);
6722           }
6723         }
6724         else
6725         {
6726           if (!ignore_broken_blob_tables())
6727           {
6728             assert(false);
6729             /* 4263 - Invalid blob attributes or invalid blob parts table */
6730             m_error.code = 4263;
6731             free(pkMask);
6732             DBUG_RETURN(-1);
6733           }
6734         }
6735       }
6736     }
6737 
6738     offset= ndb_set_record_specification(offset,
6739                                          i,
6740                                          nullableColNum,
6741                                          &spec[i],
6742                                          col);
6743   }
6744 
6745   rec= createRecord(tableOrIndex,
6746                     spec,
6747                     numCols,
6748                     sizeof(spec[0]),
6749                     0,              // No special flags
6750                     true);          // default record
6751   if (rec == NULL)
6752   {
6753     free(pkMask);
6754     DBUG_RETURN(-1);
6755   }
6756 
6757   /* Store in the table definition */
6758   tableOrIndex->m_ndbrecord= rec;
6759   tableOrIndex->m_pkMask= pkMask;
6760 
6761   DBUG_RETURN(0);
6762 }
6763 
6764 /* This method initialises the data for a single
6765  * column in the passed NdbRecord structure
6766  */
6767 int
initialiseColumnData(bool isIndex,Uint32 flags,const NdbDictionary::RecordSpecification * recSpec,Uint32 colNum,NdbRecord * rec)6768 NdbDictionaryImpl::initialiseColumnData(bool isIndex,
6769                                         Uint32 flags,
6770                                         const NdbDictionary::RecordSpecification *recSpec,
6771                                         Uint32 colNum,
6772                                         NdbRecord *rec)
6773 {
6774   const NdbColumnImpl *col= &NdbColumnImpl::getImpl(*(recSpec->column));
6775   if (!col)
6776   {
6777     // Missing column specification in NdbDictionary::RecordSpecification
6778     m_error.code= 4290;
6779     return -1;
6780   }
6781 
6782   if (col->m_attrId & AttributeHeader::PSEUDO)
6783   {
6784     /* Pseudo columns not supported by NdbRecord */
6785     m_error.code= 4523;
6786     return -1;
6787   }
6788 
6789   if (col->m_indexSourced)
6790   {
6791     // Attempt to pass an index column to createRecord...
6792     m_error.code= 4540;
6793     return -1;
6794   }
6795 
6796   NdbRecord::Attr *recCol= &rec->columns[colNum];
6797   recCol->attrId= col->m_attrId;
6798   recCol->column_no= col->m_column_no;
6799   recCol->index_attrId= ~0;
6800   recCol->offset= recSpec->offset;
6801   recCol->maxSize= col->m_attrSize*col->m_arraySize;
6802   recCol->orgAttrSize= col->m_orgAttrSize;
6803   if (recCol->offset+recCol->maxSize > rec->m_row_size)
6804     rec->m_row_size= recCol->offset+recCol->maxSize;
6805   /* Round data size to whole words + 4 bytes of AttributeHeader. */
6806   rec->m_max_transid_ai_bytes+= (recCol->maxSize+7) & ~3;
6807   recCol->charset_info= col->m_cs;
6808   recCol->compare_function= NdbSqlUtil::getType(col->m_type).m_cmp;
6809   recCol->flags= 0;
6810   if (!isIndex && col->m_pk)
6811     recCol->flags|= NdbRecord::IsKey;
6812   /* For indexes, we set key membership below. */
6813   if (col->m_storageType == NDB_STORAGETYPE_DISK)
6814     recCol->flags|= NdbRecord::IsDisk;
6815   if (col->m_nullable)
6816   {
6817     recCol->flags|= NdbRecord::IsNullable;
6818     recCol->nullbit_byte_offset= recSpec->nullbit_byte_offset;
6819     recCol->nullbit_bit_in_byte= recSpec->nullbit_bit_in_byte;
6820 
6821     const Uint32 nullbit_byte= recSpec->nullbit_byte_offset +
6822       (recSpec->nullbit_bit_in_byte >> 3);
6823     if (nullbit_byte >= rec->m_row_size)
6824       rec->m_row_size= nullbit_byte + 1;
6825   }
6826   if (col->m_arrayType==NDB_ARRAYTYPE_SHORT_VAR)
6827   {
6828     recCol->flags|= NdbRecord::IsVar1ByteLen;
6829     if (flags & NdbDictionary::RecMysqldShrinkVarchar)
6830       recCol->flags|= NdbRecord::IsMysqldShrinkVarchar;
6831   }
6832   else if (col->m_arrayType==NDB_ARRAYTYPE_MEDIUM_VAR)
6833   {
6834     recCol->flags|= NdbRecord::IsVar2ByteLen;
6835   }
6836   if (col->m_type == NdbDictionary::Column::Bit)
6837   {
6838     recCol->bitCount= col->m_length;
6839     if (flags & NdbDictionary::RecMysqldBitfield)
6840     {
6841       recCol->flags|= NdbRecord::IsMysqldBitfield;
6842       if (!(col->m_nullable))
6843       {
6844         /*
6845           We need these to access the overflow bits stored within
6846           the null bitmap.
6847         */
6848         recCol->nullbit_byte_offset= recSpec->nullbit_byte_offset;
6849         recCol->nullbit_bit_in_byte= recSpec->nullbit_bit_in_byte;
6850       }
6851     }
6852   }
6853   else
6854     recCol->bitCount= 0;
6855   if (col->m_distributionKey)
6856     recCol->flags|= NdbRecord::IsDistributionKey;
6857   if (col->getBlobType())
6858   {
6859     recCol->flags|= NdbRecord::IsBlob;
6860     rec->flags|= NdbRecord::RecHasBlob;
6861   }
6862   return 0;
6863 }
6864 
6865 /**
6866  * createRecord
6867  * Create an NdbRecord object using the table implementation and
6868  * RecordSpecification array passed.
6869  * The table pointer may be a proper table, or the underlying
6870  * table of an Index.  In any case, it is assumed that is is a
6871  * global table object, which may be safely shared between
6872  * multiple threads.  The responsibility for ensuring that it is
6873  * a global object rests with the caller
6874  */
6875 NdbRecord *
createRecord(const NdbTableImpl * table,const NdbDictionary::RecordSpecification * recSpec,Uint32 length,Uint32 elemSize,Uint32 flags,bool defaultRecord)6876 NdbDictionaryImpl::createRecord(const NdbTableImpl *table,
6877                                 const NdbDictionary::RecordSpecification *recSpec,
6878                                 Uint32 length,
6879                                 Uint32 elemSize,
6880                                 Uint32 flags,
6881                                 bool defaultRecord)
6882 {
6883   NdbRecord *rec= NULL;
6884   Uint32 numKeys, tableNumKeys, numIndexDistrKeys, min_distkey_prefix_length;
6885   Uint32 oldAttrId;
6886   bool isIndex;
6887   Uint32 i;
6888 
6889   /*
6890     In later versions we can use elemSize to provide backwards
6891     compatibility if we extend the RecordSpecification structure.
6892   */
6893   if (elemSize != sizeof(NdbDictionary::RecordSpecification))
6894   {
6895     m_error.code= 4289;
6896     return NULL;
6897   }
6898 
6899   if (!validateRecordSpec(recSpec, length, flags))
6900   {
6901     /* Error set in call */
6902     return NULL;
6903   }
6904 
6905   isIndex= (table->m_indexType==NdbDictionary::Object::OrderedIndex ||
6906             table->m_indexType==NdbDictionary::Object::UniqueHashIndex);
6907 
6908   /* Count the number of key columns in the table or index. */
6909   if (isIndex)
6910   {
6911     assert(table->m_index);
6912     /* Ignore the extra NDB$TNODE column at the end. */
6913     tableNumKeys= table->m_columns.size() - 1;
6914   }
6915   else
6916   {
6917     tableNumKeys= 0;
6918     for (i= 0; i<table->m_columns.size(); i++)
6919     {
6920       if (table->m_columns[i]->m_pk)
6921         tableNumKeys++;
6922     }
6923   }
6924   Uint32 tableNumDistKeys;
6925   if (isIndex || table->m_noOfDistributionKeys != 0)
6926     tableNumDistKeys= table->m_noOfDistributionKeys;
6927   else
6928     tableNumDistKeys= table->m_noOfKeys;
6929 
6930   int max_attrId = -1;
6931   for (i = 0; i < length; i++)
6932   {
6933     Uint32 attrId = recSpec[i].column->getAttrId();
6934     if ((int)attrId > max_attrId)
6935       max_attrId = (int)attrId;
6936   }
6937   Uint32 attrId_indexes_length = (Uint32)(max_attrId + 1);
6938 
6939   /*
6940     We need to allocate space for
6941      1. The struct itself.
6942      2. The columns[] array at the end of struct (length #columns).
6943      3. An extra Uint32 array key_indexes (length #key columns).
6944      4. An extra Uint32 array distkey_indexes (length #distribution keys).
6945      5. An extra int array attrId_indexes (length max attrId)
6946   */
6947   const Uint32 ndbRecBytes= sizeof(NdbRecord);
6948   const Uint32 colArrayBytes= (length-1)*sizeof(NdbRecord::Attr);
6949   const Uint32 tableKeyMapBytes= tableNumKeys*sizeof(Uint32);
6950   const Uint32 tableDistKeyMapBytes= tableNumDistKeys*sizeof(Uint32);
6951   const Uint32 attrIdMapBytes= attrId_indexes_length*sizeof(int);
6952   rec= (NdbRecord *)calloc(1, ndbRecBytes +
6953                               colArrayBytes +
6954                               tableKeyMapBytes +
6955                               tableDistKeyMapBytes +
6956                               attrIdMapBytes);
6957   if (!rec)
6958   {
6959     m_error.code= 4000;
6960     return NULL;
6961   }
6962   Uint32 *key_indexes= (Uint32 *)((unsigned char *)rec +
6963                                   ndbRecBytes +
6964                                   colArrayBytes);
6965   Uint32 *distkey_indexes= (Uint32 *)((unsigned char *)rec +
6966                                       ndbRecBytes +
6967                                       colArrayBytes +
6968                                       tableKeyMapBytes);
6969   int *attrId_indexes = (int *)((unsigned char *)rec +
6970                                 ndbRecBytes +
6971                                 colArrayBytes +
6972                                 tableKeyMapBytes +
6973                                 tableDistKeyMapBytes);
6974   for (i = 0; i < attrId_indexes_length; i++)
6975     attrId_indexes[i] = -1;
6976 
6977   rec->table= table;
6978   rec->tableId= table->m_id;
6979   rec->tableVersion= table->m_version;
6980   rec->flags= 0;
6981   rec->noOfColumns= length;
6982   rec->m_no_of_distribution_keys= tableNumDistKeys;
6983 
6984   /* Check for any blobs in the base table. */
6985   for (i= 0; i<table->m_columns.size(); i++)
6986   {
6987     if (table->m_columns[i]->getBlobType())
6988     {
6989       rec->flags|= NdbRecord::RecTableHasBlob;
6990       break;
6991     }
6992   }
6993 
6994   rec->m_row_size= 0;
6995   rec->m_max_transid_ai_bytes= 0;
6996   for (i= 0; i<length; i++)
6997   {
6998     const NdbDictionary::RecordSpecification *rs= &recSpec[i];
6999 
7000     /* Initialise this column in NdbRecord from column
7001      * info
7002      */
7003     if (initialiseColumnData(isIndex,
7004                              flags,
7005                              rs,
7006                              i,
7007                              rec) != 0)
7008       goto err;
7009 
7010     /*
7011       Distibution key flag for unique index needs to be corrected
7012       to reflect the keys in the index base table
7013     */
7014     if (table->m_indexType == NdbDictionary::Object::UniqueHashIndex)
7015     {
7016       NdbRecord::Attr *recCol= &rec->columns[i];
7017       if (table->m_columns[i]->m_distributionKey)
7018         recCol->flags|= NdbRecord::IsDistributionKey;
7019       else
7020         recCol->flags&= ~NdbRecord::IsDistributionKey;
7021     }
7022   }
7023 
7024   /* Now we sort the array in attrId order. */
7025   qsort(rec->columns,
7026         rec->noOfColumns,
7027         sizeof(rec->columns[0]),
7028         cmp_ndbrec_attr);
7029 
7030   /*
7031     Now check for the presence of primary keys, and set flags for whether
7032     this NdbRecord can be used for insert and/or for specifying keys for
7033     read/update.
7034 
7035     Also test for duplicate columns, easy now that they are sorted.
7036     Also set up key_indexes array.
7037     Also compute if an index includes all of the distribution key.
7038     Also set up distkey_indexes array.
7039   */
7040 
7041   oldAttrId= ~0;
7042   numKeys= 0;
7043   min_distkey_prefix_length= 0;
7044   numIndexDistrKeys= 0;
7045   for (i= 0; i<rec->noOfColumns; i++)
7046   {
7047     NdbRecord::Attr *recCol= &rec->columns[i];
7048     if (i > 0 && oldAttrId==recCol->attrId)
7049     {
7050       m_error.code= 4291;
7051       goto err;
7052     }
7053     oldAttrId= recCol->attrId;
7054 
7055     assert(recCol->attrId < attrId_indexes_length);
7056     attrId_indexes[recCol->attrId] = i;
7057 
7058     if (isIndex)
7059     {
7060       Uint32 colNo= recCol->column_no;
7061       int key_idx;
7062       if (colNo < table->m_index->m_key_ids.size() &&
7063           (key_idx= table->m_index->m_key_ids[colNo]) != -1)
7064       {
7065         assert((Uint32)key_idx < tableNumKeys);
7066         recCol->flags|= NdbRecord::IsKey;
7067         key_indexes[key_idx]= i;
7068         recCol->index_attrId= table->m_columns[key_idx]->m_attrId;
7069         numKeys++;
7070 
7071         if (recCol->flags & NdbRecord::IsDistributionKey)
7072         {
7073           if (min_distkey_prefix_length <= (Uint32)key_idx)
7074             min_distkey_prefix_length= key_idx+1;
7075           if (numIndexDistrKeys < tableNumDistKeys)
7076             distkey_indexes[numIndexDistrKeys++]= i;
7077         }
7078       }
7079     }
7080     else
7081     {
7082       if (recCol->flags & NdbRecord::IsKey)
7083       {
7084         key_indexes[numKeys]= i;
7085         numKeys++;
7086       }
7087       if (recCol->flags & NdbRecord::IsDistributionKey)
7088       {
7089         if (numIndexDistrKeys < tableNumDistKeys)
7090           distkey_indexes[numIndexDistrKeys++]= i;
7091       }
7092     }
7093   }
7094   if (defaultRecord)
7095     rec->flags|= NdbRecord::RecIsDefaultRec;
7096 
7097   rec->key_indexes= key_indexes;
7098   rec->key_index_length= tableNumKeys;
7099   rec->m_min_distkey_prefix_length= min_distkey_prefix_length;
7100   rec->distkey_indexes= distkey_indexes;
7101   rec->distkey_index_length= numIndexDistrKeys;
7102   rec->m_attrId_indexes = attrId_indexes;
7103   rec->m_attrId_indexes_length = attrId_indexes_length;
7104 
7105   /*
7106     Since we checked for duplicates, we can check for primary key completeness
7107     simply by counting.
7108   */
7109   if (numKeys == tableNumKeys)
7110   {
7111     rec->flags|= NdbRecord::RecHasAllKeys;
7112     if (rec->noOfColumns == tableNumKeys)
7113       rec->flags|= NdbRecord::RecIsKeyRecord;
7114   }
7115   if (isIndex)
7116     rec->flags|= NdbRecord::RecIsIndex;
7117   rec->m_keyLenInWords= table->m_keyLenInWords;
7118 
7119   if (table->m_fragmentType == NdbDictionary::Object::UserDefined)
7120     rec->flags |= NdbRecord::RecHasUserDefinedPartitioning;
7121 
7122   return rec;
7123 
7124  err:
7125   if (rec)
7126     free(rec);
7127   return NULL;
7128 }
7129 
7130 void
copyMask(Uint32 * dst,const unsigned char * src) const7131 NdbRecord::copyMask(Uint32 *dst, const unsigned char *src) const
7132 {
7133   Uint32 i;
7134 
7135   BitmaskImpl::clear((NDB_MAX_ATTRIBUTES_IN_TABLE+31)>>5, dst);
7136   if (src)
7137   {
7138     for (i= 0; i<noOfColumns; i++)
7139     {
7140       Uint32 attrId= columns[i].attrId;
7141 
7142       assert(!(attrId & AttributeHeader::PSEUDO));
7143 
7144       if (src[attrId>>3] & (1 << (attrId&7)))
7145         BitmaskImpl::set((NDB_MAX_ATTRIBUTES_IN_TABLE+31)>>5, dst, attrId);
7146     }
7147   }
7148   else
7149   {
7150     for (i= 0; i<noOfColumns; i++)
7151     {
7152       Uint32 attrId= columns[i].attrId;
7153 
7154       assert(!(attrId & AttributeHeader::PSEUDO));
7155 
7156       BitmaskImpl::set((NDB_MAX_ATTRIBUTES_IN_TABLE+31)>>5, dst, attrId);
7157     }
7158   }
7159 }
7160 
7161 void
get_mysqld_bitfield(const char * src_row,char * dst_buffer) const7162 NdbRecord::Attr::get_mysqld_bitfield(const char *src_row, char *dst_buffer) const
7163 {
7164   assert(flags & IsMysqldBitfield);
7165   Uint64 bits;
7166   Uint32 remaining_bits= bitCount;
7167   Uint32 fractional_bitcount= remaining_bits % 8;
7168 
7169   /* Copy fractional bits, if any. */
7170   if (fractional_bitcount > 0)
7171   {
7172     Uint32 fractional_shift= nullbit_bit_in_byte + ((flags & IsNullable) != 0);
7173     Uint32 fractional_bits= (unsigned char)(src_row[nullbit_byte_offset]);
7174     if (fractional_shift + fractional_bitcount > 8)
7175       fractional_bits|= (unsigned char)(src_row[nullbit_byte_offset+1]) << 8;
7176     fractional_bits=
7177       (fractional_bits >> fractional_shift) & ((1 << fractional_bitcount) - 1);
7178     bits= fractional_bits;
7179   }
7180   else
7181     bits= 0;
7182 
7183   /* Copy whole bytes. The mysqld format stored bit fields big-endian. */
7184   assert(remaining_bits <= 64);
7185   const unsigned char *src_ptr= (const unsigned char *)&src_row[offset];
7186   while (remaining_bits >= 8)
7187   {
7188     bits= (bits << 8) | (*src_ptr++);
7189     remaining_bits-= 8;
7190   }
7191 
7192   Uint32 small_bits= (Uint32)bits;
7193   memcpy(dst_buffer, &small_bits, 4);
7194   if (maxSize > 4)
7195   {
7196     small_bits= (Uint32)(bits >> 32);
7197     memcpy(dst_buffer+4, &small_bits, 4);
7198   }
7199 }
7200 
7201 void
put_mysqld_bitfield(char * dst_row,const char * src_buffer) const7202 NdbRecord::Attr::put_mysqld_bitfield(char *dst_row, const char *src_buffer) const
7203 {
7204   assert(flags & IsMysqldBitfield);
7205   char *dst_ptr= &dst_row[offset];
7206   Uint64 bits;
7207   Uint32 small_bits;
7208   memcpy(&small_bits, src_buffer, 4);
7209   bits= small_bits;
7210   if (maxSize > 4)
7211   {
7212     memcpy(&small_bits, src_buffer+4, 4);
7213     bits|= ((Uint64)small_bits) << 32;
7214   }
7215 
7216   /* Copy whole bytes. The mysqld format stores bitfields big-endian. */
7217   Uint32 remaining_bits= bitCount;
7218   assert(remaining_bits <= 64);
7219   dst_ptr+= remaining_bits/8;
7220   while (remaining_bits >= 8)
7221   {
7222     *--dst_ptr= (char)(bits & 0xff);
7223     bits>>= 8;
7224     remaining_bits-= 8;
7225   }
7226 
7227   /* Copy fractional bits, if any. */
7228   if (remaining_bits > 0)
7229   {
7230     Uint32 shift= nullbit_bit_in_byte + ((flags & IsNullable) != 0);
7231     Uint32 mask= ((1 << remaining_bits) - 1) << shift;
7232     bits= (bits << shift) & mask;
7233     dst_row[nullbit_byte_offset]=
7234       Uint8((dst_row[nullbit_byte_offset] & ~mask) | bits);
7235     if (shift + remaining_bits > 8)
7236     {
7237       mask>>= 8;
7238       bits>>= 8;
7239       dst_row[nullbit_byte_offset+1]=
7240         Uint8((dst_row[nullbit_byte_offset+1] & ~mask) | bits);
7241     }
7242   }
7243 }
7244 
releaseRecord_impl(NdbRecord * rec)7245 void NdbDictionaryImpl::releaseRecord_impl(NdbRecord *rec)
7246 {
7247   if (rec)
7248   {
7249     /* Silently do nothing if they've passed the default
7250      * record in (similar to null handling behaviour)
7251      */
7252     if (!(rec->flags & NdbRecord::RecIsDefaultRec))
7253     {
7254       /* For non-default records, we need to release the
7255        * global table / index reference
7256        */
7257       if (rec->flags & NdbRecord::RecIsIndex)
7258         releaseIndexGlobal(*rec->table->m_index,
7259                            false); // Don't invalidate
7260       else
7261         releaseTableGlobal(*rec->table,
7262                            false); // Don't invalidate
7263 
7264       free(rec);
7265     }
7266   }
7267 }
7268 
7269 NdbDictionary::RecordType
getRecordType(const NdbRecord * record)7270 NdbDictionaryImpl::getRecordType(const NdbRecord* record)
7271 {
7272   if (record->flags & NdbRecord::RecIsIndex)
7273     return NdbDictionary::IndexAccess;
7274   else
7275     return NdbDictionary::TableAccess;
7276 }
7277 
7278 const char*
getRecordTableName(const NdbRecord * record)7279 NdbDictionaryImpl::getRecordTableName(const NdbRecord* record)
7280 {
7281   if (!(record->flags & NdbRecord::RecIsIndex))
7282   {
7283     return record->table->m_externalName.c_str();
7284   }
7285 
7286   return NULL;
7287 }
7288 
7289 const char*
getRecordIndexName(const NdbRecord * record)7290 NdbDictionaryImpl::getRecordIndexName(const NdbRecord* record)
7291 {
7292   if (record->flags & NdbRecord::RecIsIndex)
7293   {
7294     assert(record->table->m_index != NULL);
7295     assert(record->table->m_index->m_facade != NULL);
7296 
7297     return record->table->m_index->m_externalName.c_str();
7298   }
7299 
7300   return NULL;
7301 }
7302 
7303 bool
getNextAttrIdFrom(const NdbRecord * record,Uint32 startAttrId,Uint32 & nextAttrId)7304 NdbDictionaryImpl::getNextAttrIdFrom(const NdbRecord* record,
7305                                      Uint32 startAttrId,
7306                                      Uint32& nextAttrId)
7307 {
7308   for (Uint32 i= startAttrId; i < record->m_attrId_indexes_length; i++)
7309   {
7310     if (record->m_attrId_indexes[i] != -1)
7311     {
7312       nextAttrId= i;
7313       return true;
7314     }
7315   }
7316   return false;
7317 }
7318 
7319 bool
getOffset(const NdbRecord * record,Uint32 attrId,Uint32 & offset)7320 NdbDictionaryImpl::getOffset(const NdbRecord* record,
7321                              Uint32 attrId,
7322                              Uint32& offset)
7323 {
7324   if (attrId < record->m_attrId_indexes_length)
7325   {
7326     int attrIdIndex= record->m_attrId_indexes[attrId];
7327 
7328     if (attrIdIndex != -1)
7329     {
7330       assert(attrIdIndex < (int) record->noOfColumns);
7331 
7332       offset= record->columns[attrIdIndex].offset;
7333       return true;
7334     }
7335   }
7336 
7337   /* AttrId not part of this NdbRecord */
7338   return false;
7339 }
7340 
7341 bool
getNullBitOffset(const NdbRecord * record,Uint32 attrId,Uint32 & nullbit_byte_offset,Uint32 & nullbit_bit_in_byte)7342 NdbDictionaryImpl::getNullBitOffset(const NdbRecord* record,
7343                                     Uint32 attrId,
7344                                     Uint32& nullbit_byte_offset,
7345                                     Uint32& nullbit_bit_in_byte)
7346 {
7347   if (attrId < record->m_attrId_indexes_length)
7348   {
7349     int attrIdIndex= record->m_attrId_indexes[attrId];
7350 
7351     if (attrIdIndex != -1)
7352     {
7353       assert(attrIdIndex < (int) record->noOfColumns);
7354 
7355       NdbRecord::Attr attr= record->columns[attrIdIndex];
7356 
7357       nullbit_byte_offset= attr.nullbit_byte_offset;
7358       nullbit_bit_in_byte= attr.nullbit_bit_in_byte;
7359       return true;
7360     }
7361   }
7362 
7363   /* AttrId not part of this NdbRecord */
7364   return false;
7365 }
7366 
7367 const char*
getValuePtr(const NdbRecord * record,const char * row,Uint32 attrId)7368 NdbDictionaryImpl::getValuePtr(const NdbRecord* record,
7369                                const char* row,
7370                                Uint32 attrId)
7371 {
7372   if (attrId < record->m_attrId_indexes_length)
7373   {
7374     int attrIdIndex= record->m_attrId_indexes[attrId];
7375 
7376     if (attrIdIndex != -1)
7377     {
7378       assert(attrIdIndex < (int) record->noOfColumns);
7379 
7380       return row + (record->columns[attrIdIndex].offset);
7381     }
7382   }
7383 
7384   /* AttrId not part of this NdbRecord */
7385   return NULL;
7386 }
7387 
7388 char*
getValuePtr(const NdbRecord * record,char * row,Uint32 attrId)7389 NdbDictionaryImpl::getValuePtr(const NdbRecord* record,
7390                                char* row,
7391                                Uint32 attrId)
7392 {
7393   if (attrId < record->m_attrId_indexes_length)
7394   {
7395     int attrIdIndex= record->m_attrId_indexes[attrId];
7396 
7397     if (attrIdIndex != -1)
7398     {
7399       assert(attrIdIndex < (int)record->noOfColumns);
7400 
7401       return row + (record->columns[attrIdIndex].offset);
7402     }
7403   }
7404 
7405   /* AttrId not part of this NdbRecord */
7406   return NULL;
7407 }
7408 
7409 bool
isNull(const NdbRecord * record,const char * row,Uint32 attrId)7410 NdbDictionaryImpl::isNull(const NdbRecord* record,
7411                           const char* row,
7412                           Uint32 attrId)
7413 {
7414   if (attrId < record->m_attrId_indexes_length)
7415   {
7416     int attrIdIndex= record->m_attrId_indexes[attrId];
7417 
7418     if (attrIdIndex != -1)
7419     {
7420       assert(attrIdIndex < (int)record->noOfColumns);
7421       return record->columns[attrIdIndex].is_null(row);
7422     }
7423   }
7424 
7425   /* AttrId not part of this NdbRecord or is not nullable */
7426   return false;
7427 }
7428 
7429 int
setNull(const NdbRecord * record,char * row,Uint32 attrId,bool value)7430 NdbDictionaryImpl::setNull(const NdbRecord* record,
7431                            char* row,
7432                            Uint32 attrId,
7433                            bool value)
7434 {
7435   if (attrId < record->m_attrId_indexes_length)
7436   {
7437     int attrIdIndex= record->m_attrId_indexes[attrId];
7438 
7439     if (attrIdIndex != -1)
7440     {
7441       assert(attrIdIndex < (int)record->noOfColumns);
7442       NdbRecord::Attr attr= record->columns[attrIdIndex];
7443 
7444       if (attr.flags & NdbRecord::IsNullable)
7445       {
7446         if (value)
7447           *(row + attr.nullbit_byte_offset) |=
7448             (1 << attr.nullbit_bit_in_byte);
7449         else
7450           *(row + attr.nullbit_byte_offset) &=
7451             ~(1 << attr.nullbit_bit_in_byte);
7452 
7453         return 0;
7454       }
7455     }
7456   }
7457 
7458   /* AttrId not part of this NdbRecord or is not nullable */
7459   return -1;
7460 }
7461 
7462 Uint32
getRecordRowLength(const NdbRecord * record)7463 NdbDictionaryImpl::getRecordRowLength(const NdbRecord* record)
7464 {
7465   return record->m_row_size;
7466 }
7467 
7468 
7469 
7470 int
create_file(const NdbFileImpl & file,const NdbFilegroupImpl & group,bool overwrite,NdbDictObjectImpl * obj)7471 NdbDictInterface::create_file(const NdbFileImpl & file,
7472 			      const NdbFilegroupImpl & group,
7473 			      bool overwrite,
7474 			      NdbDictObjectImpl* obj)
7475 {
7476   DBUG_ENTER("NdbDictInterface::create_file");
7477   UtilBufferWriter w(m_buffer);
7478   DictFilegroupInfo::File f; f.init();
7479   BaseString::snprintf(f.FileName, sizeof(f.FileName), "%s", file.m_path.c_str());
7480   f.FileType = file.m_type;
7481   f.FilegroupId = group.m_id;
7482   f.FilegroupVersion = group.m_version;
7483   f.FileSizeHi = (Uint32)(file.m_size >> 32);
7484   f.FileSizeLo = (Uint32)(file.m_size & 0xFFFFFFFF);
7485 
7486   SimpleProperties::UnpackStatus s;
7487   s = SimpleProperties::pack(w,
7488 			     &f,
7489 			     DictFilegroupInfo::FileMapping,
7490 			     DictFilegroupInfo::FileMappingSize, true);
7491 
7492   if(s != SimpleProperties::Eof){
7493     abort();
7494   }
7495 
7496   NdbApiSignal tSignal(m_reference);
7497   tSignal.theReceiversBlockNumber = DBDICT;
7498   tSignal.theVerId_signalNumber = GSN_CREATE_FILE_REQ;
7499   tSignal.theLength = CreateFileReq::SignalLength;
7500 
7501   CreateFileReq* req = CAST_PTR(CreateFileReq, tSignal.getDataPtrSend());
7502   req->senderRef = m_reference;
7503   req->senderData = 0;
7504   req->objType = file.m_type;
7505   req->requestInfo = 0;
7506   if (overwrite)
7507     req->requestInfo |= CreateFileReq::ForceCreateFile;
7508   req->requestInfo |= m_tx.requestFlags();
7509   req->transId = m_tx.transId();
7510   req->transKey = m_tx.transKey();
7511 
7512   LinearSectionPtr ptr[3];
7513   ptr[0].p = (Uint32*)m_buffer.get_data();
7514   ptr[0].sz = m_buffer.length() / 4;
7515 
7516   int err[] = { CreateFileRef::Busy, CreateFileRef::NotMaster, 0};
7517   /*
7518     Send signal without time-out since creating files can take a very long
7519     time if the file is very big.
7520   */
7521   int ret = dictSignal(&tSignal, ptr, 1,
7522 		       0, // master
7523 		       WAIT_CREATE_INDX_REQ,
7524 		       -1, 100,
7525 		       err);
7526 
7527   if (ret == 0)
7528   {
7529     Uint32* data = (Uint32*)m_buffer.get_data();
7530     if (obj)
7531     {
7532       obj->m_id = data[0];
7533       obj->m_version = data[1];
7534     }
7535     m_warn = data[2];
7536     DBUG_PRINT("info", ("warning flags: 0x%x", m_warn));
7537   }
7538 
7539   DBUG_RETURN(ret);
7540 }
7541 
7542 void
execCREATE_FILE_CONF(const NdbApiSignal * signal,const LinearSectionPtr ptr[3])7543 NdbDictInterface::execCREATE_FILE_CONF(const NdbApiSignal * signal,
7544 				       const LinearSectionPtr ptr[3])
7545 {
7546   const CreateFileConf* conf=
7547     CAST_CONSTPTR(CreateFileConf, signal->getDataPtr());
7548   m_buffer.grow(4 * 3); // 3 words
7549   Uint32* data = (Uint32*)m_buffer.get_data();
7550   data[0] = conf->fileId;
7551   data[1] = conf->fileVersion;
7552   data[2] = conf->warningFlags;
7553 
7554   m_impl->theWaiter.signal(NO_WAIT);
7555 }
7556 
7557 void
execCREATE_FILE_REF(const NdbApiSignal * signal,const LinearSectionPtr ptr[3])7558 NdbDictInterface::execCREATE_FILE_REF(const NdbApiSignal * signal,
7559 				      const LinearSectionPtr ptr[3])
7560 {
7561   const CreateFileRef* ref =
7562     CAST_CONSTPTR(CreateFileRef, signal->getDataPtr());
7563   m_error.code = ref->errorCode;
7564   m_masterNodeId = ref->masterNodeId;
7565   m_impl->theWaiter.signal(NO_WAIT);
7566 }
7567 
7568 int
drop_file(const NdbFileImpl & file)7569 NdbDictInterface::drop_file(const NdbFileImpl & file)
7570 {
7571   DBUG_ENTER("NdbDictInterface::drop_file");
7572   NdbApiSignal tSignal(m_reference);
7573   tSignal.theReceiversBlockNumber = DBDICT;
7574   tSignal.theVerId_signalNumber = GSN_DROP_FILE_REQ;
7575   tSignal.theLength = DropFileReq::SignalLength;
7576 
7577   DropFileReq* req = CAST_PTR(DropFileReq, tSignal.getDataPtrSend());
7578   req->senderRef = m_reference;
7579   req->senderData = 0;
7580   req->file_id = file.m_id;
7581   req->file_version = file.m_version;
7582   req->requestInfo = 0;
7583   req->requestInfo |= m_tx.requestFlags();
7584   req->transId = m_tx.transId();
7585   req->transKey = m_tx.transKey();
7586 
7587   int err[] = { DropFileRef::Busy, DropFileRef::NotMaster, 0};
7588   DBUG_RETURN(dictSignal(&tSignal, 0, 0,
7589 	                 0, // master
7590 		         WAIT_CREATE_INDX_REQ,
7591 		         DICT_WAITFOR_TIMEOUT, 100,
7592 		         err));
7593 }
7594 
7595 void
execDROP_FILE_CONF(const NdbApiSignal * signal,const LinearSectionPtr ptr[3])7596 NdbDictInterface::execDROP_FILE_CONF(const NdbApiSignal * signal,
7597 					    const LinearSectionPtr ptr[3])
7598 {
7599   m_impl->theWaiter.signal(NO_WAIT);
7600 }
7601 
7602 void
execDROP_FILE_REF(const NdbApiSignal * signal,const LinearSectionPtr ptr[3])7603 NdbDictInterface::execDROP_FILE_REF(const NdbApiSignal * signal,
7604 					   const LinearSectionPtr ptr[3])
7605 {
7606   const DropFileRef* ref =
7607     CAST_CONSTPTR(DropFileRef, signal->getDataPtr());
7608   m_error.code = ref->errorCode;
7609   m_masterNodeId = ref->masterNodeId;
7610   m_impl->theWaiter.signal(NO_WAIT);
7611 }
7612 
7613 int
create_filegroup(const NdbFilegroupImpl & group,NdbDictObjectImpl * obj)7614 NdbDictInterface::create_filegroup(const NdbFilegroupImpl & group,
7615 				   NdbDictObjectImpl* obj)
7616 {
7617   DBUG_ENTER("NdbDictInterface::create_filegroup");
7618   UtilBufferWriter w(m_buffer);
7619   DictFilegroupInfo::Filegroup fg; fg.init();
7620   BaseString::snprintf(fg.FilegroupName, sizeof(fg.FilegroupName),
7621            "%s", group.m_name.c_str());
7622   switch(group.m_type){
7623   case NdbDictionary::Object::Tablespace:
7624   {
7625     fg.FilegroupType = DictTabInfo::Tablespace;
7626     //fg.TS_DataGrow = group.m_grow_spec;
7627     fg.TS_ExtentSize = group.m_extent_size;
7628 
7629     if(group.m_logfile_group_version != ~(Uint32)0)
7630     {
7631       fg.TS_LogfileGroupId = group.m_logfile_group_id;
7632       fg.TS_LogfileGroupVersion = group.m_logfile_group_version;
7633     }
7634     else
7635     {
7636       NdbLogfileGroupImpl tmp;
7637       if(get_filegroup(tmp, NdbDictionary::Object::LogfileGroup,
7638 		       group.m_logfile_group_name.c_str()) == 0)
7639       {
7640 	fg.TS_LogfileGroupId = tmp.m_id;
7641 	fg.TS_LogfileGroupVersion = tmp.m_version;
7642       }
7643       else // error set by get filegroup
7644       {
7645 	DBUG_RETURN(-1);
7646       }
7647     }
7648   }
7649   break;
7650   case NdbDictionary::Object::LogfileGroup:
7651     fg.LF_UndoBufferSize = group.m_undo_buffer_size;
7652     fg.FilegroupType = DictTabInfo::LogfileGroup;
7653     //fg.LF_UndoGrow = group.m_grow_spec;
7654     break;
7655   default:
7656     abort();
7657     DBUG_RETURN(-1);
7658   };
7659 
7660   SimpleProperties::UnpackStatus s;
7661   s = SimpleProperties::pack(w,
7662 			     &fg,
7663 			     DictFilegroupInfo::Mapping,
7664 			     DictFilegroupInfo::MappingSize, true);
7665 
7666   if(s != SimpleProperties::Eof){
7667     abort();
7668   }
7669 
7670   NdbApiSignal tSignal(m_reference);
7671   tSignal.theReceiversBlockNumber = DBDICT;
7672   tSignal.theVerId_signalNumber = GSN_CREATE_FILEGROUP_REQ;
7673   tSignal.theLength = CreateFilegroupReq::SignalLength;
7674 
7675   CreateFilegroupReq* req =
7676     CAST_PTR(CreateFilegroupReq, tSignal.getDataPtrSend());
7677   req->senderRef = m_reference;
7678   req->senderData = 0;
7679   req->objType = fg.FilegroupType;
7680   req->requestInfo = 0;
7681   req->requestInfo |= m_tx.requestFlags();
7682   req->transId = m_tx.transId();
7683   req->transKey = m_tx.transKey();
7684 
7685   LinearSectionPtr ptr[3];
7686   ptr[0].p = (Uint32*)m_buffer.get_data();
7687   ptr[0].sz = m_buffer.length() / 4;
7688 
7689   int err[] = { CreateFilegroupRef::Busy, CreateFilegroupRef::NotMaster, 0};
7690   int ret = dictSignal(&tSignal, ptr, 1,
7691 		       0, // master
7692 		       WAIT_CREATE_INDX_REQ,
7693 		       DICT_WAITFOR_TIMEOUT, 100,
7694 		       err);
7695 
7696   if (ret == 0)
7697   {
7698     Uint32* data = (Uint32*)m_buffer.get_data();
7699     if (obj)
7700     {
7701       obj->m_id = data[0];
7702       obj->m_version = data[1];
7703     }
7704     m_warn = data[2];
7705     DBUG_PRINT("info", ("warning flags: 0x%x", m_warn));
7706   }
7707 
7708   DBUG_RETURN(ret);
7709 }
7710 
7711 void
execCREATE_FILEGROUP_CONF(const NdbApiSignal * signal,const LinearSectionPtr ptr[3])7712 NdbDictInterface::execCREATE_FILEGROUP_CONF(const NdbApiSignal * signal,
7713 					    const LinearSectionPtr ptr[3])
7714 {
7715   const CreateFilegroupConf* conf=
7716     CAST_CONSTPTR(CreateFilegroupConf, signal->getDataPtr());
7717   m_buffer.grow(4 * 3); // 3 words
7718   Uint32* data = (Uint32*)m_buffer.get_data();
7719   data[0] = conf->filegroupId;
7720   data[1] = conf->filegroupVersion;
7721   data[2] = conf->warningFlags;
7722   m_impl->theWaiter.signal(NO_WAIT);
7723 }
7724 
7725 void
execCREATE_FILEGROUP_REF(const NdbApiSignal * signal,const LinearSectionPtr ptr[3])7726 NdbDictInterface::execCREATE_FILEGROUP_REF(const NdbApiSignal * signal,
7727 					   const LinearSectionPtr ptr[3])
7728 {
7729   const CreateFilegroupRef* ref =
7730     CAST_CONSTPTR(CreateFilegroupRef, signal->getDataPtr());
7731   m_error.code = ref->errorCode;
7732   m_masterNodeId = ref->masterNodeId;
7733   m_impl->theWaiter.signal(NO_WAIT);
7734 }
7735 
7736 int
drop_filegroup(const NdbFilegroupImpl & group)7737 NdbDictInterface::drop_filegroup(const NdbFilegroupImpl & group)
7738 {
7739   DBUG_ENTER("NdbDictInterface::drop_filegroup");
7740   NdbApiSignal tSignal(m_reference);
7741   tSignal.theReceiversBlockNumber = DBDICT;
7742   tSignal.theVerId_signalNumber = GSN_DROP_FILEGROUP_REQ;
7743   tSignal.theLength = DropFilegroupReq::SignalLength;
7744 
7745   DropFilegroupReq* req = CAST_PTR(DropFilegroupReq, tSignal.getDataPtrSend());
7746   req->senderRef = m_reference;
7747   req->senderData = 0;
7748   req->filegroup_id = group.m_id;
7749   req->filegroup_version = group.m_version;
7750   req->requestInfo = 0;
7751   req->requestInfo |= m_tx.requestFlags();
7752   req->transId = m_tx.transId();
7753   req->transKey = m_tx.transKey();
7754 
7755   int err[] = { DropFilegroupRef::Busy, DropFilegroupRef::NotMaster, 0};
7756   DBUG_RETURN(dictSignal(&tSignal, 0, 0,
7757                          0, // master
7758 		         WAIT_CREATE_INDX_REQ,
7759 		         DICT_WAITFOR_TIMEOUT, 100,
7760 		         err));
7761 }
7762 
7763 void
execDROP_FILEGROUP_CONF(const NdbApiSignal * signal,const LinearSectionPtr ptr[3])7764 NdbDictInterface::execDROP_FILEGROUP_CONF(const NdbApiSignal * signal,
7765 					    const LinearSectionPtr ptr[3])
7766 {
7767   m_impl->theWaiter.signal(NO_WAIT);
7768 }
7769 
7770 void
execDROP_FILEGROUP_REF(const NdbApiSignal * signal,const LinearSectionPtr ptr[3])7771 NdbDictInterface::execDROP_FILEGROUP_REF(const NdbApiSignal * signal,
7772 					   const LinearSectionPtr ptr[3])
7773 {
7774   const DropFilegroupRef* ref =
7775     CAST_CONSTPTR(DropFilegroupRef, signal->getDataPtr());
7776   m_error.code = ref->errorCode;
7777   m_masterNodeId = ref->masterNodeId;
7778   m_impl->theWaiter.signal(NO_WAIT);
7779 }
7780 
7781 
7782 int
get_filegroup(NdbFilegroupImpl & dst,NdbDictionary::Object::Type type,const char * name)7783 NdbDictInterface::get_filegroup(NdbFilegroupImpl & dst,
7784 				NdbDictionary::Object::Type type,
7785 				const char * name){
7786   DBUG_ENTER("NdbDictInterface::get_filegroup");
7787   NdbApiSignal tSignal(m_reference);
7788   GetTabInfoReq * req = CAST_PTR(GetTabInfoReq, tSignal.getDataPtrSend());
7789 
7790   Uint32 strLen = (Uint32)strlen(name) + 1;
7791 
7792   req->senderRef = m_reference;
7793   req->senderData = 0;
7794   req->requestType =
7795     GetTabInfoReq::RequestByName | GetTabInfoReq::LongSignalConf;
7796   req->tableNameLen = strLen;
7797   req->schemaTransId = m_tx.transId();
7798   tSignal.theReceiversBlockNumber = DBDICT;
7799   tSignal.theVerId_signalNumber   = GSN_GET_TABINFOREQ;
7800   tSignal.theLength = GetTabInfoReq::SignalLength;
7801 
7802   LinearSectionPtr ptr[1];
7803   ptr[0].p  = (Uint32*)name;
7804   ptr[0].sz = (strLen + 3)/4;
7805 
7806 #ifndef IGNORE_VALGRIND_WARNINGS
7807   if (strLen & 3)
7808   {
7809     Uint32 pad = 0;
7810     m_buffer.clear();
7811     m_buffer.append(name, strLen);
7812     m_buffer.append(&pad, 4);
7813     ptr[0].p = (Uint32*)m_buffer.get_data();
7814   }
7815 #endif
7816 
7817   int r = dictSignal(&tSignal, ptr, 1,
7818 		     -1, // any node
7819 		     WAIT_GET_TAB_INFO_REQ,
7820 		     DICT_WAITFOR_TIMEOUT, 100);
7821   if (r)
7822   {
7823     dst.m_id = RNIL;
7824     dst.m_version = ~0;
7825 
7826     DBUG_PRINT("info", ("get_filegroup failed dictSignal"));
7827     DBUG_RETURN(-1);
7828   }
7829 
7830   m_error.code = parseFilegroupInfo(dst,
7831 				    (Uint32*)m_buffer.get_data(),
7832 				    m_buffer.length() / 4);
7833 
7834   if(m_error.code)
7835   {
7836     DBUG_PRINT("info", ("get_filegroup failed parseFilegroupInfo %d",
7837                          m_error.code));
7838     DBUG_RETURN(m_error.code);
7839   }
7840 
7841   if(dst.m_type == NdbDictionary::Object::Tablespace)
7842   {
7843     NdbDictionary::LogfileGroup tmp;
7844     get_filegroup(NdbLogfileGroupImpl::getImpl(tmp),
7845 		  NdbDictionary::Object::LogfileGroup,
7846 		  dst.m_logfile_group_id);
7847     if (!dst.m_logfile_group_name.assign(tmp.getName()))
7848       DBUG_RETURN(m_error.code = 4000);
7849   }
7850 
7851   if(dst.m_type == type)
7852   {
7853     DBUG_RETURN(0);
7854   }
7855   DBUG_PRINT("info", ("get_filegroup failed no such filegroup"));
7856   DBUG_RETURN(m_error.code = GetTabInfoRef::TableNotDefined);
7857 }
7858 
7859 int
parseFilegroupInfo(NdbFilegroupImpl & dst,const Uint32 * data,Uint32 len)7860 NdbDictInterface::parseFilegroupInfo(NdbFilegroupImpl &dst,
7861 				     const Uint32 * data, Uint32 len)
7862 
7863 {
7864   SimplePropertiesLinearReader it(data, len);
7865 
7866   SimpleProperties::UnpackStatus status;
7867   DictFilegroupInfo::Filegroup fg; fg.init();
7868   status = SimpleProperties::unpack(it, &fg,
7869 				    DictFilegroupInfo::Mapping,
7870 				    DictFilegroupInfo::MappingSize,
7871 				    true, true);
7872 
7873   if(status != SimpleProperties::Eof){
7874     return CreateFilegroupRef::InvalidFormat;
7875   }
7876 
7877   dst.m_id = fg.FilegroupId;
7878   dst.m_version = fg.FilegroupVersion;
7879   dst.m_type = (NdbDictionary::Object::Type)fg.FilegroupType;
7880   dst.m_status = NdbDictionary::Object::Retrieved;
7881 
7882   if (!dst.m_name.assign(fg.FilegroupName))
7883     return 4000;
7884   dst.m_extent_size = fg.TS_ExtentSize;
7885   dst.m_undo_buffer_size = fg.LF_UndoBufferSize;
7886   dst.m_logfile_group_id = fg.TS_LogfileGroupId;
7887   dst.m_logfile_group_version = fg.TS_LogfileGroupVersion;
7888   dst.m_undo_free_words= ((Uint64)fg.LF_UndoFreeWordsHi << 32)
7889     | (fg.LF_UndoFreeWordsLo);
7890 
7891   return 0;
7892 }
7893 
7894 int
get_filegroup(NdbFilegroupImpl & dst,NdbDictionary::Object::Type type,Uint32 id)7895 NdbDictInterface::get_filegroup(NdbFilegroupImpl & dst,
7896 				NdbDictionary::Object::Type type,
7897 				Uint32 id){
7898   DBUG_ENTER("NdbDictInterface::get_filegroup");
7899   NdbApiSignal tSignal(m_reference);
7900   GetTabInfoReq * req = CAST_PTR(GetTabInfoReq, tSignal.getDataPtrSend());
7901 
7902   req->senderRef = m_reference;
7903   req->senderData = 0;
7904   req->requestType =
7905     GetTabInfoReq::RequestById | GetTabInfoReq::LongSignalConf;
7906   req->tableId = id;
7907   req->schemaTransId = m_tx.transId();
7908   tSignal.theReceiversBlockNumber = DBDICT;
7909   tSignal.theVerId_signalNumber   = GSN_GET_TABINFOREQ;
7910   tSignal.theLength = GetTabInfoReq::SignalLength;
7911 
7912   int r = dictSignal(&tSignal, NULL, 1,
7913 		     -1, // any node
7914 		     WAIT_GET_TAB_INFO_REQ,
7915 		     DICT_WAITFOR_TIMEOUT, 100);
7916   if (r)
7917   {
7918     DBUG_PRINT("info", ("get_filegroup failed dictSignal"));
7919     DBUG_RETURN(-1);
7920   }
7921 
7922   m_error.code = parseFilegroupInfo(dst,
7923 				    (Uint32*)m_buffer.get_data(),
7924 				    m_buffer.length() / 4);
7925 
7926   if(m_error.code)
7927   {
7928     DBUG_PRINT("info", ("get_filegroup failed parseFilegroupInfo %d",
7929                          m_error.code));
7930     DBUG_RETURN(m_error.code);
7931   }
7932 
7933   if(dst.m_type == type)
7934   {
7935     DBUG_RETURN(0);
7936   }
7937   DBUG_PRINT("info", ("get_filegroup failed no such filegroup"));
7938   DBUG_RETURN(m_error.code = GetTabInfoRef::TableNotDefined);
7939 }
7940 
7941 int
get_file(NdbFileImpl & dst,NdbDictionary::Object::Type type,int node,const char * name)7942 NdbDictInterface::get_file(NdbFileImpl & dst,
7943 			   NdbDictionary::Object::Type type,
7944 			   int node,
7945 			   const char * name){
7946   DBUG_ENTER("NdbDictInterface::get_file");
7947   NdbApiSignal tSignal(m_reference);
7948   GetTabInfoReq * req = CAST_PTR(GetTabInfoReq, tSignal.getDataPtrSend());
7949 
7950   Uint32 strLen = (Uint32)strlen(name) + 1;
7951 
7952   req->senderRef = m_reference;
7953   req->senderData = 0;
7954   req->requestType =
7955     GetTabInfoReq::RequestByName | GetTabInfoReq::LongSignalConf;
7956   req->tableNameLen = strLen;
7957   req->schemaTransId = m_tx.transId();
7958   tSignal.theReceiversBlockNumber = DBDICT;
7959   tSignal.theVerId_signalNumber   = GSN_GET_TABINFOREQ;
7960   tSignal.theLength = GetTabInfoReq::SignalLength;
7961 
7962   LinearSectionPtr ptr[1];
7963   ptr[0].p  = (Uint32*)name;
7964   ptr[0].sz = (strLen + 3)/4;
7965 
7966 #ifndef IGNORE_VALGRIND_WARNINGS
7967   if (strLen & 3)
7968   {
7969     Uint32 pad = 0;
7970     m_buffer.clear();
7971     m_buffer.append(name, strLen);
7972     m_buffer.append(&pad, 4);
7973     ptr[0].p = (Uint32*)m_buffer.get_data();
7974   }
7975 #endif
7976 
7977   int r = dictSignal(&tSignal, ptr, 1,
7978 		     node,
7979 		     WAIT_GET_TAB_INFO_REQ,
7980 		     DICT_WAITFOR_TIMEOUT, 100);
7981   if (r)
7982   {
7983     DBUG_PRINT("info", ("get_file failed dictSignal"));
7984     DBUG_RETURN(-1);
7985   }
7986 
7987   m_error.code = parseFileInfo(dst,
7988 			       (Uint32*)m_buffer.get_data(),
7989 			       m_buffer.length() / 4);
7990 
7991   if(m_error.code)
7992   {
7993     DBUG_PRINT("info", ("get_file failed parseFileInfo %d",
7994                          m_error.code));
7995     DBUG_RETURN(m_error.code);
7996   }
7997 
7998   if(dst.m_type == NdbDictionary::Object::Undofile)
7999   {
8000     NdbDictionary::LogfileGroup tmp;
8001     get_filegroup(NdbLogfileGroupImpl::getImpl(tmp),
8002 		  NdbDictionary::Object::LogfileGroup,
8003 		  dst.m_filegroup_id);
8004     if (!dst.m_filegroup_name.assign(tmp.getName()))
8005       DBUG_RETURN(m_error.code = 4000);
8006   }
8007   else if(dst.m_type == NdbDictionary::Object::Datafile)
8008   {
8009     NdbDictionary::Tablespace tmp;
8010     get_filegroup(NdbTablespaceImpl::getImpl(tmp),
8011 		  NdbDictionary::Object::Tablespace,
8012 		  dst.m_filegroup_id);
8013     if (!dst.m_filegroup_name.assign(tmp.getName()))
8014       DBUG_RETURN(m_error.code = 4000);
8015     dst.m_free *= tmp.getExtentSize();
8016   }
8017   else
8018     dst.m_filegroup_name.assign("Not Yet Implemented");
8019 
8020   if(dst.m_type == type)
8021   {
8022     DBUG_RETURN(0);
8023   }
8024   DBUG_PRINT("info", ("get_file failed no such file"));
8025   DBUG_RETURN(m_error.code = GetTabInfoRef::TableNotDefined);
8026 }
8027 
8028 int
parseFileInfo(NdbFileImpl & dst,const Uint32 * data,Uint32 len)8029 NdbDictInterface::parseFileInfo(NdbFileImpl &dst,
8030 				const Uint32 * data, Uint32 len)
8031 {
8032   SimplePropertiesLinearReader it(data, len);
8033 
8034   SimpleProperties::UnpackStatus status;
8035   DictFilegroupInfo::File f; f.init();
8036   status = SimpleProperties::unpack(it, &f,
8037 				    DictFilegroupInfo::FileMapping,
8038 				    DictFilegroupInfo::FileMappingSize,
8039 				    true, true);
8040 
8041   if(status != SimpleProperties::Eof){
8042     return CreateFilegroupRef::InvalidFormat;
8043   }
8044 
8045   dst.m_type= (NdbDictionary::Object::Type)f.FileType;
8046   dst.m_id= f.FileId;
8047   dst.m_version = f.FileVersion;
8048 
8049   dst.m_size= ((Uint64)f.FileSizeHi << 32) | (f.FileSizeLo);
8050   if (!dst.m_path.assign(f.FileName))
8051     return 4000;
8052 
8053   dst.m_filegroup_id= f.FilegroupId;
8054   dst.m_filegroup_version= f.FilegroupVersion;
8055   dst.m_free=  f.FileFreeExtents;
8056   return 0;
8057 }
8058 
8059 /**
8060  * HashMap
8061  */
8062 
NdbHashMapImpl()8063 NdbHashMapImpl::NdbHashMapImpl()
8064   : NdbDictionary::HashMap(* this),
8065     NdbDictObjectImpl(NdbDictionary::Object::HashMap), m_facade(this)
8066 {
8067 }
8068 
NdbHashMapImpl(NdbDictionary::HashMap & f)8069 NdbHashMapImpl::NdbHashMapImpl(NdbDictionary::HashMap & f)
8070   : NdbDictionary::HashMap(* this),
8071     NdbDictObjectImpl(NdbDictionary::Object::HashMap), m_facade(&f)
8072 {
8073 }
8074 
~NdbHashMapImpl()8075 NdbHashMapImpl::~NdbHashMapImpl()
8076 {
8077 }
8078 
8079 int
assign(const NdbHashMapImpl & org)8080 NdbHashMapImpl::assign(const NdbHashMapImpl& org)
8081 {
8082   m_id = org.m_id;
8083   m_version = org.m_version;
8084   m_status = org.m_status;
8085 
8086   m_name.assign(org.m_name);
8087   m_map.assign(org.m_map);
8088 
8089   return 0;
8090 }
8091 
8092 int
get_hashmap(NdbHashMapImpl & dst,const char * name)8093 NdbDictInterface::get_hashmap(NdbHashMapImpl & dst,
8094                               const char * name)
8095 {
8096   NdbApiSignal tSignal(m_reference);
8097   GetTabInfoReq * req = CAST_PTR(GetTabInfoReq, tSignal.getDataPtrSend());
8098 
8099   Uint32 strLen = (Uint32)strlen(name) + 1;
8100 
8101   req->senderRef = m_reference;
8102   req->senderData = 0;
8103   req->requestType =
8104     GetTabInfoReq::RequestByName | GetTabInfoReq::LongSignalConf;
8105   req->tableNameLen = strLen;
8106   req->schemaTransId = m_tx.transId();
8107   tSignal.theReceiversBlockNumber = DBDICT;
8108   tSignal.theVerId_signalNumber   = GSN_GET_TABINFOREQ;
8109   tSignal.theLength = GetTabInfoReq::SignalLength;
8110 
8111   LinearSectionPtr ptr[1];
8112   ptr[0].p  = (Uint32*)name;
8113   ptr[0].sz = (strLen + 3)/4;
8114 
8115 #ifndef IGNORE_VALGRIND_WARNINGS
8116   if (strLen & 3)
8117   {
8118     Uint32 pad = 0;
8119     m_buffer.clear();
8120     m_buffer.append(name, strLen);
8121     m_buffer.append(&pad, 4);
8122     ptr[0].p = (Uint32*)m_buffer.get_data();
8123   }
8124 #endif
8125 
8126   int r = dictSignal(&tSignal, ptr, 1,
8127 		     -1, // any node
8128 		     WAIT_GET_TAB_INFO_REQ,
8129 		     DICT_WAITFOR_TIMEOUT, 100);
8130   if (r)
8131   {
8132     dst.m_id = -1;
8133     dst.m_version = ~0;
8134 
8135     return -1;
8136   }
8137 
8138   m_error.code = parseHashMapInfo(dst,
8139                                   (Uint32*)m_buffer.get_data(),
8140                                   m_buffer.length() / 4);
8141 
8142   return m_error.code;
8143 }
8144 
8145 int
get_hashmap(NdbHashMapImpl & dst,Uint32 id)8146 NdbDictInterface::get_hashmap(NdbHashMapImpl & dst,
8147                               Uint32 id)
8148 {
8149   NdbApiSignal tSignal(m_reference);
8150   GetTabInfoReq * req = CAST_PTR(GetTabInfoReq, tSignal.getDataPtrSend());
8151 
8152   req->senderRef = m_reference;
8153   req->senderData = 0;
8154   req->requestType =
8155     GetTabInfoReq::RequestById | GetTabInfoReq::LongSignalConf;
8156   req->tableId = id;
8157   req->schemaTransId = m_tx.transId();
8158   tSignal.theReceiversBlockNumber = DBDICT;
8159   tSignal.theVerId_signalNumber   = GSN_GET_TABINFOREQ;
8160   tSignal.theLength = GetTabInfoReq::SignalLength;
8161 
8162   int r = dictSignal(&tSignal, 0, 0,
8163 		     -1, // any node
8164 		     WAIT_GET_TAB_INFO_REQ,
8165 		     DICT_WAITFOR_TIMEOUT, 100);
8166   if (r)
8167   {
8168     dst.m_id = -1;
8169     dst.m_version = ~0;
8170 
8171     return -1;
8172   }
8173 
8174   m_error.code = parseHashMapInfo(dst,
8175                                   (Uint32*)m_buffer.get_data(),
8176                                   m_buffer.length() / 4);
8177 
8178   return m_error.code;
8179 }
8180 
8181 int
parseHashMapInfo(NdbHashMapImpl & dst,const Uint32 * data,Uint32 len)8182 NdbDictInterface::parseHashMapInfo(NdbHashMapImpl &dst,
8183                                    const Uint32 * data, Uint32 len)
8184 {
8185   SimplePropertiesLinearReader it(data, len);
8186 
8187   SimpleProperties::UnpackStatus status;
8188   DictHashMapInfo::HashMap hm; hm.init();
8189   status = SimpleProperties::unpack(it, &hm,
8190                                     DictHashMapInfo::Mapping,
8191                                     DictHashMapInfo::MappingSize,
8192                                     true, true);
8193 
8194   if(status != SimpleProperties::Eof){
8195     return CreateFilegroupRef::InvalidFormat;
8196   }
8197 
8198   dst.m_name.assign(hm.HashMapName);
8199   dst.m_id= hm.HashMapObjectId;
8200   dst.m_version = hm.HashMapVersion;
8201 
8202   /**
8203    * pack is stupid...and requires bytes!
8204    * we store shorts...so divide by 2
8205    */
8206   hm.HashMapBuckets /= sizeof(Uint16);
8207 
8208   dst.m_map.clear();
8209   for (Uint32 i = 0; i<hm.HashMapBuckets; i++)
8210   {
8211     dst.m_map.push_back(hm.HashMapValues[i]);
8212   }
8213 
8214   return 0;
8215 }
8216 
8217 int
create_hashmap(const NdbHashMapImpl & src,NdbDictObjectImpl * obj,Uint32 flags)8218 NdbDictInterface::create_hashmap(const NdbHashMapImpl& src,
8219                                  NdbDictObjectImpl* obj,
8220                                  Uint32 flags)
8221 {
8222   DictHashMapInfo::HashMap hm; hm.init();
8223   BaseString::snprintf(hm.HashMapName, sizeof(hm.HashMapName),
8224                        "%s", src.getName());
8225   hm.HashMapBuckets = src.getMapLen();
8226   for (Uint32 i = 0; i<hm.HashMapBuckets; i++)
8227   {
8228     hm.HashMapValues[i] = NdbHashMapImpl::getImpl(src).m_map[i];
8229   }
8230 
8231   /**
8232    * pack is stupid...and requires bytes!
8233    * we store shorts...so multiply by 2
8234    */
8235   hm.HashMapBuckets *= sizeof(Uint16);
8236   SimpleProperties::UnpackStatus s;
8237   UtilBufferWriter w(m_buffer);
8238   s = SimpleProperties::pack(w,
8239                              &hm,
8240                              DictHashMapInfo::Mapping,
8241                              DictHashMapInfo::MappingSize, true);
8242 
8243   if(s != SimpleProperties::Eof)
8244   {
8245     abort();
8246   }
8247 
8248   NdbApiSignal tSignal(m_reference);
8249   tSignal.theReceiversBlockNumber = DBDICT;
8250   tSignal.theVerId_signalNumber = GSN_CREATE_HASH_MAP_REQ;
8251   tSignal.theLength = CreateHashMapReq::SignalLength;
8252 
8253   CreateHashMapReq* req = CAST_PTR(CreateHashMapReq, tSignal.getDataPtrSend());
8254   req->clientRef = m_reference;
8255   req->clientData = 0;
8256   req->requestInfo = flags;
8257   req->requestInfo |= m_tx.requestFlags();
8258   req->transId = m_tx.transId();
8259   req->transKey = m_tx.transKey();
8260   req->fragments = 0; // not used from here
8261   req->buckets = 0; // not used from here
8262 
8263   LinearSectionPtr ptr[3];
8264   ptr[0].p = (Uint32*)m_buffer.get_data();
8265   ptr[0].sz = m_buffer.length() / 4;
8266 
8267   int err[]= { CreateTableRef::Busy, CreateTableRef::NotMaster, 0 };
8268 
8269   /*
8270     Send signal without time-out since creating files can take a very long
8271     time if the file is very big.
8272   */
8273   Uint32 seccnt = 1;
8274   if (flags & CreateHashMapReq::CreateDefault)
8275   {
8276     seccnt = 0;
8277   }
8278   int ret = dictSignal(&tSignal, ptr, seccnt,
8279 		       0, // master
8280 		       WAIT_CREATE_INDX_REQ,
8281 		       -1, 100,
8282 		       err);
8283 
8284   if (ret == 0 && obj)
8285   {
8286     Uint32* data = (Uint32*)m_buffer.get_data();
8287     obj->m_id = data[0];
8288     obj->m_version = data[1];
8289   }
8290 
8291   return ret;
8292 }
8293 
8294 void
execCREATE_HASH_MAP_REF(const NdbApiSignal * signal,const LinearSectionPtr ptr[3])8295 NdbDictInterface::execCREATE_HASH_MAP_REF(const NdbApiSignal * signal,
8296                                           const LinearSectionPtr ptr[3])
8297 {
8298   const CreateHashMapRef* ref =
8299     CAST_CONSTPTR(CreateHashMapRef, signal->getDataPtr());
8300   m_error.code = ref->errorCode;
8301   m_masterNodeId = ref->masterNodeId;
8302   m_impl->theWaiter.signal(NO_WAIT);
8303 }
8304 
8305 
8306 void
execCREATE_HASH_MAP_CONF(const NdbApiSignal * signal,const LinearSectionPtr ptr[3])8307 NdbDictInterface::execCREATE_HASH_MAP_CONF(const NdbApiSignal * signal,
8308                                            const LinearSectionPtr ptr[3])
8309 {
8310   const CreateHashMapConf* conf=
8311     CAST_CONSTPTR(CreateHashMapConf, signal->getDataPtr());
8312   m_buffer.grow(4 * 2); // 2 words
8313   Uint32* data = (Uint32*)m_buffer.get_data();
8314   data[0] = conf->objectId;
8315   data[1] = conf->objectVersion;
8316 
8317   m_impl->theWaiter.signal(NO_WAIT);
8318 }
8319 
8320 template class Vector<NdbTableImpl*>;
8321 template class Vector<NdbColumnImpl*>;
8322 
8323 int
beginSchemaTrans(bool retry711)8324 NdbDictionaryImpl::beginSchemaTrans(bool retry711)
8325 {
8326   DBUG_ENTER("beginSchemaTrans");
8327   if (m_tx.m_state == NdbDictInterface::Tx::Started) {
8328     m_error.code = 4410;
8329     DBUG_RETURN(-1);
8330   }
8331   if (!m_receiver.checkAllNodeVersionsMin(NDBD_SCHEMA_TRANS_VERSION))
8332   {
8333     /* Upgrade 6.3 -> 7.0 path */
8334     /* Schema transaction not possible until upgrade complete */
8335     m_error.code = 4411;
8336     DBUG_RETURN(-1);
8337   }
8338   // TODO real transId
8339   m_tx.m_transId = rand();
8340   m_tx.m_state = NdbDictInterface::Tx::Started;
8341   m_tx.m_error.code = 0;
8342   if (m_tx.m_transId == 0)
8343     m_tx.m_transId = 1;
8344   int ret = m_receiver.beginSchemaTrans(retry711);
8345   if (ret == -1) {
8346     m_tx.m_state = NdbDictInterface::Tx::NotStarted;
8347     DBUG_RETURN(-1);
8348   }
8349   DBUG_PRINT("info", ("transId: %x transKey: %x",
8350                       m_tx.m_transId, m_tx.m_transKey));
8351   DBUG_RETURN(0);
8352 }
8353 
8354 int
endSchemaTrans(Uint32 flags)8355 NdbDictionaryImpl::endSchemaTrans(Uint32 flags)
8356 {
8357   DBUG_ENTER("endSchemaTrans");
8358   if (m_tx.m_state == NdbDictInterface::Tx::NotStarted) {
8359     DBUG_RETURN(0);
8360   }
8361   /*
8362     Check if schema transaction has been aborted
8363     already, for example because of master node failure.
8364    */
8365   if (m_tx.m_state != NdbDictInterface::Tx::Started)
8366   {
8367     m_tx.m_op.clear();
8368     DBUG_PRINT("info", ("endSchemaTrans: state %u, flags 0x%x\n", m_tx.m_state, flags));
8369     if (m_tx.m_state == NdbDictInterface::Tx::Aborted && // rollback at master takeover
8370         flags & NdbDictionary::Dictionary::SchemaTransAbort)
8371     {
8372       m_tx.m_error.code = 0;
8373       DBUG_RETURN(0);
8374     }
8375     m_error.code = m_tx.m_error.code;
8376     DBUG_RETURN(-1);
8377   }
8378   DBUG_PRINT("info", ("transId: %x transKey: %x",
8379                       m_tx.m_transId, m_tx.m_transKey));
8380   int ret = m_receiver.endSchemaTrans(flags);
8381   if (ret == -1 || m_tx.m_error.code != 0) {
8382     DBUG_PRINT("info", ("endSchemaTrans: state %u, flags 0x%x\n", m_tx.m_state, flags));
8383     if (m_tx.m_state == NdbDictInterface::Tx::Committed && // rollforward at master takeover
8384         !(flags & NdbDictionary::Dictionary::SchemaTransAbort))
8385       goto committed;
8386     m_tx.m_op.clear();
8387     if (m_tx.m_state == NdbDictInterface::Tx::Aborted && // rollback at master takeover
8388         flags & NdbDictionary::Dictionary::SchemaTransAbort)
8389     {
8390       m_error.code = m_tx.m_error.code = 0;
8391       m_tx.m_state = NdbDictInterface::Tx::NotStarted;
8392       DBUG_RETURN(0);
8393     }
8394     if (m_tx.m_error.code != 0)
8395       m_error.code = m_tx.m_error.code;
8396     m_tx.m_state = NdbDictInterface::Tx::NotStarted;
8397     DBUG_RETURN(-1);
8398   }
8399 committed:
8400   // invalidate old version of altered table
8401   uint i;
8402   for (i = 0; i < m_tx.m_op.size(); i++) {
8403     NdbDictInterface::Tx::Op& op = m_tx.m_op[i];
8404     if (op.m_gsn == GSN_ALTER_TABLE_REQ)
8405     {
8406       op.m_impl->m_status = NdbDictionary::Object::Invalid;
8407       m_globalHash->lock();
8408       int ret = m_globalHash->dec_ref_count(op.m_impl);
8409       m_globalHash->unlock();
8410       if (ret != 0)
8411         abort();
8412     }
8413   }
8414   m_tx.m_state = NdbDictInterface::Tx::NotStarted;
8415   m_tx.m_op.clear();
8416   DBUG_RETURN(0);
8417 }
8418 
8419 bool
checkAllNodeVersionsMin(Uint32 minNdbVersion) const8420 NdbDictInterface::checkAllNodeVersionsMin(Uint32 minNdbVersion) const
8421 {
8422   for (Uint32 nodeId = 1; nodeId < MAX_NODES; nodeId++)
8423   {
8424     if (m_impl->getIsDbNode(nodeId) &&
8425         m_impl->getIsNodeSendable(nodeId) &&
8426         (m_impl->getNodeNdbVersion(nodeId) <
8427          minNdbVersion))
8428     {
8429       /* At least 1 sendable data node has lower-than-min
8430        * version
8431        */
8432       return false;
8433     }
8434   }
8435 
8436   return true;
8437 }
8438 
8439 
8440 int
beginSchemaTrans(bool retry711)8441 NdbDictInterface::beginSchemaTrans(bool retry711)
8442 {
8443   assert(m_tx.m_op.size() == 0);
8444   NdbApiSignal tSignal(m_reference);
8445   SchemaTransBeginReq* req =
8446     CAST_PTR(SchemaTransBeginReq, tSignal.getDataPtrSend());
8447 
8448   tSignal.theReceiversBlockNumber = DBDICT;
8449   tSignal.theVerId_signalNumber = GSN_SCHEMA_TRANS_BEGIN_REQ;
8450   tSignal.theLength = SchemaTransBeginReq::SignalLength;
8451 
8452   req->clientRef =  m_reference;
8453   req->transId = m_tx.m_transId;
8454   req->requestInfo = 0;
8455 
8456   int errCodes[] = {
8457     SchemaTransBeginRef::NotMaster,
8458     SchemaTransBeginRef::Busy,
8459     retry711 ? SchemaTransBeginRef::BusyWithNR : 0,
8460     0
8461   };
8462 
8463   int ret = dictSignal(
8464       &tSignal,
8465       0,
8466       0,
8467       0,
8468       WAIT_SCHEMA_TRANS,
8469       DICT_WAITFOR_TIMEOUT,
8470       100,
8471       errCodes);
8472   if (ret == -1)
8473     return -1;
8474   return 0;
8475 }
8476 
8477 int
endSchemaTrans(Uint32 flags)8478 NdbDictInterface::endSchemaTrans(Uint32 flags)
8479 {
8480   NdbApiSignal tSignal(m_reference);
8481   SchemaTransEndReq* req =
8482     CAST_PTR(SchemaTransEndReq, tSignal.getDataPtrSend());
8483 
8484   tSignal.theReceiversBlockNumber = DBDICT;
8485   tSignal.theVerId_signalNumber = GSN_SCHEMA_TRANS_END_REQ;
8486   tSignal.theLength = SchemaTransEndReq::SignalLength;
8487 
8488   req->clientRef =  m_reference;
8489   req->transId = m_tx.m_transId;
8490   req->requestInfo = 0;
8491   req->transKey = m_tx.m_transKey;
8492   req->flags = flags;
8493 
8494   int errCodes[] = {
8495     SchemaTransBeginRef::NotMaster,
8496     0
8497   };
8498   int ret = dictSignal(
8499       &tSignal,
8500       0,
8501       0,
8502       0,
8503       WAIT_SCHEMA_TRANS,
8504       DICT_WAITFOR_TIMEOUT,
8505       100,
8506       errCodes);
8507   if (ret == -1)
8508     return -1;
8509   return 0;
8510 }
8511 
8512 void
execSCHEMA_TRANS_BEGIN_CONF(const NdbApiSignal * signal,const LinearSectionPtr ptr[3])8513 NdbDictInterface::execSCHEMA_TRANS_BEGIN_CONF(const NdbApiSignal * signal,
8514                                               const LinearSectionPtr ptr[3])
8515 {
8516   const SchemaTransBeginConf* conf=
8517     CAST_CONSTPTR(SchemaTransBeginConf, signal->getDataPtr());
8518   assert(m_tx.m_transId == conf->transId);
8519   m_tx.m_transKey = conf->transKey;
8520   m_impl->theWaiter.signal(NO_WAIT);
8521 }
8522 
8523 void
execSCHEMA_TRANS_BEGIN_REF(const NdbApiSignal * signal,const LinearSectionPtr ptr[3])8524 NdbDictInterface::execSCHEMA_TRANS_BEGIN_REF(const NdbApiSignal * signal,
8525                                              const LinearSectionPtr ptr[3])
8526 {
8527   const SchemaTransBeginRef* ref =
8528     CAST_CONSTPTR(SchemaTransBeginRef, signal->getDataPtr());
8529   m_error.code = ref->errorCode;
8530   m_masterNodeId = ref->masterNodeId;
8531   m_impl->theWaiter.signal(NO_WAIT);
8532 }
8533 
8534 void
execSCHEMA_TRANS_END_CONF(const NdbApiSignal * signal,const LinearSectionPtr ptr[3])8535 NdbDictInterface::execSCHEMA_TRANS_END_CONF(const NdbApiSignal * signal,
8536                                             const LinearSectionPtr ptr[3])
8537 {
8538   const SchemaTransEndConf* conf=
8539     CAST_CONSTPTR(SchemaTransEndConf, signal->getDataPtr());
8540   assert(m_tx.m_transId == conf->transId);
8541   m_impl->theWaiter.signal(NO_WAIT);
8542 }
8543 
8544 void
execSCHEMA_TRANS_END_REF(const NdbApiSignal * signal,const LinearSectionPtr ptr[3])8545 NdbDictInterface::execSCHEMA_TRANS_END_REF(const NdbApiSignal * signal,
8546                                            const LinearSectionPtr ptr[3])
8547 {
8548   const SchemaTransEndRef* ref =
8549     CAST_CONSTPTR(SchemaTransEndRef, signal->getDataPtr());
8550   m_error.code = ref->errorCode;
8551   m_tx.m_error.code = ref->errorCode;
8552   m_masterNodeId = ref->masterNodeId;
8553   m_impl->theWaiter.signal(NO_WAIT);
8554 }
8555 
8556 void
execSCHEMA_TRANS_END_REP(const NdbApiSignal * signal,const LinearSectionPtr ptr[3])8557 NdbDictInterface::execSCHEMA_TRANS_END_REP(const NdbApiSignal * signal,
8558                                            const LinearSectionPtr ptr[3])
8559 {
8560   const SchemaTransEndRep* rep =
8561     CAST_CONSTPTR(SchemaTransEndRep, signal->getDataPtr());
8562   (rep->errorCode == 0) ?
8563     m_tx.m_state = Tx::Committed
8564     :
8565     m_tx.m_state = Tx::Aborted;
8566   m_tx.m_error.code = rep->errorCode;
8567   m_masterNodeId = rep->masterNodeId;
8568   m_impl->theWaiter.signal(NO_WAIT);
8569 }
8570 
8571 const NdbDictionary::Column * NdbDictionary::Column::FRAGMENT = 0;
8572 const NdbDictionary::Column * NdbDictionary::Column::FRAGMENT_FIXED_MEMORY = 0;
8573 const NdbDictionary::Column * NdbDictionary::Column::FRAGMENT_VARSIZED_MEMORY = 0;
8574 const NdbDictionary::Column * NdbDictionary::Column::ROW_COUNT = 0;
8575 const NdbDictionary::Column * NdbDictionary::Column::COMMIT_COUNT = 0;
8576 const NdbDictionary::Column * NdbDictionary::Column::ROW_SIZE = 0;
8577 const NdbDictionary::Column * NdbDictionary::Column::RANGE_NO = 0;
8578 const NdbDictionary::Column * NdbDictionary::Column::DISK_REF = 0;
8579 const NdbDictionary::Column * NdbDictionary::Column::RECORDS_IN_RANGE = 0;
8580 const NdbDictionary::Column * NdbDictionary::Column::ROWID = 0;
8581 const NdbDictionary::Column * NdbDictionary::Column::ROW_GCI = 0;
8582 const NdbDictionary::Column * NdbDictionary::Column::ROW_GCI64 = 0;
8583 const NdbDictionary::Column * NdbDictionary::Column::ROW_AUTHOR = 0;
8584 const NdbDictionary::Column * NdbDictionary::Column::ANY_VALUE = 0;
8585 const NdbDictionary::Column * NdbDictionary::Column::COPY_ROWID = 0;
8586 const NdbDictionary::Column * NdbDictionary::Column::OPTIMIZE = 0;
8587 const NdbDictionary::Column * NdbDictionary::Column::FRAGMENT_EXTENT_SPACE = 0;
8588 const NdbDictionary::Column * NdbDictionary::Column::FRAGMENT_FREE_EXTENT_SPACE = 0;
8589 const NdbDictionary::Column * NdbDictionary::Column::LOCK_REF = 0;
8590 const NdbDictionary::Column * NdbDictionary::Column::OP_ID = 0;
8591 
8592 template class Vector<NdbDictInterface::Tx::Op>;
8593