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