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