~ubuntu-branches/ubuntu/precise/mysql-5.1/precise

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Tretkowski
  • Date: 2010-03-17 14:56:02 UTC
  • Revision ID: james.westby@ubuntu.com-20100317145602-x7e30l1b2sb5s6w6
Tags: upstream-5.1.45
ImportĀ upstreamĀ versionĀ 5.1.45

Show diffs side-by-side

added added

removed removed

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