ha_ndbcluster.h 22.7 KB
Newer Older
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
25 26 27 28 29
#pragma interface                       /* gcc class implementation */
#endif

#include <ndbapi_limits.h>

30 31
#define NDB_HIDDEN_PRIMARY_KEY_LENGTH 8

32 33
class Ndb;             // Forward declaration
class NdbOperation;    // Forward declaration
34
class NdbTransaction;  // Forward declaration
35
class NdbRecAttr;      // Forward declaration
joreland@mysql.com's avatar
joreland@mysql.com committed
36
class NdbScanOperation; 
37
class NdbScanFilter; 
joreland@mysql.com's avatar
joreland@mysql.com committed
38
class NdbIndexScanOperation; 
pekka@mysql.com's avatar
pekka@mysql.com committed
39
class NdbBlob;
40

41 42
// connectstring to cluster if given by mysqld
extern const char *ndbcluster_connectstring;
43
extern ulong ndb_cache_check_time;
44

45 46 47
typedef enum ndb_index_type {
  UNDEFINED_INDEX = 0,
  PRIMARY_KEY_INDEX = 1,
48 49 50 51
  PRIMARY_KEY_ORDERED_INDEX = 2,
  UNIQUE_INDEX = 3,
  UNIQUE_ORDERED_INDEX = 4,
  ORDERED_INDEX = 5
52 53
} NDB_INDEX_TYPE;

54 55 56 57
typedef struct ndb_index_data {
  NDB_INDEX_TYPE type;
  void *index;
  void *unique_index;
58
  unsigned char *unique_index_attrid_map;
59
} NDB_INDEX_DATA;
60 61 62 63 64 65

typedef struct st_ndbcluster_share {
  THR_LOCK lock;
  pthread_mutex_t mutex;
  char *table_name;
  uint table_name_length,use_count;
66
  uint commit_count_lock;
67
  ulonglong commit_count;
68 69
} NDB_SHARE;

70 71 72
typedef enum ndb_item_type {
  NDB_VALUE = 0,   // Qualified more with Item::Type
  NDB_FIELD = 1,   // Qualified from table definition
73 74
  NDB_FUNCTION = 2,// Qualified from Item_func::Functype
  NDB_END_COND = 3 // End marker for condition group
75 76
} NDB_ITEM_TYPE;

77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
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;

95 96
typedef union ndb_item_qualification {
  Item::Type value_type; 
97 98
  enum_field_types field_type; // Instead of Item::FIELD_ITEM
  NDB_FUNC_TYPE function_type; // Instead of Item::FUNC_ITEM
99 100 101 102 103 104 105 106
} NDB_ITEM_QUALIFICATION;

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

typedef union ndb_item_value {
mskold@mysql.com's avatar
mskold@mysql.com committed
107
  const Item *item;
108
  NDB_ITEM_FIELD_VALUE *field_value;
109
  uint arg_count;
110 111
} NDB_ITEM_VALUE;

112 113
struct negated_function_mapping
{
114 115
  NDB_FUNC_TYPE pos_fun;
  NDB_FUNC_TYPE neg_fun;
116 117
};

118 119 120 121
/*
  Define what functions can be negated in condition pushdown.
  Note, these HAVE to be in the same order as in definition enum
*/
122 123
static const negated_function_mapping neg_map[]= 
{
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
  {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}
139 140
};
  
141
/*
142 143 144 145 146 147 148
  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
149
  breadth-first traversal of the Item (i.e. expression) tree in prefix order.
150 151 152 153
  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.
*/
154 155
class Ndb_item {
 public:
mskold@mysql.com's avatar
mskold@mysql.com committed
156
  Ndb_item(NDB_ITEM_TYPE item_type) : type(item_type) {};
157
  Ndb_item(NDB_ITEM_TYPE item_type, 
158 159
           NDB_ITEM_QUALIFICATION item_qualification,
           const Item *item_value)
mskold@mysql.com's avatar
mskold@mysql.com committed
160 161 162 163 164 165 166 167 168 169 170 171
    : 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;
172 173
      break;
    }
mskold@mysql.com's avatar
mskold@mysql.com committed
174
    case(NDB_FUNCTION):
175
      value.item= item_value;
176
      value.arg_count= ((Item_func *) item_value)->argument_count();
177
      break;
mskold@mysql.com's avatar
mskold@mysql.com committed
178 179
    case(NDB_END_COND):
      break;
180
    }
mskold@mysql.com's avatar
mskold@mysql.com committed
181 182 183 184 185 186 187 188 189
  };
  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;
  };
190 191
  Ndb_item(Item_func::Functype func_type, const Item *item_value) 
    : type(NDB_FUNCTION)
mskold@mysql.com's avatar
mskold@mysql.com committed
192
  {
193
    qualification.function_type= item_func_to_ndb_func(func_type);
194
    value.item= item_value;
195 196 197 198 199
    value.arg_count= ((Item_func *) item_value)->argument_count();
  };
  Ndb_item(Item_func::Functype func_type, uint no_args) 
    : type(NDB_FUNCTION)
  {
200
    qualification.function_type= item_func_to_ndb_func(func_type);
201
    value.arg_count= no_args;
mskold@mysql.com's avatar
mskold@mysql.com committed
202 203 204 205 206
  };
  ~Ndb_item()
  { 
    if (type == NDB_FIELD)
      {
207 208
        delete value.field_value;
        value.field_value= NULL;
mskold@mysql.com's avatar
mskold@mysql.com committed
209 210 211 212 213 214
      }
  };

  uint32 pack_length() 
  { 
    switch(type) {
215 216 217 218
    case(NDB_VALUE):
      if(qualification.value_type == Item::STRING_ITEM)
        return value.item->str_value.length();
      break;
mskold@mysql.com's avatar
mskold@mysql.com committed
219 220
    case(NDB_FIELD):
      return value.field_value->field->pack_length(); 
221 222 223
    default:
      break;
    }
mskold@mysql.com's avatar
mskold@mysql.com committed
224 225 226
    
    return 0;
  };
227

mskold@mysql.com's avatar
mskold@mysql.com committed
228
  Field * get_field() { return value.field_value->field; };
229

mskold@mysql.com's avatar
mskold@mysql.com committed
230
  int get_field_no() { return value.field_value->column_no; };
231

232 233
  int argument_count() 
  { 
234
    return value.arg_count;
235 236
  };

237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
  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;
  };

mskold@mysql.com's avatar
mskold@mysql.com committed
253 254 255 256
  void save_in_field(Ndb_item *field_item)
  {
    Field *field = field_item->value.field_value->field;
    const Item *item= value.item;
257

mskold@mysql.com's avatar
mskold@mysql.com committed
258 259
    if (item && field)
      ((Item *)item)->save_in_field(field, false);
260 261
  };

262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282
  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)
283
  {
284 285
    uint i= (uint) fun;
    DBUG_ASSERT(fun == neg_map[i].pos_fun);
286 287
    return  neg_map[i].neg_fun;
  };
mskold@mysql.com's avatar
mskold@mysql.com committed
288

289 290 291 292 293 294
  NDB_ITEM_TYPE type;
  NDB_ITEM_QUALIFICATION qualification;
 private:
  NDB_ITEM_VALUE value;
};

295 296 297 298 299 300
/*
  This class implements a linked list used for storing a
  serialization of the Item tree for condition pushdown.
 */
class Ndb_cond 
{
301 302 303 304 305 306 307 308 309 310 311 312 313 314
 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;
};

315 316 317 318 319 320 321 322 323
/*
  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 
{
324 325 326 327 328 329
 public:
  Ndb_cond_stack() : ndb_cond(NULL), next(NULL) {};
  ~Ndb_cond_stack() 
  { 
    if (ndb_cond) delete ndb_cond; 
    ndb_cond= NULL; 
330
    if (next) delete next;
331 332 333 334 335 336
    next= NULL; 
  };
  Ndb_cond *ndb_cond;
  Ndb_cond_stack *next;
};

337 338 339 340 341 342 343 344 345 346 347 348 349 350 351
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;
};

352 353 354 355 356 357 358 359 360
/*
  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 
{
361
 public:
362
  Ndb_cond_traverse_context(TABLE *tab, void* ndb_tab, Ndb_cond_stack* stack)
363
    : table(tab), ndb_table(ndb_tab), 
364
    supported(TRUE), stack_ptr(stack), cond_ptr(NULL),
365 366
    expect_mask(0), expect_field_result_mask(0), skip(0), collation(NULL),
    rewrite_stack(NULL)
367 368 369 370
  {
    if (stack)
      cond_ptr= stack->ndb_cond;
  };
371 372 373 374
  ~Ndb_cond_traverse_context()
  {
    if (rewrite_stack) delete rewrite_stack;
  }
375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390
  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;
  };
391 392 393 394 395
  void expect_only(Item::Type type)
  {
    expect_mask= 0;
    expect(type);
  };
396 397 398 399 400 401 402 403 404 405 406 407 408

  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;
  };
409 410 411 412 413
  void expect_only_field_result(Item_result result)
  {
    expect_field_result_mask= 0;
    expect_field_result(result);
  };
414 415 416 417 418 419 420 421 422 423 424
  void expect_collation(CHARSET_INFO* col)
  {
    collation= col;
  };
  bool expecting_collation(CHARSET_INFO* col)
  {
    bool matching= (!collation) ? true : (collation == col);
    collation= NULL;

    return matching;
  };
425 426 427

  TABLE* table;
  void* ndb_table;
428
  bool supported;
429 430 431 432
  Ndb_cond_stack* stack_ptr;
  Ndb_cond* cond_ptr;
  uint expect_mask;
  uint expect_field_result_mask;
mskold@mysql.com's avatar
mskold@mysql.com committed
433
  uint skip;
434
  CHARSET_INFO* collation;
435
  Ndb_rewrite_context *rewrite_stack;
436 437
};

438 439 440 441
/*
  Place holder for ha_ndbcluster thread specific data
*/

442 443
class Thd_ndb 
{
444 445 446 447 448 449
 public:
  Thd_ndb();
  ~Thd_ndb();
  Ndb *ndb;
  ulong count;
  uint lock_count;
450 451
  NdbTransaction *all;
  NdbTransaction *stmt;
452
  int error;
453
  List<NDB_SHARE> changed_tables;
454 455
};

456 457 458 459 460 461 462 463 464 465 466 467 468 469 470
class ha_ndbcluster: public handler
{
 public:
  ha_ndbcluster(TABLE *table);
  ~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);
  int index_init(uint index);
  int index_end();
  int index_read(byte *buf, const byte *key, uint key_len, 
471
                 enum ha_rkey_function find_flag);
472
  int index_read_idx(byte *buf, uint index, const byte *key, uint key_len, 
473
                     enum ha_rkey_function find_flag);
474 475 476 477
  int index_next(byte *buf);
  int index_prev(byte *buf);
  int index_first(byte *buf);
  int index_last(byte *buf);
478
  int index_read_last(byte * buf, const byte * key, uint key_len);
479
  int rnd_init(bool scan);
480 481 482 483
  int rnd_end();
  int rnd_next(byte *buf);
  int rnd_pos(byte *buf, byte *pos);
  void position(const byte *record);
484
  int read_range_first(const key_range *start_key,
485 486
                       const key_range *end_key,
                       bool eq_range, bool sorted);
487
  int read_range_first_to_buf(const key_range *start_key,
488 489 490
                              const key_range *end_key,
                              bool eq_range, bool sorted,
                              byte* buf);
491
  int read_range_next();
492

493 494 495
  /**
   * Multi range stuff
   */
496
  int read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
497 498
                             KEY_MULTI_RANGE*ranges, uint range_count,
                             bool sorted, HANDLER_BUFFER *buffer);
499
  int read_multi_range_next(KEY_MULTI_RANGE **found_range_p);
500

501
  bool get_error_message(int error, String *buf);
502 503 504 505
  void info(uint);
  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);
serg@serg.mylan's avatar
serg@serg.mylan committed
506
  int start_stmt(THD *thd, thr_lock_type lock_type);
507
  const char * table_type() const;
508
  const char ** bas_ext() const;
509
  ulong table_flags(void) const;
510
  ulong index_flags(uint idx, uint part, bool all_parts) const;
511 512 513 514
  uint max_supported_record_length() const;
  uint max_supported_keys() const;
  uint max_supported_key_parts() const;
  uint max_supported_key_length() const;
pekka@mysql.com's avatar
pekka@mysql.com committed
515
  uint max_supported_key_part_length() const;
516 517 518 519 520

  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);
  THR_LOCK_DATA **store_lock(THD *thd,
521 522
                             THR_LOCK_DATA **to,
                             enum thr_lock_type lock_type);
523

524 525 526
  bool low_byte_first() const;
  bool has_transactions();
  const char* index_type(uint key_number);
527 528

  double scan_time();
529
  ha_rows records_in_range(uint inx, key_range *min_key, key_range *max_key);
530 531
  void start_bulk_insert(ha_rows rows);
  int end_bulk_insert();
532

533 534
  static Thd_ndb* seize_thd_ndb();
  static void release_thd_ndb(Thd_ndb* thd_ndb);
535
 
mskold@mysql.com's avatar
Merge  
mskold@mysql.com committed
536 537 538
static void set_dbname(const char *pathname, char *dbname);
static void set_tabname(const char *pathname, char *tabname);

539 540 541
  /*
    Condition pushdown
  */
542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568

 /*
   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.
 */ 
569
  const COND *cond_push(const COND *cond);
570 571 572 573 574 575
 /*
   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
 */
576 577
  void cond_pop();

578
  uint8 table_cache_type();
579
  my_bool register_query_cache_table(THD *thd, char *table_key,
580 581 582
                                     uint key_length,
                                     qc_engine_callback *engine_callback,
                                     ulonglong *engine_data);
583
private:
584
  int alter_table_name(const char *to);
585
  int drop_table();
586 587 588
  int create_index(const char *name, KEY *key_info, bool unique);
  int create_ordered_index(const char *name, KEY *key_info);
  int create_unique_index(const char *name, KEY *key_info);
589
  int initialize_autoincrement(const void *table);
mskold@mysql.com's avatar
mskold@mysql.com committed
590
  enum ILBP {ILBP_CREATE = 0, ILBP_OPEN = 1}; // Index List Build Phase
591
  int build_index_list(Ndb *ndb, TABLE *tab, enum ILBP phase);
592 593 594 595
  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;
596 597
  int check_index_fields_not_null(uint index_no);

598 599
  int pk_read(const byte *key, uint key_len, byte *buf);
  int complemented_pk_read(const byte *old_data, byte *new_data);
600 601 602 603 604
  bool check_all_operations_for_error(NdbTransaction *trans,
                                      const NdbOperation *first,
                                      const NdbOperation *last,
                                      uint errcode);
  int peek_indexed_rows(const byte *record);
605
  int unique_index_read(const byte *key, uint key_len, 
606
                        byte *buf);
607
  int ordered_index_scan(const key_range *start_key,
608 609
                         const key_range *end_key,
                         bool sorted, bool descending, byte* buf);
610
  int full_table_scan(byte * buf);
611
  int fetch_next(NdbScanOperation* op);
612
  int next_result(byte *buf); 
613
  int define_read_attrs(byte* buf, NdbOperation* op);
614
  int filtered_scan(const byte *key, uint key_len, 
615 616
                    byte *buf,
                    enum ha_rkey_function find_flag);
617
  int close_scan();
618
  void unpack_record(byte *buf);
pekka@mysql.com's avatar
pekka@mysql.com committed
619
  int get_ndb_lock_type(enum thr_lock_type type);
620 621 622 623 624

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

  bool set_hidden_key(NdbOperation*,
625
                      uint fieldnr, const byte* field_ptr);
626
  int set_ndb_key(NdbOperation*, Field *field,
627
                  uint fieldnr, const byte* field_ptr);
628
  int set_ndb_value(NdbOperation*, Field *field, uint fieldnr, bool *set_blob_value= 0);
joreland@mysql.com's avatar
joreland@mysql.com committed
629
  int get_ndb_value(NdbOperation*, Field *field, uint fieldnr, byte*);
630
  friend int g_get_ndb_blobs_value(NdbBlob *ndb_blob, void *arg);
pekka@mysql.com's avatar
pekka@mysql.com committed
631
  int get_ndb_blobs_value(NdbBlob *last_ndb_blob);
632
  int set_primary_key(NdbOperation *op, const byte *key);
633
  int set_primary_key_from_record(NdbOperation *op, const byte *record);
634 635
  int set_index_key_from_record(NdbOperation *op, const byte *record,
                                uint keyno);
636
  int set_bounds(NdbIndexScanOperation*, const key_range *keys[2], uint= 0);
637
  int key_cmp(uint keynr, const byte * old_row, const byte * new_row);
638
  int set_index_key(NdbOperation *, const KEY *key_info, const byte *key_ptr);
639 640
  void print_results();

641
  ulonglong get_auto_increment();
642
  void invalidate_dictionary_cache(bool global);
643
  int ndb_err(NdbTransaction*);
pekka@mysql.com's avatar
pekka@mysql.com committed
644
  bool uses_blob_value(bool all_fields);
645

mskold@mysql.com's avatar
mskold@mysql.com committed
646 647
  char *update_table_comment(const char * comment);

648 649
  int write_ndb_file();

650
  int check_ndb_connection(THD* thd= current_thd);
651

652 653 654 655 656 657 658 659
  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 *);

  /*
mskold@mysql.com's avatar
mskold@mysql.com committed
660
    Condition pushdown
661 662 663
  */
  void cond_clear();
  bool serialize_cond(const COND *cond, Ndb_cond_stack *ndb_cond);
664
  int build_scan_filter_predicate(Ndb_cond* &cond, 
665 666
                                  NdbScanFilter* filter,
                                  bool negated= false);
667
  int build_scan_filter_group(Ndb_cond* &cond, 
668
                              NdbScanFilter* filter);
669 670
  int build_scan_filter(Ndb_cond* &cond, NdbScanFilter* filter);
  int generate_scan_filter(Ndb_cond_stack* cond_stack, 
671
                           NdbScanOperation* op);
672

673 674 675
  friend int execute_commit(ha_ndbcluster*, NdbTransaction*);
  friend int execute_no_commit(ha_ndbcluster*, NdbTransaction*);
  friend int execute_no_commit_ie(ha_ndbcluster*, NdbTransaction*);
676

677
  NdbTransaction *m_active_trans;
678
  NdbScanOperation *m_active_cursor;
679
  void *m_table;
680
  int m_table_version;
681
  void *m_table_info;
682 683 684 685 686 687
  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;
688
  NDB_INDEX_DATA  m_index[MAX_KEY];
pekka@mysql.com's avatar
pekka@mysql.com committed
689
  // NdbRecAttr has no reference to blob
690
  typedef union { const NdbRecAttr *rec; NdbBlob *blob; void *ptr; } NdbValue;
pekka@mysql.com's avatar
pekka@mysql.com committed
691
  NdbValue m_value[NDB_MAX_ATTRIBUTES_IN_TABLE];
692
  byte m_ref[NDB_HIDDEN_PRIMARY_KEY_LENGTH];
693
  bool m_use_write;
694
  bool m_ignore_dup_key;
695
  bool m_has_unique_index;
696 697
  bool m_primary_key_update;
  bool m_retrieve_all_fields;
698
  bool m_retrieve_primary_key;
699 700 701
  ha_rows m_rows_to_insert;
  ha_rows m_rows_inserted;
  ha_rows m_bulk_insert_rows;
702
  ha_rows m_rows_changed;
703 704 705 706
  bool m_bulk_insert_not_flushed;
  ha_rows m_ops_pending;
  bool m_skip_auto_increment;
  bool m_blobs_pending;
pekka@mysql.com's avatar
pekka@mysql.com committed
707
  // memory for blobs in one tuple
708 709 710
  char *m_blobs_buffer;
  uint32 m_blobs_buffer_size;
  uint m_dupkey;
711
  // set from thread variables at external lock
712 713 714 715
  bool m_ha_not_exact_count;
  bool m_force_send;
  ha_rows m_autoincrement_prefetch;
  bool m_transaction_on;
716
  Ndb_cond_stack *m_cond_stack;
717
  bool m_disable_multi_read;
718
  byte *m_multi_range_result_ptr;
719 720
  KEY_MULTI_RANGE *m_multi_ranges;
  KEY_MULTI_RANGE *m_multi_range_defined;
721 722 723
  const NdbOperation *m_current_multi_operation;
  NdbIndexScanOperation *m_multi_cursor;
  byte *m_multi_range_cursor_result_ptr;
724
  int setup_recattr(const NdbRecAttr*);
725
  Ndb *get_ndb();
726 727
};

728 729
extern struct show_var_st ndb_status_variables[];

730
bool ndbcluster_init(void);
731 732
bool ndbcluster_end(void);

733
int ndbcluster_discover(THD* thd, const char* dbname, const char* name,
734
                        const void** frmblob, uint* frmlen);
735
int ndbcluster_find_files(THD *thd,const char *db,const char *path,
736
                          const char *wild, bool dir, List<char> *files);
737 738
int ndbcluster_table_exists_in_engine(THD* thd,
                                      const char *db, const char *name);
739 740
int ndbcluster_drop_database(const char* path);

741
void ndbcluster_print_error(int error, const NdbOperation *error_op);
742 743

int ndbcluster_show_status(THD*);