ha_ndbcluster.h 26.9 KB
Newer Older
unknown's avatar
unknown committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/* Copyright (C) 2000-2003 MySQL AB

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

/*
  This file defines the NDB Cluster handler: the interface between MySQL and
  NDB Cluster
*/

/* The class defining a handle to an NDB Cluster table */

24
#ifdef USE_PRAGMA_INTERFACE
unknown's avatar
unknown committed
25 26 27
#pragma interface                       /* gcc class implementation */
#endif

28 29 30
/* Blob tables and events are internal to NDB and must never be accessed */
#define IS_NDB_BLOB_PREFIX(A) is_prefix(A, "NDB$BLOB")

31
#include <NdbApi.hpp>
unknown's avatar
unknown committed
32 33
#include <ndbapi_limits.h>

34 35
#define NDB_HIDDEN_PRIMARY_KEY_LENGTH 8

unknown's avatar
unknown committed
36 37
class Ndb;             // Forward declaration
class NdbOperation;    // Forward declaration
38
class NdbTransaction;  // Forward declaration
unknown's avatar
unknown committed
39
class NdbRecAttr;      // Forward declaration
unknown's avatar
unknown committed
40
class NdbScanOperation; 
41
class NdbScanFilter; 
unknown's avatar
unknown committed
42
class NdbIndexScanOperation; 
unknown's avatar
unknown committed
43
class NdbBlob;
44
class NdbIndexStat;
unknown's avatar
unknown committed
45
class NdbEventOperation;
unknown's avatar
unknown committed
46

47 48
// connectstring to cluster if given by mysqld
extern const char *ndbcluster_connectstring;
unknown's avatar
unknown committed
49
extern ulong ndb_cache_check_time;
unknown's avatar
unknown committed
50
#ifdef HAVE_NDB_BINLOG
unknown's avatar
unknown committed
51 52
extern ulong ndb_report_thresh_binlog_epoch_slip;
extern ulong ndb_report_thresh_binlog_mem_usage;
unknown's avatar
unknown committed
53
#endif
54

unknown's avatar
unknown committed
55 56 57
typedef enum ndb_index_type {
  UNDEFINED_INDEX = 0,
  PRIMARY_KEY_INDEX = 1,
58 59 60 61
  PRIMARY_KEY_ORDERED_INDEX = 2,
  UNIQUE_INDEX = 3,
  UNIQUE_ORDERED_INDEX = 4,
  ORDERED_INDEX = 5
unknown's avatar
unknown committed
62 63
} NDB_INDEX_TYPE;

64 65
typedef enum ndb_index_status {
  UNDEFINED = 0,
66 67
  ACTIVE = 1,
  TO_BE_DROPPED = 2
68 69
} NDB_INDEX_STATUS;

70 71
typedef struct ndb_index_data {
  NDB_INDEX_TYPE type;
72
  NDB_INDEX_STATUS status;  
73 74
  void *index;
  void *unique_index;
75
  unsigned char *unique_index_attrid_map;
76 77 78 79 80 81
  // In this version stats are not shared between threads
  NdbIndexStat* index_stat;
  uint index_stat_cache_entries;
  // Simple counter mechanism to decide when to connect to db
  uint index_stat_update_freq;
  uint index_stat_query_count;
82
} NDB_INDEX_DATA;
unknown's avatar
unknown committed
83

unknown's avatar
unknown committed
84 85
typedef union { const NdbRecAttr *rec; NdbBlob *blob; void *ptr; } NdbValue;

86 87 88 89
int get_ndb_blobs_value(TABLE* table, NdbValue* value_array,
                        byte*& buffer, uint& buffer_size,
                        my_ptrdiff_t ptrdiff);

unknown's avatar
unknown committed
90 91
typedef enum {
  NSS_INITIAL= 0,
unknown's avatar
unknown committed
92 93
  NSS_DROPPED,
  NSS_ALTERED 
unknown's avatar
unknown committed
94 95
} NDB_SHARE_STATE;

unknown's avatar
unknown committed
96
typedef struct st_ndbcluster_share {
unknown's avatar
unknown committed
97
  NDB_SHARE_STATE state;
unknown's avatar
unknown committed
98
  MEM_ROOT mem_root;
unknown's avatar
unknown committed
99 100
  THR_LOCK lock;
  pthread_mutex_t mutex;
unknown's avatar
unknown committed
101 102 103 104
  char *key;
  uint key_length;
  THD *util_lock;
  uint use_count;
105
  uint commit_count_lock;
unknown's avatar
unknown committed
106
  ulonglong commit_count;
unknown's avatar
unknown committed
107 108
  char *db;
  char *table_name;
unknown's avatar
unknown committed
109 110 111 112 113 114 115 116 117 118
#ifdef HAVE_NDB_BINLOG
  uint32 flags;
  NdbEventOperation *op;
  NdbEventOperation *op_old; // for rename table
  char *old_names; // for rename table
  TABLE_SHARE *table_share;
  TABLE *table;
  NdbValue *ndb_value[2];
  MY_BITMAP *subscriber_bitmap;
#endif
unknown's avatar
unknown committed
119 120
} NDB_SHARE;

121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
inline
NDB_SHARE_STATE
get_ndb_share_state(NDB_SHARE *share)
{
  NDB_SHARE_STATE state;
  pthread_mutex_lock(&share->mutex);
  state= share->state;
  pthread_mutex_unlock(&share->mutex);
  return state;
}

inline
void
set_ndb_share_state(NDB_SHARE *share, NDB_SHARE_STATE state)
{
  pthread_mutex_lock(&share->mutex);
  share->state= state;
  pthread_mutex_unlock(&share->mutex);
}

unknown's avatar
unknown committed
141 142 143
#ifdef HAVE_NDB_BINLOG
/* NDB_SHARE.flags */
#define NSF_HIDDEN_PK 1 /* table has hidden primary key */
144
#define NSF_BLOB_FLAG 2 /* table has blob attributes */
145
#define NSF_NO_BINLOG 4 /* table should not be binlogged */
unknown's avatar
unknown committed
146 147
#endif

148 149 150
typedef enum ndb_item_type {
  NDB_VALUE = 0,   // Qualified more with Item::Type
  NDB_FIELD = 1,   // Qualified from table definition
151 152
  NDB_FUNCTION = 2,// Qualified from Item_func::Functype
  NDB_END_COND = 3 // End marker for condition group
153 154
} NDB_ITEM_TYPE;

155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
typedef enum ndb_func_type {
  NDB_EQ_FUNC = 0,
  NDB_NE_FUNC = 1,
  NDB_LT_FUNC = 2,
  NDB_LE_FUNC = 3,
  NDB_GT_FUNC = 4,
  NDB_GE_FUNC = 5,
  NDB_ISNULL_FUNC = 6,
  NDB_ISNOTNULL_FUNC = 7,
  NDB_LIKE_FUNC = 8,
  NDB_NOTLIKE_FUNC = 9,
  NDB_NOT_FUNC = 10,
  NDB_UNKNOWN_FUNC = 11,
  NDB_COND_AND_FUNC = 12,
  NDB_COND_OR_FUNC = 13,
  NDB_UNSUPPORTED_FUNC = 14
} NDB_FUNC_TYPE;

173 174
typedef union ndb_item_qualification {
  Item::Type value_type; 
175 176
  enum_field_types field_type; // Instead of Item::FIELD_ITEM
  NDB_FUNC_TYPE function_type; // Instead of Item::FUNC_ITEM
177 178 179 180 181 182 183 184
} NDB_ITEM_QUALIFICATION;

typedef struct ndb_item_field_value {
  Field* field;
  int column_no;
} NDB_ITEM_FIELD_VALUE;

typedef union ndb_item_value {
unknown's avatar
unknown committed
185
  const Item *item;
186
  NDB_ITEM_FIELD_VALUE *field_value;
187
  uint arg_count;
188 189
} NDB_ITEM_VALUE;

190 191
struct negated_function_mapping
{
192 193
  NDB_FUNC_TYPE pos_fun;
  NDB_FUNC_TYPE neg_fun;
194 195
};

196

197 198 199 200
/*
  Define what functions can be negated in condition pushdown.
  Note, these HAVE to be in the same order as in definition enum
*/
201 202
static const negated_function_mapping neg_map[]= 
{
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
  {NDB_EQ_FUNC, NDB_NE_FUNC},
  {NDB_NE_FUNC, NDB_EQ_FUNC},
  {NDB_LT_FUNC, NDB_GE_FUNC},
  {NDB_LE_FUNC, NDB_GT_FUNC},
  {NDB_GT_FUNC, NDB_LE_FUNC},
  {NDB_GE_FUNC, NDB_LT_FUNC},
  {NDB_ISNULL_FUNC, NDB_ISNOTNULL_FUNC},
  {NDB_ISNOTNULL_FUNC, NDB_ISNULL_FUNC},
  {NDB_LIKE_FUNC, NDB_NOTLIKE_FUNC},
  {NDB_NOTLIKE_FUNC, NDB_LIKE_FUNC},
  {NDB_NOT_FUNC, NDB_UNSUPPORTED_FUNC},
  {NDB_UNKNOWN_FUNC, NDB_UNSUPPORTED_FUNC},
  {NDB_COND_AND_FUNC, NDB_UNSUPPORTED_FUNC},
  {NDB_COND_OR_FUNC, NDB_UNSUPPORTED_FUNC},
  {NDB_UNSUPPORTED_FUNC, NDB_UNSUPPORTED_FUNC}
218 219
};
  
220
/*
221 222 223 224 225 226 227
  This class is the construction element for serialization of Item tree 
  in condition pushdown.
  An instance of Ndb_Item represents a constant, table field reference,
  unary or binary comparison predicate, and start/end of AND/OR.
  Instances of Ndb_Item are stored in a linked list implemented by Ndb_cond
  class.
  The order of elements produced by Ndb_cond::next corresponds to
unknown's avatar
unknown committed
228
  breadth-first traversal of the Item (i.e. expression) tree in prefix order.
229 230 231 232
  AND and OR have arbitrary arity, so the end of AND/OR group is marked with  
  Ndb_item with type == NDB_END_COND.
  NOT items represent negated conditions and generate NAND/NOR groups.
*/
233 234
class Ndb_item {
 public:
unknown's avatar
unknown committed
235
  Ndb_item(NDB_ITEM_TYPE item_type) : type(item_type) {};
236
  Ndb_item(NDB_ITEM_TYPE item_type, 
237 238
           NDB_ITEM_QUALIFICATION item_qualification,
           const Item *item_value)
unknown's avatar
unknown committed
239 240 241 242 243 244 245 246 247 248 249 250
    : type(item_type), qualification(item_qualification)
  { 
    switch(item_type) {
    case(NDB_VALUE):
      value.item= item_value;
      break;
    case(NDB_FIELD): {
      NDB_ITEM_FIELD_VALUE *field_value= new NDB_ITEM_FIELD_VALUE();
      Item_field *field_item= (Item_field *) item_value;
      field_value->field= field_item->field;
      field_value->column_no= -1; // Will be fetched at scan filter generation
      value.field_value= field_value;
251 252
      break;
    }
unknown's avatar
unknown committed
253
    case(NDB_FUNCTION):
254
      value.item= item_value;
255
      value.arg_count= ((Item_func *) item_value)->argument_count();
256
      break;
unknown's avatar
unknown committed
257 258
    case(NDB_END_COND):
      break;
259
    }
unknown's avatar
unknown committed
260 261 262 263 264 265 266 267 268
  };
  Ndb_item(Field *field, int column_no) : type(NDB_FIELD)
  {
    NDB_ITEM_FIELD_VALUE *field_value= new NDB_ITEM_FIELD_VALUE();
    qualification.field_type= field->type();
    field_value->field= field;
    field_value->column_no= column_no;
    value.field_value= field_value;
  };
269 270
  Ndb_item(Item_func::Functype func_type, const Item *item_value) 
    : type(NDB_FUNCTION)
unknown's avatar
unknown committed
271
  {
272
    qualification.function_type= item_func_to_ndb_func(func_type);
273
    value.item= item_value;
274 275 276 277 278
    value.arg_count= ((Item_func *) item_value)->argument_count();
  };
  Ndb_item(Item_func::Functype func_type, uint no_args) 
    : type(NDB_FUNCTION)
  {
279
    qualification.function_type= item_func_to_ndb_func(func_type);
280
    value.arg_count= no_args;
unknown's avatar
unknown committed
281 282 283 284 285
  };
  ~Ndb_item()
  { 
    if (type == NDB_FIELD)
      {
286 287
        delete value.field_value;
        value.field_value= NULL;
unknown's avatar
unknown committed
288 289 290 291 292 293
      }
  };

  uint32 pack_length() 
  { 
    switch(type) {
294 295 296 297
    case(NDB_VALUE):
      if(qualification.value_type == Item::STRING_ITEM)
        return value.item->str_value.length();
      break;
unknown's avatar
unknown committed
298 299
    case(NDB_FIELD):
      return value.field_value->field->pack_length(); 
300 301 302
    default:
      break;
    }
unknown's avatar
unknown committed
303 304 305
    
    return 0;
  };
306

unknown's avatar
unknown committed
307
  Field * get_field() { return value.field_value->field; };
308

unknown's avatar
unknown committed
309
  int get_field_no() { return value.field_value->column_no; };
310

311 312
  int argument_count() 
  { 
313
    return value.arg_count;
314 315
  };

316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331
  const char* get_val() 
  {  
    switch(type) {
    case(NDB_VALUE):
      if(qualification.value_type == Item::STRING_ITEM)
        return value.item->str_value.ptr();
      break;
    case(NDB_FIELD):
      return value.field_value->field->ptr; 
    default:
      break;
    }
    
    return NULL;
  };

unknown's avatar
unknown committed
332 333 334 335
  void save_in_field(Ndb_item *field_item)
  {
    Field *field = field_item->value.field_value->field;
    const Item *item= value.item;
336

unknown's avatar
unknown committed
337 338
    if (item && field)
      ((Item *)item)->save_in_field(field, false);
339 340
  };

341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361
  static NDB_FUNC_TYPE item_func_to_ndb_func(Item_func::Functype fun)
  {
    switch (fun) {
    case (Item_func::EQ_FUNC): { return NDB_EQ_FUNC; }
    case (Item_func::NE_FUNC): { return NDB_NE_FUNC; }
    case (Item_func::LT_FUNC): { return NDB_LT_FUNC; }
    case (Item_func::LE_FUNC): { return NDB_LE_FUNC; }
    case (Item_func::GT_FUNC): { return NDB_GT_FUNC; }
    case (Item_func::GE_FUNC): { return NDB_GE_FUNC; }
    case (Item_func::ISNULL_FUNC): { return NDB_ISNULL_FUNC; }
    case (Item_func::ISNOTNULL_FUNC): { return NDB_ISNOTNULL_FUNC; }
    case (Item_func::LIKE_FUNC): { return NDB_LIKE_FUNC; }
    case (Item_func::NOT_FUNC): { return NDB_NOT_FUNC; }
    case (Item_func::UNKNOWN_FUNC): { return NDB_UNKNOWN_FUNC; }
    case (Item_func::COND_AND_FUNC): { return NDB_COND_AND_FUNC; }
    case (Item_func::COND_OR_FUNC): { return NDB_COND_OR_FUNC; }
    default: { return NDB_UNSUPPORTED_FUNC; }
    }
  };

  static NDB_FUNC_TYPE negate(NDB_FUNC_TYPE fun)
362
  {
363 364
    uint i= (uint) fun;
    DBUG_ASSERT(fun == neg_map[i].pos_fun);
365 366
    return  neg_map[i].neg_fun;
  };
unknown's avatar
unknown committed
367

368 369 370 371 372 373
  NDB_ITEM_TYPE type;
  NDB_ITEM_QUALIFICATION qualification;
 private:
  NDB_ITEM_VALUE value;
};

374 375 376 377 378 379
/*
  This class implements a linked list used for storing a
  serialization of the Item tree for condition pushdown.
 */
class Ndb_cond 
{
380 381 382 383 384 385 386 387 388 389 390 391 392 393
 public:
  Ndb_cond() : ndb_item(NULL), next(NULL), prev(NULL) {};
  ~Ndb_cond() 
  { 
    if (ndb_item) delete ndb_item; 
    ndb_item= NULL; 
    if (next) delete next;
    next= prev= NULL; 
  };
  Ndb_item *ndb_item;
  Ndb_cond *next;
  Ndb_cond *prev;
};

394 395 396 397 398 399 400 401 402
/*
  This class implements a stack for storing several conditions
  for pushdown (represented as serialized Item trees using Ndb_cond).
  The current implementation only pushes one condition, but is
  prepared for handling several (C1 AND C2 ...) if the logic for 
  pushing conditions is extended in sql_select.
*/
class Ndb_cond_stack 
{
403 404 405 406 407 408
 public:
  Ndb_cond_stack() : ndb_cond(NULL), next(NULL) {};
  ~Ndb_cond_stack() 
  { 
    if (ndb_cond) delete ndb_cond; 
    ndb_cond= NULL; 
409
    if (next) delete next;
410 411 412 413 414 415
    next= NULL; 
  };
  Ndb_cond *ndb_cond;
  Ndb_cond_stack *next;
};

416 417 418 419 420 421 422 423 424 425 426 427 428 429 430
class Ndb_rewrite_context
{
public:
  Ndb_rewrite_context(Item_func *func) 
    : func_item(func), left_hand_item(NULL), count(0) {};
  ~Ndb_rewrite_context()
  {
    if (next) delete next;
  }
  const Item_func *func_item;
  const Item *left_hand_item;
  uint count;
  Ndb_rewrite_context *next;
};

431 432 433 434 435 436 437 438 439
/*
  This class is used for storing the context when traversing
  the Item tree. It stores a reference to the table the condition
  is defined on, the serialized representation being generated, 
  if the condition found is supported, and information what is
  expected next in the tree inorder for the condition to be supported.
*/
class Ndb_cond_traverse_context 
{
440
 public:
441
  Ndb_cond_traverse_context(TABLE *tab, void* ndb_tab, Ndb_cond_stack* stack)
442
    : table(tab), ndb_table(ndb_tab), 
443
    supported(TRUE), stack_ptr(stack), cond_ptr(NULL),
444 445
    expect_mask(0), expect_field_result_mask(0), skip(0), collation(NULL),
    rewrite_stack(NULL)
446 447 448 449
  {
    if (stack)
      cond_ptr= stack->ndb_cond;
  };
450 451 452 453
  ~Ndb_cond_traverse_context()
  {
    if (rewrite_stack) delete rewrite_stack;
  }
454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469
  void expect(Item::Type type)
  {
    expect_mask|= (1 << type);
  };
  void dont_expect(Item::Type type)
  {
    expect_mask&= ~(1 << type);
  };
  bool expecting(Item::Type type)
  {
    return (expect_mask & (1 << type));
  };
  void expect_nothing()
  {
    expect_mask= 0;
  };
470 471 472 473 474
  void expect_only(Item::Type type)
  {
    expect_mask= 0;
    expect(type);
  };
475 476 477 478 479 480 481 482 483 484 485 486 487

  void expect_field_result(Item_result result)
  {
    expect_field_result_mask|= (1 << result);
  };
  bool expecting_field_result(Item_result result)
  {
    return (expect_field_result_mask & (1 << result));
  };
  void expect_no_field_result()
  {
    expect_field_result_mask= 0;
  };
488 489 490 491 492
  void expect_only_field_result(Item_result result)
  {
    expect_field_result_mask= 0;
    expect_field_result(result);
  };
493 494 495 496 497 498 499 500 501 502 503
  void expect_collation(CHARSET_INFO* col)
  {
    collation= col;
  };
  bool expecting_collation(CHARSET_INFO* col)
  {
    bool matching= (!collation) ? true : (collation == col);
    collation= NULL;

    return matching;
  };
504 505 506

  TABLE* table;
  void* ndb_table;
507
  bool supported;
508 509 510 511
  Ndb_cond_stack* stack_ptr;
  Ndb_cond* cond_ptr;
  uint expect_mask;
  uint expect_field_result_mask;
unknown's avatar
unknown committed
512
  uint skip;
513
  CHARSET_INFO* collation;
514
  Ndb_rewrite_context *rewrite_stack;
515 516
};

517 518 519 520
/*
  Place holder for ha_ndbcluster thread specific data
*/

unknown's avatar
unknown committed
521 522 523 524 525
enum THD_NDB_OPTIONS
{
  TNO_NO_LOG_SCHEMA_OP= 1 << 0
};

526 527
class Thd_ndb 
{
528 529 530 531 532 533
 public:
  Thd_ndb();
  ~Thd_ndb();
  Ndb *ndb;
  ulong count;
  uint lock_count;
534 535
  NdbTransaction *all;
  NdbTransaction *stmt;
536
  int error;
unknown's avatar
unknown committed
537
  uint32 options;
538
  List<NDB_SHARE> changed_tables;
539 540
};

unknown's avatar
unknown committed
541 542 543
class ha_ndbcluster: public handler
{
 public:
unknown's avatar
unknown committed
544
  ha_ndbcluster(TABLE_SHARE *table);
unknown's avatar
unknown committed
545 546 547 548 549 550 551 552
  ~ha_ndbcluster();

  int open(const char *name, int mode, uint test_if_locked);
  int close(void);

  int write_row(byte *buf);
  int update_row(const byte *old_data, byte *new_data);
  int delete_row(const byte *buf);
553
  int index_init(uint index, bool sorted);
unknown's avatar
unknown committed
554 555
  int index_end();
  int index_read(byte *buf, const byte *key, uint key_len, 
556
                 enum ha_rkey_function find_flag);
unknown's avatar
unknown committed
557
  int index_read_idx(byte *buf, uint index, const byte *key, uint key_len, 
558
                     enum ha_rkey_function find_flag);
unknown's avatar
unknown committed
559 560 561 562
  int index_next(byte *buf);
  int index_prev(byte *buf);
  int index_first(byte *buf);
  int index_last(byte *buf);
563
  int index_read_last(byte * buf, const byte * key, uint key_len);
564
  int rnd_init(bool scan);
unknown's avatar
unknown committed
565 566 567 568
  int rnd_end();
  int rnd_next(byte *buf);
  int rnd_pos(byte *buf, byte *pos);
  void position(const byte *record);
569
  int read_range_first(const key_range *start_key,
570 571
                       const key_range *end_key,
                       bool eq_range, bool sorted);
572
  int read_range_first_to_buf(const key_range *start_key,
573 574 575
                              const key_range *end_key,
                              bool eq_range, bool sorted,
                              byte* buf);
576
  int read_range_next();
unknown's avatar
unknown committed
577
  int alter_tablespace(st_alter_tablespace *info);
578

579 580 581
  /**
   * Multi range stuff
   */
582
  int read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
583 584
                             KEY_MULTI_RANGE*ranges, uint range_count,
                             bool sorted, HANDLER_BUFFER *buffer);
585
  int read_multi_range_next(KEY_MULTI_RANGE **found_range_p);
586

587
  bool get_error_message(int error, String *buf);
unknown's avatar
unknown committed
588
  void info(uint);
589
  void get_dynamic_partition_info(PARTITION_INFO *stat_info, uint part_id);
unknown's avatar
unknown committed
590 591 592
  int extra(enum ha_extra_function operation);
  int extra_opt(enum ha_extra_function operation, ulong cache_size);
  int external_lock(THD *thd, int lock_type);
unknown's avatar
unknown committed
593
  int start_stmt(THD *thd, thr_lock_type lock_type);
unknown's avatar
unknown committed
594
  void print_error(int error, myf errflag);
595
  const char * table_type() const;
unknown's avatar
unknown committed
596
  const char ** bas_ext() const;
597
  ulong table_flags(void) const;
598 599 600
  int add_index(TABLE *table_arg, KEY *key_info, uint num_of_keys);
  int prepare_drop_index(TABLE *table_arg, uint *key_num, uint num_of_keys);
  int final_drop_index(TABLE *table_arg);
601
  void set_part_info(partition_info *part_info);
602
  ulong index_flags(uint idx, uint part, bool all_parts) const;
603 604 605 606
  uint max_supported_record_length() const;
  uint max_supported_keys() const;
  uint max_supported_key_parts() const;
  uint max_supported_key_length() const;
unknown's avatar
unknown committed
607
  uint max_supported_key_part_length() const;
unknown's avatar
unknown committed
608 609 610 611

  int rename_table(const char *from, const char *to);
  int delete_table(const char *name);
  int create(const char *name, TABLE *form, HA_CREATE_INFO *info);
unknown's avatar
unknown committed
612
  int create_handler_files(const char *file);
613
  int get_default_no_partitions(ulonglong max_rows);
unknown's avatar
unknown committed
614 615 616
  bool get_no_parts(const char *name, uint *no_parts);
  void set_auto_partitions(partition_info *part_info);

unknown's avatar
unknown committed
617
  THR_LOCK_DATA **store_lock(THD *thd,
618 619
                             THR_LOCK_DATA **to,
                             enum thr_lock_type lock_type);
unknown's avatar
unknown committed
620

621 622
  bool low_byte_first() const;
  bool has_transactions();
unknown's avatar
unknown committed
623 624 625

  virtual bool is_injective() const { return true; }

626
  const char* index_type(uint key_number);
unknown's avatar
unknown committed
627 628

  double scan_time();
unknown's avatar
unknown committed
629
  ha_rows records_in_range(uint inx, key_range *min_key, key_range *max_key);
630 631
  void start_bulk_insert(ha_rows rows);
  int end_bulk_insert();
unknown's avatar
unknown committed
632

633 634
  static Thd_ndb* seize_thd_ndb();
  static void release_thd_ndb(Thd_ndb* thd_ndb);
635
 
unknown's avatar
Merge  
unknown committed
636 637 638
static void set_dbname(const char *pathname, char *dbname);
static void set_tabname(const char *pathname, char *tabname);

639 640 641
  /*
    Condition pushdown
  */
642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668

 /*
   Push condition down to the table handler.
   SYNOPSIS
     cond_push()
     cond   Condition to be pushed. The condition tree must not be
     modified by the by the caller.
   RETURN
     The 'remainder' condition that caller must use to filter out records.
     NULL means the handler will not return rows that do not match the
     passed condition.
   NOTES
   The pushed conditions form a stack (from which one can remove the
   last pushed condition using cond_pop).
   The table handler filters out rows using (pushed_cond1 AND pushed_cond2 
   AND ... AND pushed_condN)
   or less restrictive condition, depending on handler's capabilities.
   
   handler->extra(HA_EXTRA_RESET) call empties the condition stack.
   Calls to rnd_init/rnd_end, index_init/index_end etc do not affect the  
   condition stack.
   The current implementation supports arbitrary AND/OR nested conditions
   with comparisons between columns and constants (including constant
   expressions and function calls) and the following comparison operators:
   =, !=, >, >=, <, <=, like, "not like", "is null", and "is not null". 
   Negated conditions are supported by NOT which generate NAND/NOR groups.
 */ 
669
  const COND *cond_push(const COND *cond);
670 671 672 673 674 675
 /*
   Pop the top condition from the condition stack of the handler instance.
   SYNOPSIS
     cond_pop()
     Pops the top if condition stack, if stack is not empty
 */
676 677
  void cond_pop();

678
  uint8 table_cache_type();
679
  my_bool register_query_cache_table(THD *thd, char *table_key,
680 681 682
                                     uint key_length,
                                     qc_engine_callback *engine_callback,
                                     ulonglong *engine_data);
unknown's avatar
unknown committed
683

unknown's avatar
unknown committed
684 685
  bool check_if_incompatible_data(HA_CREATE_INFO *info,
				  uint table_changes);
unknown's avatar
unknown committed
686

687
private:
688
  friend int ndbcluster_drop_database_impl(const char *path);
689 690 691 692
  friend int ndb_handle_schema_change(THD *thd, 
                                      Ndb *ndb, NdbEventOperation *pOp,
                                      NDB_SHARE *share);

693
  int alter_table_name(const char *to);
unknown's avatar
unknown committed
694 695 696 697
  static int delete_table(ha_ndbcluster *h, Ndb *ndb,
			  const char *path,
			  const char *db,
			  const char *table_name);
698 699
  int drop_ndb_table();
  int create_ndb_index(const char *name, KEY *key_info, bool unique);
700 701
  int create_ordered_index(const char *name, KEY *key_info);
  int create_unique_index(const char *name, KEY *key_info);
702 703 704
  int create_index(const char *name, KEY *key_info, 
                   NDB_INDEX_TYPE idx_type, uint idx_no);
  int drop_ndb_index(const char *name);
unknown's avatar
unknown committed
705
  int table_changed(const void *pack_frm_data, uint pack_frm_len);
706 707 708 709
// Index list management
  int create_indexes(Ndb *ndb, TABLE *tab);
  void clear_index(int i);
  void clear_indexes();
710
  int open_indexes(Ndb *ndb, TABLE *tab, bool ignore_error);
711
  void renumber_indexes(Ndb *ndb, TABLE *tab);
712 713 714
  int drop_indexes(Ndb *ndb, TABLE *tab);
  int add_index_handle(THD *thd, NdbDictionary::Dictionary *dict,
                       KEY *key_info, const char *index_name, uint index_no);
unknown's avatar
unknown committed
715
  int initialize_autoincrement(const void *table);
unknown's avatar
unknown committed
716 717 718 719
  int get_metadata(const char* path);
  void release_metadata();
  NDB_INDEX_TYPE get_index_type(uint idx_no) const;
  NDB_INDEX_TYPE get_index_type_from_table(uint index_no) const;
720 721
  NDB_INDEX_TYPE get_index_type_from_key(uint index_no, KEY *key_info, 
                                         bool primary) const;
722 723
  int check_index_fields_not_null(uint index_no);

724 725 726
  uint set_up_partition_info(partition_info *part_info,
                             TABLE *table,
                             void *tab);
727
  char* get_tablespace_name(THD *thd);
unknown's avatar
unknown committed
728 729
  int set_range_data(void *tab, partition_info* part_info);
  int set_list_data(void *tab, partition_info* part_info);
730 731
  int complemented_read(const byte *old_data, byte *new_data,
                        uint32 old_part_id);
732
  int pk_read(const byte *key, uint key_len, byte *buf, uint32 part_id);
733
  int ordered_index_scan(const key_range *start_key,
734
                         const key_range *end_key,
735 736
                         bool sorted, bool descending, byte* buf,
                         part_id_range *part_spec);
unknown's avatar
unknown committed
737
  int full_table_scan(byte * buf);
738

739 740 741 742 743
  bool check_all_operations_for_error(NdbTransaction *trans,
                                      const NdbOperation *first,
                                      const NdbOperation *last,
                                      uint errcode);
  int peek_indexed_rows(const byte *record);
744 745
  int unique_index_read(const byte *key, uint key_len, 
                        byte *buf);
unknown's avatar
unknown committed
746
  int fetch_next(NdbScanOperation* op);
unknown's avatar
unknown committed
747
  int next_result(byte *buf); 
748
  int define_read_attrs(byte* buf, NdbOperation* op);
unknown's avatar
unknown committed
749
  int filtered_scan(const byte *key, uint key_len, 
750 751
                    byte *buf,
                    enum ha_rkey_function find_flag);
752
  int close_scan();
unknown's avatar
unknown committed
753
  void unpack_record(byte *buf);
unknown's avatar
unknown committed
754
  int get_ndb_lock_type(enum thr_lock_type type);
unknown's avatar
unknown committed
755 756 757 758 759

  void set_dbname(const char *pathname);
  void set_tabname(const char *pathname);

  bool set_hidden_key(NdbOperation*,
760
                      uint fieldnr, const byte* field_ptr);
unknown's avatar
unknown committed
761
  int set_ndb_key(NdbOperation*, Field *field,
762
                  uint fieldnr, const byte* field_ptr);
unknown's avatar
unknown committed
763 764
  int set_ndb_value(NdbOperation*, Field *field, uint fieldnr,
		    int row_offset= 0, bool *set_blob_value= 0);
unknown's avatar
unknown committed
765
  int get_ndb_value(NdbOperation*, Field *field, uint fieldnr, byte*);
unknown's avatar
unknown committed
766
  int get_ndb_partition_id(NdbOperation *);
unknown's avatar
unknown committed
767
  friend int g_get_ndb_blobs_value(NdbBlob *ndb_blob, void *arg);
unknown's avatar
unknown committed
768
  int get_ndb_blobs_value(NdbBlob *last_ndb_blob);
unknown's avatar
unknown committed
769
  int set_primary_key(NdbOperation *op, const byte *key);
770
  int set_primary_key_from_record(NdbOperation *op, const byte *record);
771 772
  int set_index_key_from_record(NdbOperation *op, const byte *record,
                                uint keyno);
773 774
  int set_bounds(NdbIndexScanOperation*, uint inx, bool rir,
                 const key_range *keys[2], uint= 0);
unknown's avatar
unknown committed
775
  int key_cmp(uint keynr, const byte * old_row, const byte * new_row);
776
  int set_index_key(NdbOperation *, const KEY *key_info, const byte *key_ptr);
unknown's avatar
unknown committed
777 778
  void print_results();

779
  ulonglong get_auto_increment();
780
  int invalidate_dictionary_cache(bool global);
781
  int ndb_err(NdbTransaction*);
782
  bool uses_blob_value();
unknown's avatar
unknown committed
783

unknown's avatar
unknown committed
784 785
  char *update_table_comment(const char * comment);

unknown's avatar
unknown committed
786
  int write_ndb_file(const char *name);
787

788
  int check_ndb_connection(THD* thd= current_thd);
unknown's avatar
unknown committed
789

790 791 792 793 794 795 796 797
  void set_rec_per_key();
  void records_update();
  void no_uncommitted_rows_execute_failure();
  void no_uncommitted_rows_update(int);
  void no_uncommitted_rows_init(THD *);
  void no_uncommitted_rows_reset(THD *);

  /*
unknown's avatar
unknown committed
798
    Condition pushdown
799 800 801
  */
  void cond_clear();
  bool serialize_cond(const COND *cond, Ndb_cond_stack *ndb_cond);
802
  int build_scan_filter_predicate(Ndb_cond* &cond, 
803 804
                                  NdbScanFilter* filter,
                                  bool negated= false);
805
  int build_scan_filter_group(Ndb_cond* &cond, 
806
                              NdbScanFilter* filter);
807 808
  int build_scan_filter(Ndb_cond* &cond, NdbScanFilter* filter);
  int generate_scan_filter(Ndb_cond_stack* cond_stack, 
809
                           NdbScanOperation* op);
810

unknown's avatar
unknown committed
811
  friend int execute_commit(ha_ndbcluster*, NdbTransaction*);
unknown's avatar
unknown committed
812
  friend int execute_no_commit_ignore_no_key(ha_ndbcluster*, NdbTransaction*);
unknown's avatar
unknown committed
813 814
  friend int execute_no_commit(ha_ndbcluster*, NdbTransaction*);
  friend int execute_no_commit_ie(ha_ndbcluster*, NdbTransaction*);
815

816
  NdbTransaction *m_active_trans;
unknown's avatar
unknown committed
817
  NdbScanOperation *m_active_cursor;
818
  void *m_table;
819
  int m_table_version;
820
  void *m_table_info;
unknown's avatar
unknown committed
821 822 823 824 825 826
  char m_dbname[FN_HEADLEN];
  //char m_schemaname[FN_HEADLEN];
  char m_tabname[FN_HEADLEN];
  ulong m_table_flags;
  THR_LOCK_DATA m_lock;
  NDB_SHARE *m_share;
827
  NDB_INDEX_DATA  m_index[MAX_KEY];
unknown's avatar
unknown committed
828 829
  // NdbRecAttr has no reference to blob
  NdbValue m_value[NDB_MAX_ATTRIBUTES_IN_TABLE];
830
  byte m_ref[NDB_HIDDEN_PRIMARY_KEY_LENGTH];
831
  partition_info *m_part_info;
832
  uint32 m_part_id;
833 834 835 836
  byte *m_rec0;
  Field **m_part_field_array;
  bool m_use_partition_function;
  bool m_sorted;
unknown's avatar
unknown committed
837
  bool m_use_write;
838
  bool m_ignore_dup_key;
839
  bool m_has_unique_index;
840
  bool m_primary_key_update;
841
  bool m_write_op;
unknown's avatar
unknown committed
842
  bool m_ignore_no_key;
843 844 845
  ha_rows m_rows_to_insert;
  ha_rows m_rows_inserted;
  ha_rows m_bulk_insert_rows;
846
  ha_rows m_rows_changed;
847 848 849 850
  bool m_bulk_insert_not_flushed;
  ha_rows m_ops_pending;
  bool m_skip_auto_increment;
  bool m_blobs_pending;
unknown's avatar
unknown committed
851
  // memory for blobs in one tuple
852 853 854
  char *m_blobs_buffer;
  uint32 m_blobs_buffer_size;
  uint m_dupkey;
unknown's avatar
unknown committed
855
  // set from thread variables at external lock
856 857 858 859
  bool m_ha_not_exact_count;
  bool m_force_send;
  ha_rows m_autoincrement_prefetch;
  bool m_transaction_on;
860
  Ndb_cond_stack *m_cond_stack;
861
  bool m_disable_multi_read;
unknown's avatar
unknown committed
862
  byte *m_multi_range_result_ptr;
863 864
  KEY_MULTI_RANGE *m_multi_ranges;
  KEY_MULTI_RANGE *m_multi_range_defined;
unknown's avatar
unknown committed
865 866 867
  const NdbOperation *m_current_multi_operation;
  NdbIndexScanOperation *m_multi_cursor;
  byte *m_multi_range_cursor_result_ptr;
868
  int setup_recattr(const NdbRecAttr*);
869
  Ndb *get_ndb();
unknown's avatar
unknown committed
870 871
};

unknown's avatar
unknown committed
872
extern SHOW_VAR ndb_status_variables[];
873

874
int ndbcluster_discover(THD* thd, const char* dbname, const char* name,
875
                        const void** frmblob, uint* frmlen);
876
int ndbcluster_find_files(THD *thd,const char *db,const char *path,
877
                          const char *wild, bool dir, List<char> *files);
878 879
int ndbcluster_table_exists_in_engine(THD* thd,
                                      const char *db, const char *name);
880
void ndbcluster_print_error(int error, const NdbOperation *error_op);