~ubuntu-branches/ubuntu/trusty/mysql-5.6/trusty

« back to all changes in this revision

Viewing changes to storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2014-02-12 11:54:27 UTC
  • Revision ID: package-import@ubuntu.com-20140212115427-oq6tfsqxl1wuwehi
Tags: upstream-5.6.15
ImportĀ upstreamĀ versionĀ 5.6.15

Show diffs side-by-side

added added

removed removed

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