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