sql_class.h 112 KB
Newer Older
Sergei Golubchik's avatar
Sergei Golubchik committed
1
/* Copyright (C) 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.
unknown's avatar
unknown committed
2

unknown's avatar
unknown committed
3 4
   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
unknown's avatar
unknown committed
5
   the Free Software Foundation; version 2 of the License.
unknown's avatar
unknown committed
6

unknown's avatar
unknown committed
7 8 9 10
   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.
unknown's avatar
unknown committed
11

unknown's avatar
unknown committed
12 13 14 15 16 17 18
   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 */


/* Classes in mysql */

19
#ifdef USE_PRAGMA_INTERFACE
unknown's avatar
unknown committed
20 21 22
#pragma interface			/* gcc class implementation */
#endif

23 24
#include "log.h"
#include "rpl_tblmap.h"
25

unknown's avatar
unknown committed
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64

/**
  Interface for Item iterator
*/

class Item_iterator
{
public:
  /**
    Shall set this iterator to the position before the first item

    @note
    This method also may perform some other initialization actions like
    allocation of certain resources.
  */
  virtual void open()= 0;
  /**
    Shall return the next Item (or NULL if there is no next item) and
    move pointer to position after it.
  */
  virtual Item *next()= 0;
  /**
    Shall force iterator to free resources (if it holds them)

    @note
    One should not use the iterator without open() call after close()
  */
  virtual void close()= 0;

  virtual ~Item_iterator() {}
};


/**
  Item iterator over List_iterator_fast for Item references
*/

class Item_iterator_ref_list: public Item_iterator
{
65
  List_iterator<Item*> list;
unknown's avatar
unknown committed
66
public:
67
  Item_iterator_ref_list(List_iterator<Item*> &arg_list):
unknown's avatar
unknown committed
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
    list(arg_list) {}
  void open() { list.rewind(); }
  Item *next() { return *(list++); }
  void close() {}
};


/**
  Item iterator over Item interface for rows
*/

class Item_iterator_row: public Item_iterator
{
  Item *base_item;
  uint current;
public:
  Item_iterator_row(Item *base) : base_item(base), current(0) {}
  void open() { current= 0; }
  Item *next()
  {
    if (current >= base_item->cols())
      return NULL;
    return base_item->element_index(current++);
  }
  void close() {}
};


unknown's avatar
unknown committed
96
/**
97
  An interface that is used to take an action when
unknown's avatar
unknown committed
98 99 100 101 102 103 104 105 106 107 108
  the locking module notices that a table version has changed
  since the last execution. "Table" here may refer to any kind of
  table -- a base table, a temporary table, a view or an
  information schema table.

  When we open and lock tables for execution of a prepared
  statement, we must verify that they did not change
  since statement prepare. If some table did change, the statement
  parse tree *may* be no longer valid, e.g. in case it contains
  optimizations that depend on table metadata.

109
  This class provides an interface (a method) that is
unknown's avatar
unknown committed
110
  invoked when such a situation takes place.
111 112
  The implementation of the method simply reports an error, but
  the exact details depend on the nature of the SQL statement.
unknown's avatar
unknown committed
113 114

  At most 1 instance of this class is active at a time, in which
115
  case THD::m_reprepare_observer is not NULL.
unknown's avatar
unknown committed
116

117
  @sa check_and_update_table_version() for details of the
unknown's avatar
unknown committed
118 119
  version tracking algorithm 

120
  @sa Open_tables_state::m_reprepare_observer for the life cycle
unknown's avatar
unknown committed
121 122 123
  of metadata observers.
*/

124
class Reprepare_observer
unknown's avatar
unknown committed
125 126 127 128 129 130 131 132
{
public:
  /**
    Check if a change of metadata is OK. In future
    the signature of this method may be extended to accept the old
    and the new versions, but since currently the check is very
    simple, we only need the THD to report an error.
  */
133 134 135
  bool report_error(THD *thd);
  bool is_invalidated() const { return m_invalidated; }
  void reset_reprepare_observer() { m_invalidated= FALSE; }
Michael Widenius's avatar
Michael Widenius committed
136
  Reprepare_observer() {}                     /* Remove gcc warning */
137 138
private:
  bool m_invalidated;
unknown's avatar
unknown committed
139 140
};

141
#include <waiting_threads.h>
142

143
class Relay_log_info;
144

unknown's avatar
unknown committed
145 146
class Query_log_event;
class Load_log_event;
147
class Slave_log_event;
148
class sp_rcontext;
149
class sp_cache;
150
class Lex_input_stream;
151
class Parser_state;
152
class Rows_log_event;
unknown's avatar
unknown committed
153

154
enum enum_enable_or_disable { LEAVE_AS_IS, ENABLE, DISABLE };
155
enum enum_ha_read_modes { RFIRST, RNEXT, RPREV, RLAST, RKEY, RNEXT_SAME };
156
enum enum_duplicates { DUP_ERROR, DUP_REPLACE, DUP_UPDATE };
157 158
enum enum_delay_key_write { DELAY_KEY_WRITE_NONE, DELAY_KEY_WRITE_ON,
			    DELAY_KEY_WRITE_ALL };
159 160 161 162

#define SLAVE_EXEC_MODE_STRICT      (1U << 0)
#define SLAVE_EXEC_MODE_IDEMPOTENT  (1U << 1)

163 164
enum enum_mark_columns
{ MARK_COLUMNS_NONE, MARK_COLUMNS_READ, MARK_COLUMNS_WRITE};
165

unknown's avatar
unknown committed
166
extern char internal_table_name[2];
167
extern char empty_c_string[1];
168
extern MYSQL_PLUGIN_IMPORT const char **errmesg;
unknown's avatar
unknown committed
169

170 171
extern bool volatile shutdown_in_progress;

172 173 174 175 176 177 178
#define TC_LOG_PAGE_SIZE   8192
#define TC_LOG_MIN_SIZE    (3*TC_LOG_PAGE_SIZE)

#define TC_HEURISTIC_RECOVER_COMMIT   1
#define TC_HEURISTIC_RECOVER_ROLLBACK 2
extern uint tc_heuristic_recover;

unknown's avatar
unknown committed
179 180 181 182 183 184 185 186 187
typedef struct st_user_var_events
{
  user_var_entry *user_var_event;
  char *value;
  ulong length;
  Item_result type;
  uint charset_number;
} BINLOG_USER_VAR_EVENT;

188 189 190
#define RP_LOCK_LOG_IS_ALREADY_LOCKED 1
#define RP_FORCE_ROTATE               2

191 192 193 194 195 196 197 198 199 200 201 202
/*
  The COPY_INFO structure is used by INSERT/REPLACE code.
  The schema of the row counting by the INSERT/INSERT ... ON DUPLICATE KEY
  UPDATE code:
    If a row is inserted then the copied variable is incremented.
    If a row is updated by the INSERT ... ON DUPLICATE KEY UPDATE and the
      new data differs from the old one then the copied and the updated
      variables are incremented.
    The touched variable is incremented if a row was touched by the update part
      of the INSERT ... ON DUPLICATE KEY UPDATE no matter whether the row
      was actually changed or not.
*/
unknown's avatar
unknown committed
203
typedef struct st_copy_info {
unknown's avatar
unknown committed
204 205 206 207
  ha_rows records; /**< Number of processed records */
  ha_rows deleted; /**< Number of deleted records */
  ha_rows updated; /**< Number of updated records */
  ha_rows copied;  /**< Number of copied records */
208
  ha_rows error_count;
209
  ha_rows touched; /* Number of touched records */
unknown's avatar
unknown committed
210
  enum enum_duplicates handle_duplicates;
211
  int escape_char, last_errno;
212 213
  bool ignore;
  /* for INSERT ... UPDATE */
214 215
  List<Item> *update_fields;
  List<Item> *update_values;
unknown's avatar
unknown committed
216
  /* for VIEW ... WITH CHECK OPTION */
unknown's avatar
unknown committed
217
  TABLE_LIST *view;
unknown's avatar
unknown committed
218 219 220
} COPY_INFO;


unknown's avatar
unknown committed
221
class Key_part_spec :public Sql_alloc {
unknown's avatar
unknown committed
222 223 224
public:
  const char *field_name;
  uint length;
unknown's avatar
unknown committed
225 226
  Key_part_spec(const char *name,uint len=0) :field_name(name), length(len) {}
  bool operator==(const Key_part_spec& other) const;
227
  /**
unknown's avatar
unknown committed
228
    Construct a copy of this Key_part_spec. field_name is copied
229 230 231 232 233 234 235
    by-pointer as it is known to never change. At the same time
    'length' may be reset in mysql_prepare_create_table, and this
    is why we supply it with a copy.

    @return If out of memory, 0 is returned and an error is set in
    THD.
  */
unknown's avatar
unknown committed
236 237
  Key_part_spec *clone(MEM_ROOT *mem_root) const
  { return new (mem_root) Key_part_spec(*this); }
unknown's avatar
unknown committed
238 239 240 241 242 243 244 245 246 247
};


class Alter_drop :public Sql_alloc {
public:
  enum drop_type {KEY, COLUMN };
  const char *name;
  enum drop_type type;
  Alter_drop(enum drop_type par_type,const char *par_name)
    :name(par_name), type(par_type) {}
248 249
  /**
    Used to make a clone of this object for ALTER/CREATE TABLE
unknown's avatar
unknown committed
250
    @sa comment for Key_part_spec::clone
251 252 253
  */
  Alter_drop *clone(MEM_ROOT *mem_root) const
    { return new (mem_root) Alter_drop(*this); }
unknown's avatar
unknown committed
254 255 256 257 258 259 260 261 262
};


class Alter_column :public Sql_alloc {
public:
  const char *name;
  Item *def;
  Alter_column(const char *par_name,Item *literal)
    :name(par_name), def(literal) {}
263 264
  /**
    Used to make a clone of this object for ALTER/CREATE TABLE
unknown's avatar
unknown committed
265
    @sa comment for Key_part_spec::clone
266 267 268
  */
  Alter_column *clone(MEM_ROOT *mem_root) const
    { return new (mem_root) Alter_column(*this); }
unknown's avatar
unknown committed
269 270 271 272 273
};


class Key :public Sql_alloc {
public:
274
  enum Keytype { PRIMARY, UNIQUE, MULTIPLE, FULLTEXT, SPATIAL, FOREIGN_KEY};
unknown's avatar
unknown committed
275
  enum Keytype type;
unknown's avatar
unknown committed
276
  KEY_CREATE_INFO key_create_info;
unknown's avatar
unknown committed
277
  List<Key_part_spec> columns;
278
  const char *name;
279
  engine_option_value *option_list;
280
  bool generated;
unknown's avatar
unknown committed
281

282 283
  Key(enum Keytype type_par, const char *name_arg,
      KEY_CREATE_INFO *key_info_arg,
284 285
      bool generated_arg, List<Key_part_spec> &cols,
      engine_option_value *create_opt)
unknown's avatar
unknown committed
286
    :type(type_par), key_create_info(*key_info_arg), columns(cols),
287
    name(name_arg), option_list(create_opt), generated(generated_arg)
288
  {}
289 290
  Key(const Key &rhs, MEM_ROOT *mem_root);
  virtual ~Key() {}
291
  /* Equality comparison of keys (ignoring name) */
292
  friend bool foreign_key_prefix(Key *a, Key *b);
293 294
  /**
    Used to make a clone of this object for ALTER/CREATE TABLE
unknown's avatar
unknown committed
295
    @sa comment for Key_part_spec::clone
296 297 298
  */
  virtual Key *clone(MEM_ROOT *mem_root) const
    { return new (mem_root) Key(*this, mem_root); }
unknown's avatar
unknown committed
299 300
};

301 302
class Table_ident;

unknown's avatar
unknown committed
303
class Foreign_key: public Key {
304 305 306 307 308 309 310
public:
  enum fk_match_opt { FK_MATCH_UNDEF, FK_MATCH_FULL,
		      FK_MATCH_PARTIAL, FK_MATCH_SIMPLE};
  enum fk_option { FK_OPTION_UNDEF, FK_OPTION_RESTRICT, FK_OPTION_CASCADE,
		   FK_OPTION_SET_NULL, FK_OPTION_NO_ACTION, FK_OPTION_DEFAULT};

  Table_ident *ref_table;
unknown's avatar
unknown committed
311
  List<Key_part_spec> ref_columns;
312
  uint delete_opt, update_opt, match_opt;
unknown's avatar
unknown committed
313 314
  Foreign_key(const char *name_arg, List<Key_part_spec> &cols,
	      Table_ident *table,   List<Key_part_spec> &ref_cols,
315
	      uint delete_opt_arg, uint update_opt_arg, uint match_opt_arg)
316
    :Key(FOREIGN_KEY, name_arg, &default_key_create_info, 0, cols, NULL),
317
    ref_table(table), ref_columns(ref_cols),
318 319 320
    delete_opt(delete_opt_arg), update_opt(update_opt_arg),
    match_opt(match_opt_arg)
  {}
unknown's avatar
unknown committed
321
  Foreign_key(const Foreign_key &rhs, MEM_ROOT *mem_root);
322 323
  /**
    Used to make a clone of this object for ALTER/CREATE TABLE
unknown's avatar
unknown committed
324
    @sa comment for Key_part_spec::clone
325 326
  */
  virtual Key *clone(MEM_ROOT *mem_root) const
unknown's avatar
unknown committed
327
  { return new (mem_root) Foreign_key(*this, mem_root); }
328 329
  /* Used to validate foreign key options */
  bool validate(List<Create_field> &table_fields);
330
};
unknown's avatar
unknown committed
331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349

typedef struct st_mysql_lock
{
  TABLE **table;
  uint table_count,lock_count;
  THR_LOCK_DATA **locks;
} MYSQL_LOCK;


class LEX_COLUMN : public Sql_alloc
{
public:
  String column;
  uint rights;
  LEX_COLUMN (const String& x,const  uint& y ): column (x),rights (y) {}
};

#include "sql_lex.h"				/* Must be here */

350
class Delayed_insert;
unknown's avatar
unknown committed
351
class select_result;
352
class Time_zone;
unknown's avatar
unknown committed
353

354 355 356 357 358
#define THD_SENTRY_MAGIC 0xfeedd1ff
#define THD_SENTRY_GONE  0xdeadbeef

#define THD_CHECK_SENTRY(thd) DBUG_ASSERT(thd->dbug_sentry == THD_SENTRY_MAGIC)

359 360
struct system_variables
{
unknown's avatar
unknown committed
361 362
  /*
    How dynamically allocated system variables are handled:
363

unknown's avatar
unknown committed
364 365 366 367 368
    The global_system_variables and max_system_variables are "authoritative"
    They both should have the same 'version' and 'size'.
    When attempting to access a dynamic variable, if the session version
    is out of date, then the session version is updated and realloced if
    neccessary and bytes copied from global to make up for missing data.
369 370 371

    Note that one should use my_bool instead of bool here, as the variables
    are used with my_getopt.c
372
  */
unknown's avatar
unknown committed
373 374 375 376
  ulong dynamic_variables_version;
  char* dynamic_variables_ptr;
  uint dynamic_variables_head;  /* largest valid variable offset */
  uint dynamic_variables_size;  /* how many bytes are in use */
377

unknown's avatar
unknown committed
378 379
  ulonglong myisam_max_extra_sort_file_size;
  ulonglong myisam_max_sort_file_size;
380 381
  ulonglong max_heap_table_size;
  ulonglong tmp_table_size;
382
  ulonglong long_query_time;
383
  ulonglong join_buff_space_limit;
384 385
  ha_rows select_limit;
  ha_rows max_join_size;
386
  ulong auto_increment_increment, auto_increment_offset;
unknown's avatar
unknown committed
387
  ulong bulk_insert_buff_size;
388
  ulong join_buff_size;
389
  ulong join_cache_level;
unknown's avatar
unknown committed
390
  ulong max_allowed_packet;
391
  ulong max_error_count;
unknown's avatar
unknown committed
392
  ulong max_length_for_sort_data;
393
  ulong max_sort_length;
394
  ulong max_tmp_tables;
395
  ulong max_insert_delayed_threads;
396
  ulong min_examined_row_limit;
397
  ulong myisam_repair_threads;
unknown's avatar
unknown committed
398
  ulong myisam_sort_buff_size;
399
  ulong myisam_stats_method;
unknown's avatar
unknown committed
400
  ulong net_buffer_length;
401
  ulong net_interactive_timeout;
unknown's avatar
unknown committed
402
  ulong net_read_timeout;
403
  ulong net_retry_count;
404
  ulong net_wait_timeout;
unknown's avatar
unknown committed
405
  ulong net_write_timeout;
406 407
  ulong optimizer_prune_level;
  ulong optimizer_search_depth;
408 409
  /* A bitmap for switching optimizations on/off */
  ulong optimizer_switch;
410 411 412 413 414 415 416 417
  /*
    Controls use of Engine-MRR:
      0 - auto, based on cost
      1 - force MRR when the storage engine is capable of doing it
      2 - disable MRR.
  */
  ulong optimizer_use_mrr; 

unknown's avatar
unknown committed
418
  ulong preload_buff_size;
419
  ulong profiling_history_size;
unknown's avatar
unknown committed
420 421 422
  ulong query_cache_type;
  ulong read_buff_size;
  ulong read_rnd_buff_size;
Sergey Petrunya's avatar
Sergey Petrunya committed
423
  ulong mrr_buff_size;
unknown's avatar
unknown committed
424
  ulong div_precincrement;
425
  ulong sortbuff_size;
426 427
  /* Total size of all buffers used by the subselect_rowid_merge_engine. */
  ulong rowid_merge_buff_size;
unknown's avatar
unknown committed
428
  ulong thread_handling;
unknown's avatar
unknown committed
429
  ulong tx_isolation;
unknown's avatar
Merge  
unknown committed
430
  ulong completion_type;
431
  /* Determines which non-standard SQL behaviour should be enabled */
432
  ulong sql_mode;
433
  ulong max_sp_recursion_depth;
unknown's avatar
VIEW  
unknown committed
434
  /* check of key presence in updatable view */
435
  ulong updatable_views_with_limit;
unknown's avatar
unknown committed
436
  ulong default_week_format;
437
  ulong max_seeks_for_key;
438 439 440 441 442
  ulong range_alloc_block_size;
  ulong query_alloc_block_size;
  ulong query_prealloc_size;
  ulong trans_alloc_block_size;
  ulong trans_prealloc_size;
443
  ulong log_warnings;
444
  ulong group_concat_max_len;
445 446 447 448
  /* Flags for slow log filtering */
  ulong log_slow_rate_limit; 
  ulong log_slow_filter; 
  ulong log_slow_verbosity; 
unknown's avatar
unknown committed
449 450 451 452
  ulong ndb_autoincrement_prefetch_sz;
  ulong ndb_index_stat_cache_entries;
  ulong ndb_index_stat_update_freq;
  ulong binlog_format; // binlog format for this thd (see enum_binlog_format)
453
  my_bool binlog_direct_non_trans_update;
unknown's avatar
unknown committed
454 455 456 457
  /*
    In slave thread we need to know in behalf of which
    thread the query is being run to replicate temp tables properly
  */
unknown's avatar
unknown committed
458
  my_thread_id pseudo_thread_id;
unknown's avatar
unknown committed
459

unknown's avatar
unknown committed
460 461
  my_bool low_priority_updates;
  my_bool new_mode;
462
  /*
463
    compatibility option:
464
      - index usage hints (USE INDEX without a FOR clause) behave as in 5.0
465 466
  */
  my_bool old_mode;
467
  my_bool query_cache_wlock_invalidate;
unknown's avatar
unknown committed
468
  my_bool engine_condition_pushdown;
unknown's avatar
unknown committed
469
  my_bool keep_files_on_create;
470
  my_bool ndb_force_send;
471
  my_bool ndb_use_copying_alter_table;
472 473
  my_bool ndb_use_exact_count;
  my_bool ndb_use_transactions;
474
  my_bool ndb_index_stat_enable;
475

unknown's avatar
unknown committed
476
  my_bool old_alter_table;
477
  my_bool old_passwords;
478

unknown's avatar
unknown committed
479
  plugin_ref table_plugin;
unknown's avatar
unknown committed
480

481
  /* Only charset part of these variables is sensible */
unknown's avatar
unknown committed
482
  CHARSET_INFO  *character_set_filesystem;
483
  CHARSET_INFO  *character_set_client;
484
  CHARSET_INFO  *character_set_results;
485

486 487 488
  /* Both charset and collation parts of these variables are important */
  CHARSET_INFO	*collation_server;
  CHARSET_INFO	*collation_database;
unknown's avatar
unknown committed
489
  CHARSET_INFO  *collation_connection;
490

unknown's avatar
unknown committed
491 492 493
  /* Locale Support */
  MY_LOCALE *lc_time_names;

494 495
  Time_zone *time_zone;

496
  /* DATE, DATETIME and MYSQL_TIME formats */
497 498 499
  DATE_TIME_FORMAT *date_format;
  DATE_TIME_FORMAT *datetime_format;
  DATE_TIME_FORMAT *time_format;
500
  my_bool sysdate_is_now;
501

502 503 504
  /* deadlock detection */
  ulong wt_timeout_short, wt_deadlock_search_depth_short;
  ulong wt_timeout_long, wt_deadlock_search_depth_long;
unknown's avatar
unknown committed
505 506
};

507

508 509 510 511 512
/**
  Per thread status variables.
  Must be long/ulong up to last_system_status_var so that
  add_to_status/add_diff_to_status can work.
*/
513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528

typedef struct system_status_var
{
  ulong com_other;
  ulong com_stat[(uint) SQLCOM_END];
  ulong created_tmp_disk_tables;
  ulong created_tmp_tables;
  ulong ha_commit_count;
  ulong ha_delete_count;
  ulong ha_read_first_count;
  ulong ha_read_last_count;
  ulong ha_read_key_count;
  ulong ha_read_next_count;
  ulong ha_read_prev_count;
  ulong ha_read_rnd_count;
  ulong ha_read_rnd_next_count;
529 530 531 532 533 534 535
  /*
    This number doesn't include calls to the default implementation and
    calls made by range access. The intent is to count only calls made by
    BatchedKeyAccess.
  */
  ulong ha_multi_range_read_init_count;

536 537 538
  ulong ha_rollback_count;
  ulong ha_update_count;
  ulong ha_write_count;
539 540 541 542
  ulong ha_prepare_count;
  ulong ha_discover_count;
  ulong ha_savepoint_count;
  ulong ha_savepoint_rollback_count;
543 544 545 546 547 548 549 550 551 552 553 554

  /* KEY_CACHE parts. These are copies of the original */
  ulong key_blocks_changed;
  ulong key_blocks_used;
  ulong key_cache_r_requests;
  ulong key_cache_read;
  ulong key_cache_w_requests;
  ulong key_cache_write;
  /* END OF KEY_CACHE parts */

  ulong net_big_packet_count;
  ulong opened_tables;
unknown's avatar
unknown committed
555
  ulong opened_shares;
556 557 558 559 560
  ulong select_full_join_count;
  ulong select_full_range_join_count;
  ulong select_range_count;
  ulong select_range_check_count;
  ulong select_scan_count;
561 562
  ulong rows_read;
  ulong rows_sent;
563 564 565 566 567
  ulong long_query_count;
  ulong filesort_merge_passes;
  ulong filesort_range_count;
  ulong filesort_rows;
  ulong filesort_scan_count;
568
  /* Prepared statements and binary protocol */
unknown's avatar
unknown committed
569
  ulong com_stmt_prepare;
unknown's avatar
unknown committed
570
  ulong com_stmt_reprepare;
unknown's avatar
unknown committed
571 572 573 574 575
  ulong com_stmt_execute;
  ulong com_stmt_send_long_data;
  ulong com_stmt_fetch;
  ulong com_stmt_reset;
  ulong com_stmt_close;
576
  /*
577 578 579 580 581 582
    Number of statements sent from the client
  */
  ulong questions;
  /*
    IMPORTANT!
    SEE last_system_status_var DEFINITION BELOW.
583 584
    Below 'last_system_status_var' are all variables that cannot be handled
    automatically by add_to_status()/add_diff_to_status().
585
  */
Sergei Golubchik's avatar
Sergei Golubchik committed
586 587 588
  ulong empty_queries;
  ulong access_denied_errors;                   /* Can only be 0 or 1 */
  ulong lost_connections;
589 590 591
  ulonglong bytes_received;
  ulonglong bytes_sent;
  ulonglong binlog_bytes_written;
592
  double last_query_cost;
593
  double cpu_time, busy_time;
594 595 596
} STATUS_VAR;

/*
597
  This is used for 'SHOW STATUS'. It must be updated to the last ulong
598
  variable in system_status_var which is makes sense to add to the global
599
  counter
600 601
*/

602
#define last_system_status_var questions
603

unknown's avatar
unknown committed
604 605
void mark_transaction_to_rollback(THD *thd, bool all);

606 607
#ifdef MYSQL_SERVER

608
void free_tmp_table(THD *thd, TABLE *entry);
609 610


unknown's avatar
unknown committed
611 612
/* The following macro is to make init of Query_arena simpler */
#ifndef DBUG_OFF
unknown's avatar
unknown committed
613
#define INIT_ARENA_DBUG_INFO is_backup_arena= 0; is_reprepared= FALSE;
614 615
#else
#define INIT_ARENA_DBUG_INFO
unknown's avatar
unknown committed
616 617
#endif

unknown's avatar
unknown committed
618
class Query_arena
619 620 621 622 623 624 625
{
public:
  /*
    List of items created in the parser for this query. Every item puts
    itself to the list on creation (see Item::Item() for details))
  */
  Item *free_list;
unknown's avatar
unknown committed
626
  MEM_ROOT *mem_root;                   // Pointer to current memroot
unknown's avatar
unknown committed
627
#ifndef DBUG_OFF
628
  bool is_backup_arena; /* True if this arena is used for backup. */
unknown's avatar
unknown committed
629
  bool is_reprepared;
unknown's avatar
unknown committed
630
#endif
631 632 633 634 635 636 637
  /*
    The states relfects three diffrent life cycles for three
    different types of statements:
    Prepared statement: INITIALIZED -> PREPARED -> EXECUTED.
    Stored procedure:   INITIALIZED_FOR_SP -> EXECUTED.
    Other statements:   CONVENTIONAL_EXECUTION never changes.
  */
unknown's avatar
unknown committed
638
  enum enum_state
639
  {
640 641
    INITIALIZED= 0, INITIALIZED_FOR_SP= 1, PREPARED= 2,
    CONVENTIONAL_EXECUTION= 3, EXECUTED= 4, ERROR= -1
642
  };
unknown's avatar
unknown committed
643

unknown's avatar
unknown committed
644
  enum_state state;
645 646 647 648 649 650 651

  /* We build without RTTI, so dynamic_cast can't be used. */
  enum Type
  {
    STATEMENT, PREPARED_STATEMENT, STORED_PROCEDURE
  };

652 653
  Query_arena(MEM_ROOT *mem_root_arg, enum enum_state state_arg) :
    free_list(0), mem_root(mem_root_arg), state(state_arg)
654
  { INIT_ARENA_DBUG_INFO; }
655
  /*
unknown's avatar
unknown committed
656 657
    This constructor is used only when Query_arena is created as
    backup storage for another instance of Query_arena.
658
  */
659 660
  Query_arena() { INIT_ARENA_DBUG_INFO; }

661
  virtual Type type() const;
unknown's avatar
unknown committed
662
  virtual ~Query_arena() {};
663

664
  inline bool is_stmt_prepare() const { return state == INITIALIZED; }
665 666
  inline bool is_first_sp_execute() const
  { return state == INITIALIZED_FOR_SP; }
667 668
  inline bool is_stmt_prepare_or_first_sp_execute() const
  { return (int)state < (int)PREPARED; }
669 670
  inline bool is_stmt_prepare_or_first_stmt_execute() const
  { return (int)state <= (int)PREPARED; }
unknown's avatar
unknown committed
671
  inline bool is_first_stmt_execute() const { return state == PREPARED; }
672 673
  inline bool is_stmt_execute() const
  { return state == PREPARED || state == EXECUTED; }
unknown's avatar
unknown committed
674
  inline bool is_conventional() const
unknown's avatar
unknown committed
675
  { return state == CONVENTIONAL_EXECUTION; }
676

677 678
  inline void* alloc(size_t size) { return alloc_root(mem_root,size); }
  inline void* calloc(size_t size)
679
  {
680
    void *ptr;
unknown's avatar
unknown committed
681
    if ((ptr=alloc_root(mem_root,size)))
682
      bzero(ptr, size);
683 684 685
    return ptr;
  }
  inline char *strdup(const char *str)
unknown's avatar
unknown committed
686
  { return strdup_root(mem_root,str); }
687
  inline char *strmake(const char *str, size_t size)
unknown's avatar
unknown committed
688
  { return strmake_root(mem_root,str,size); }
689
  inline void *memdup(const void *str, size_t size)
unknown's avatar
unknown committed
690
  { return memdup_root(mem_root,str,size); }
691
  inline void *memdup_w_gap(const void *str, size_t size, uint gap)
692
  {
693 694
    void *ptr;
    if ((ptr= alloc_root(mem_root,size+gap)))
695 696 697 698
      memcpy(ptr,str,size);
    return ptr;
  }

unknown's avatar
unknown committed
699
  void set_query_arena(Query_arena *set);
700 701

  void free_items();
702 703
  /* Close the active state associated with execution of this statement */
  virtual void cleanup_stmt();
704 705
};

706

707
class Server_side_cursor;
708

709 710 711 712
/**
  @class Statement
  @brief State of a single command executed against this connection.

713 714 715 716 717
  One connection can contain a lot of simultaneously running statements,
  some of which could be:
   - prepared, that is, contain placeholders,
   - opened as cursors. We maintain 1 to 1 relationship between
     statement and cursor - if user wants to create another cursor for his
718
     query, we create another statement for it.
719 720 721 722 723 724
  To perform some action with statement we reset THD part to the state  of
  that statement, do the action, and then save back modified state from THD
  to the statement. It will be changed in near future, and Statement will
  be used explicitly.
*/

725
class Statement: public ilink, public Query_arena
726
{
727 728
  Statement(const Statement &rhs);              /* not implemented: */
  Statement &operator=(const Statement &rhs);   /* non-copyable */
729 730
public:
  /*
unknown's avatar
unknown committed
731
    Uniquely identifies each statement object in thread scope; change during
732
    statement lifetime. FIXME: must be const
733
  */
unknown's avatar
unknown committed
734
   ulong id;
735 736

  /*
737 738 739 740 741 742 743 744 745
    MARK_COLUMNS_NONE:  Means mark_used_colums is not set and no indicator to
                        handler of fields used is set
    MARK_COLUMNS_READ:  Means a bit in read set is set to inform handler
	                that the field is to be read. If field list contains
                        duplicates, then thd->dup_field is set to point
                        to the last found duplicate.
    MARK_COLUMNS_WRITE: Means a bit is set in write set to inform handler
			that it needs to update this field in write_row
                        and update_row.
746
  */
747
  enum enum_mark_columns mark_used_columns;
748

749
  LEX_STRING name; /* name for named prepared statements */
750 751 752 753 754
  LEX *lex;                                     // parse tree descriptor
  /*
    Points to the query associated with this statement. It's const, but
    we need to declare it char * because all table handlers are written
    in C and need to point to it.
755

756 757 758 759
    Note that if we set query = NULL, we must at the same time set
    query_length = 0, and protect the whole operation with
    LOCK_thd_data mutex. To avoid crashes in races, if we do not
    know that thd->query cannot change at the moment, we should print
760
    thd->query like this:
761 762 763 764 765
      (1) reserve the LOCK_thd_data mutex;
      (2) print or copy the value of query and query_length
      (3) release LOCK_thd_data mutex.
    This printing is needed at least in SHOW PROCESSLIST and SHOW
    ENGINE INNODB STATUS.
766
  */
767
  LEX_STRING query_string;
768
  Server_side_cursor *cursor;
769

770 771 772 773
  inline char *query() { return query_string.str; }
  inline uint32 query_length() { return query_string.length; }
  void set_query_inner(char *query_arg, uint32 query_length_arg);

774 775 776 777 778 779 780 781 782 783 784 785 786 787
  /**
    Name of the current (default) database.

    If there is the current (default) database, "db" contains its name. If
    there is no current (default) database, "db" is NULL and "db_length" is
    0. In other words, "db", "db_length" must either be NULL, or contain a
    valid database name.

    @note this attribute is set and alloced by the slave SQL thread (for
    the THD of that thread); that thread is (and must remain, for now) the
    only responsible for freeing this member.
  */

  char *db;
788
  size_t db_length;
789

790 791
public:

unknown's avatar
unknown committed
792
  /* This constructor is called for backup statements */
793
  Statement() {}
794

795 796
  Statement(LEX *lex_arg, MEM_ROOT *mem_root_arg,
            enum enum_state state_arg, ulong id_arg);
797
  virtual ~Statement();
798 799

  /* Assign execution context (note: not all members) of given stmt to self */
800
  virtual void set_statement(Statement *stmt);
801 802
  void set_n_backup_statement(Statement *stmt, Statement *backup);
  void restore_backup_statement(Statement *stmt, Statement *backup);
803 804
  /* return class type */
  virtual Type type() const;
805 806 807
};


808
/**
809 810 811 812 813
  Container for all statements created/used in a connection.
  Statements in Statement_map have unique Statement::id (guaranteed by id
  assignment in Statement::Statement)
  Non-empty statement names are unique too: attempt to insert a new statement
  with duplicate name causes older statement to be deleted
814

815 816
  Statements are auto-deleted when they are removed from the map and when the
  map is deleted.
817 818 819 820 821 822
*/

class Statement_map
{
public:
  Statement_map();
823

824
  int insert(THD *thd, Statement *statement);
825 826

  Statement *find_by_name(LEX_STRING *name)
827
  {
828
    Statement *stmt;
829
    stmt= (Statement*)hash_search(&names_hash, (uchar*)name->str,
830 831
                                  name->length);
    return stmt;
832
  }
833 834

  Statement *find(ulong id)
835
  {
836
    if (last_found_statement == 0 || id != last_found_statement->id)
837 838
    {
      Statement *stmt;
839
      stmt= (Statement *) hash_search(&st_hash, (uchar *) &id, sizeof(id));
840
      if (stmt && stmt->name.str)
841 842 843
        return NULL;
      last_found_statement= stmt;
    }
844
    return last_found_statement;
845
  }
846 847 848 849 850 851
  /*
    Close all cursors of this connection that use tables of a storage
    engine that has transaction-specific state and therefore can not
    survive COMMIT or ROLLBACK. Currently all but MyISAM cursors are closed.
  */
  void close_transient_cursors();
852
  void erase(Statement *statement);
853
  /* Erase all statements (calls Statement destructor) */
854 855
  void reset();
  ~Statement_map();
856 857
private:
  HASH st_hash;
858
  HASH names_hash;
859
  I_List<Statement> transient_cursor_list;
860
  Statement *last_found_statement;
861 862
};

863 864 865
struct st_savepoint {
  struct st_savepoint *prev;
  char                *name;
866 867
  uint                 length;
  Ha_trx_info         *ha_list;
868 869
};

870
enum xa_states {XA_NOTR=0, XA_ACTIVE, XA_IDLE, XA_PREPARED, XA_ROLLBACK_ONLY};
unknown's avatar
unknown committed
871
extern const char *xa_state_names[];
872

873 874 875 876 877
typedef struct st_xid_state {
  /* For now, this is only used to catch duplicated external xids */
  XID  xid;                           // transaction identifier
  enum xa_states xa_state;            // used by external XA only
  bool in_thd;
878 879
  /* Error reported by the Resource Manager (RM) to the Transaction Manager. */
  uint rm_error;
880 881 882 883 884 885 886 887 888 889 890
} XID_STATE;

extern pthread_mutex_t LOCK_xid_cache;
extern HASH xid_cache;
bool xid_cache_init(void);
void xid_cache_free(void);
XID_STATE *xid_cache_search(XID *xid);
bool xid_cache_insert(XID *xid, enum xa_states xa_state);
bool xid_cache_insert(XID_STATE *xid_state);
void xid_cache_delete(XID_STATE *xid_state);

891 892 893 894
/**
  @class Security_context
  @brief A set of THD members describing the current authenticated user.
*/
895

896 897
class Security_context {
public:
898
  Security_context() {}                       /* Remove gcc warning */
899 900 901 902
  /*
    host - host of the client
    user - user of the client, set to NULL until the user has been read from
    the connection
903
    priv_user - The user privilege we are using. May be "" for anonymous user.
904 905
    ip - client IP
  */
906 907
  char   *host, *user, *ip;
  char   priv_user[USERNAME_LENGTH];
908
  /* The host privilege we are using */
909 910 911 912 913 914 915 916 917
  char   priv_host[MAX_HOSTNAME];
  /* points to host if host is available, otherwise points to ip */
  const char *host_or_ip;
  ulong master_access;                 /* Global privileges from mysql.user */
  ulong db_access;                     /* Privileges for current db */

  void init();
  void destroy();
  void skip_grants();
918
  inline char *priv_host_name()
919 920 921
  {
    return (*priv_host ? priv_host : (char *)"%");
  }
922

923
  bool set_user(char *user_arg);
924 925 926 927 928 929 930 931 932 933 934 935

#ifndef NO_EMBEDDED_ACCESS_CHECKS
  bool
  change_security_context(THD *thd,
                          LEX_STRING *definer_user,
                          LEX_STRING *definer_host,
                          LEX_STRING *db,
                          Security_context **backup);

  void
  restore_security_context(THD *thd, Security_context *backup);
#endif
936
  bool user_matches(Security_context *);
937 938 939
};


940
/**
941 942 943 944 945 946 947 948 949 950
  A registry for item tree transformations performed during
  query optimization. We register only those changes which require
  a rollback to re-execute a prepared statement or stored procedure
  yet another time.
*/

struct Item_change_record;
typedef I_List<Item_change_record> Item_change_list;


951
/**
952 953 954 955 956 957 958 959
  Type of prelocked mode.
  See comment for THD::prelocked_mode for complete description.
*/

enum prelocked_mode_type {NON_PRELOCKED= 0, PRELOCKED= 1,
                          PRELOCKED_UNDER_LOCK_TABLES= 2};


960
/**
961
  Class that holds information about tables which were opened and locked
962 963 964 965 966 967 968
  by the thread. It is also used to save/restore this information in
  push_open_tables_state()/pop_open_tables_state().
*/

class Open_tables_state
{
public:
unknown's avatar
unknown committed
969 970 971 972 973 974 975 976 977 978
  /**
    As part of class THD, this member is set during execution
    of a prepared statement. When it is set, it is used
    by the locking subsystem to report a change in table metadata.

    When Open_tables_state part of THD is reset to open
    a system or INFORMATION_SCHEMA table, the member is cleared
    to avoid spurious ER_NEED_REPREPARE errors -- system and
    INFORMATION_SCHEMA tables are not subject to metadata version
    tracking.
979
    @sa check_and_update_table_version()
unknown's avatar
unknown committed
980
  */
981
  Reprepare_observer *m_reprepare_observer;
unknown's avatar
unknown committed
982

983 984 985 986 987 988 989 990 991 992 993
  /**
    List of regular tables in use by this thread. Contains temporary and
    base tables that were opened with @see open_tables().
  */
  TABLE *open_tables;
  /**
    List of temporary tables used by this thread. Contains user-level
    temporary tables, created with CREATE TEMPORARY TABLE, and
    internal temporary tables, created, e.g., to resolve a SELECT,
    or for an intermediate table used in ALTER.
    XXX Why are internal temporary tables added to this list?
994
  */
995 996 997 998
  TABLE *temporary_tables;
  /**
    List of tables that were opened with HANDLER OPEN and are
    still in use by this thread.
999
  */
1000 1001
  TABLE *handler_tables;
  TABLE *derived_tables;
1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022
  /*
    During a MySQL session, one can lock tables in two modes: automatic
    or manual. In automatic mode all necessary tables are locked just before
    statement execution, and all acquired locks are stored in 'lock'
    member. Unlocking takes place automatically as well, when the
    statement ends.
    Manual mode comes into play when a user issues a 'LOCK TABLES'
    statement. In this mode the user can only use the locked tables.
    Trying to use any other tables will give an error. The locked tables are
    stored in 'locked_tables' member.  Manual locking is described in
    the 'LOCK_TABLES' chapter of the MySQL manual.
    See also lock_tables() for details.
  */
  MYSQL_LOCK *lock;
  /*
    Tables that were locked with explicit or implicit LOCK TABLES.
    (Implicit LOCK TABLES happens when we are prelocking tables for
     execution of statement which uses stored routines. See description
     THD::prelocked_mode for more info.)
  */
  MYSQL_LOCK *locked_tables;
1023 1024 1025 1026 1027 1028 1029 1030

  /*
    CREATE-SELECT keeps an extra lock for the table being
    created. This field is used to keep the extra lock available for
    lower level routines, which would otherwise miss that lock.
   */
  MYSQL_LOCK *extra_lock;

1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057
  /*
    prelocked_mode_type enum and prelocked_mode member are used for
    indicating whenever "prelocked mode" is on, and what type of
    "prelocked mode" is it.

    Prelocked mode is used for execution of queries which explicitly
    or implicitly (via views or triggers) use functions, thus may need
    some additional tables (mentioned in query table list) for their
    execution.

    First open_tables() call for such query will analyse all functions
    used by it and add all additional tables to table its list. It will
    also mark this query as requiring prelocking. After that lock_tables()
    will issue implicit LOCK TABLES for the whole table list and change
    thd::prelocked_mode to non-0. All queries called in functions invoked
    by the main query will use prelocked tables. Non-0 prelocked_mode
    will also surpress mentioned analysys in those queries thus saving
    cycles. Prelocked mode will be turned off once close_thread_tables()
    for the main query will be called.

    Note: Since not all "tables" present in table list are really locked
    thd::prelocked_mode does not imply thd::locked_tables.
  */
  prelocked_mode_type prelocked_mode;
  ulong	version;
  uint current_tablenr;

1058 1059 1060 1061 1062 1063 1064 1065 1066
  enum enum_flags {
    BACKUPS_AVAIL = (1U << 0)     /* There are backups available */
  };

  /*
    Flags with information about the open tables state.
  */
  uint state_flags;

1067 1068 1069 1070
  /*
    This constructor serves for creation of Open_tables_state instances
    which are used as backup storage.
  */
1071
  Open_tables_state() : state_flags(0U) { }
1072 1073

  Open_tables_state(ulong version_arg);
1074 1075 1076 1077 1078 1079 1080 1081 1082

  void set_open_tables_state(Open_tables_state *state)
  {
    *this= *state;
  }

  void reset_open_tables_state()
  {
    open_tables= temporary_tables= handler_tables= derived_tables= 0;
1083
    extra_lock= lock= locked_tables= 0;
1084
    prelocked_mode= NON_PRELOCKED;
1085
    state_flags= 0U;
1086
    m_reprepare_observer= NULL;
1087 1088 1089
  }
};

1090 1091 1092 1093
/**
  @class Sub_statement_state
  @brief Used to save context when executing a function or trigger
*/
1094 1095 1096 1097 1098 1099

/* Defines used for Sub_statement_state::in_sub_stmt */

#define SUB_STMT_TRIGGER 1
#define SUB_STMT_FUNCTION 2

1100

1101 1102 1103 1104
class Sub_statement_state
{
public:
  ulonglong options;
1105 1106 1107
  ulonglong first_successful_insert_id_in_prev_stmt;
  ulonglong first_successful_insert_id_in_cur_stmt, insert_id_for_cur_row;
  Discrete_interval auto_inc_interval_for_cur_row;
1108
  Discrete_intervals_list auto_inc_intervals_forced;
1109 1110 1111
  ulonglong limit_found_rows;
  ha_rows    cuted_fields, sent_row_count, examined_row_count;
  ulong client_capabilities;
1112
  ulong query_plan_flags; 
1113
  uint in_sub_stmt;
1114
  bool enable_slow_log;
unknown's avatar
unknown committed
1115
  bool last_insert_id_used;
1116
  SAVEPOINT *savepoints;
1117
  enum enum_check_fields count_cuted_fields;
1118 1119 1120
};


1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132
/* Flags for the THD::system_thread variable */
enum enum_thread_type
{
  NON_SYSTEM_THREAD= 0,
  SYSTEM_THREAD_DELAYED_INSERT= 1,
  SYSTEM_THREAD_SLAVE_IO= 2,
  SYSTEM_THREAD_SLAVE_SQL= 4,
  SYSTEM_THREAD_NDBCLUSTER_BINLOG= 8,
  SYSTEM_THREAD_EVENT_SCHEDULER= 16,
  SYSTEM_THREAD_EVENT_WORKER= 32
};

1133 1134 1135 1136 1137
inline char const *
show_system_thread(enum_thread_type thread)
{
#define RETURN_NAME_AS_STRING(NAME) case (NAME): return #NAME
  switch (thread) {
1138
    static char buf[64];
1139 1140 1141 1142 1143 1144 1145
    RETURN_NAME_AS_STRING(NON_SYSTEM_THREAD);
    RETURN_NAME_AS_STRING(SYSTEM_THREAD_DELAYED_INSERT);
    RETURN_NAME_AS_STRING(SYSTEM_THREAD_SLAVE_IO);
    RETURN_NAME_AS_STRING(SYSTEM_THREAD_SLAVE_SQL);
    RETURN_NAME_AS_STRING(SYSTEM_THREAD_NDBCLUSTER_BINLOG);
    RETURN_NAME_AS_STRING(SYSTEM_THREAD_EVENT_SCHEDULER);
    RETURN_NAME_AS_STRING(SYSTEM_THREAD_EVENT_WORKER);
1146 1147 1148
  default:
    sprintf(buf, "<UNKNOWN SYSTEM THREAD: %d>", thread);
    return buf;
1149 1150 1151
  }
#undef RETURN_NAME_AS_STRING
}
1152

unknown's avatar
unknown committed
1153 1154 1155 1156 1157 1158 1159 1160
/**
  This class represents the interface for internal error handlers.
  Internal error handlers are exception handlers used by the server
  implementation.
*/
class Internal_error_handler
{
protected:
1161 1162 1163 1164
  Internal_error_handler() :
    m_prev_internal_handler(NULL)
  {}

unknown's avatar
unknown committed
1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193
  virtual ~Internal_error_handler() {}

public:
  /**
    Handle an error condition.
    This method can be implemented by a subclass to achieve any of the
    following:
    - mask an error internally, prevent exposing it to the user,
    - mask an error and throw another one instead.
    When this method returns true, the error condition is considered
    'handled', and will not be propagated to upper layers.
    It is the responsability of the code installing an internal handler
    to then check for trapped conditions, and implement logic to recover
    from the anticipated conditions trapped during runtime.

    This mechanism is similar to C++ try/throw/catch:
    - 'try' correspond to <code>THD::push_internal_handler()</code>,
    - 'throw' correspond to <code>my_error()</code>,
    which invokes <code>my_message_sql()</code>,
    - 'catch' correspond to checking how/if an internal handler was invoked,
    before removing it from the exception stack with
    <code>THD::pop_internal_handler()</code>.

    @param sql_errno the error number
    @param level the error level
    @param thd the calling thread
    @return true if the error is handled
  */
  virtual bool handle_error(uint sql_errno,
1194
                            const char *message,
unknown's avatar
unknown committed
1195 1196
                            MYSQL_ERROR::enum_warning_level level,
                            THD *thd) = 0;
1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218
private:
  Internal_error_handler *m_prev_internal_handler;
  friend class THD;
};


/**
  Implements the trivial error handler which cancels all error states
  and prevents an SQLSTATE to be set.
*/

class Dummy_error_handler : public Internal_error_handler
{
public:
  bool handle_error(uint sql_errno,
                    const char *message,
                    MYSQL_ERROR::enum_warning_level level,
                    THD *thd)
  {
    /* Ignore error */
    return TRUE;
  }
Michael Widenius's avatar
Michael Widenius committed
1219
  Dummy_error_handler() {}                    /* Remove gcc warning */
unknown's avatar
unknown committed
1220 1221 1222
};


1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247
/**
  This class is an internal error handler implementation for 
  DROP TABLE statements. The thing is that there may be warnings during
  execution of these statements, which should not be exposed to the user.
  This class is intended to silence such warnings.
*/

class Drop_table_error_handler : public Internal_error_handler
{
public:
  Drop_table_error_handler(Internal_error_handler *err_handler)
    :m_err_handler(err_handler)
  { }

public:
  bool handle_error(uint sql_errno,
                    const char *message,
                    MYSQL_ERROR::enum_warning_level level,
                    THD *thd);

private:
  Internal_error_handler *m_err_handler;
};


1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261
/**
  Stores status of the currently executed statement.
  Cleared at the beginning of the statement, and then
  can hold either OK, ERROR, or EOF status.
  Can not be assigned twice per statement.
*/

class Diagnostics_area
{
public:
  enum enum_diagnostics_status
  {
    /** The area is cleared at start of a statement. */
    DA_EMPTY= 0,
1262
    /** Set whenever one calls my_ok(). */
1263
    DA_OK,
1264
    /** Set whenever one calls my_eof(). */
1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276
    DA_EOF,
    /** Set whenever one calls my_error() or my_message(). */
    DA_ERROR,
    /** Set in case of a custom response, such as one from COM_STMT_PREPARE. */
    DA_DISABLED
  };
  /** True if status information is sent to the client. */
  bool is_sent;
  /** Set to make set_error_status after set_{ok,eof}_status possible. */
  bool can_overwrite_status;

  void set_ok_status(THD *thd, ha_rows affected_rows_arg,
1277
                     ulonglong last_insert_id_arg,
1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307
                     const char *message);
  void set_eof_status(THD *thd);
  void set_error_status(THD *thd, uint sql_errno_arg, const char *message_arg);

  void disable_status();

  void reset_diagnostics_area();

  bool is_set() const { return m_status != DA_EMPTY; }
  bool is_error() const { return m_status == DA_ERROR; }
  bool is_eof() const { return m_status == DA_EOF; }
  bool is_ok() const { return m_status == DA_OK; }
  bool is_disabled() const { return m_status == DA_DISABLED; }
  enum_diagnostics_status status() const { return m_status; }

  const char *message() const
  { DBUG_ASSERT(m_status == DA_ERROR || m_status == DA_OK); return m_message; }

  uint sql_errno() const
  { DBUG_ASSERT(m_status == DA_ERROR); return m_sql_errno; }

  uint server_status() const
  {
    DBUG_ASSERT(m_status == DA_OK || m_status == DA_EOF);
    return m_server_status;
  }

  ha_rows affected_rows() const
  { DBUG_ASSERT(m_status == DA_OK); return m_affected_rows; }

1308
  ulonglong last_insert_id() const
1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331
  { DBUG_ASSERT(m_status == DA_OK); return m_last_insert_id; }

  uint total_warn_count() const
  {
    DBUG_ASSERT(m_status == DA_OK || m_status == DA_EOF);
    return m_total_warn_count;
  }

  Diagnostics_area() { reset_diagnostics_area(); }

private:
  /** Message buffer. Can be used by OK or ERROR status. */
  char m_message[MYSQL_ERRMSG_SIZE];
  /**
    SQL error number. One of ER_ codes from share/errmsg.txt.
    Set by set_error_status.
  */
  uint m_sql_errno;

  /**
    Copied from thd->server_status when the diagnostics area is assigned.
    We need this member as some places in the code use the following pattern:
    thd->server_status|= ...
1332
    my_eof(thd);
1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353
    thd->server_status&= ~...
    Assigned by OK, EOF or ERROR.
  */
  uint m_server_status;
  /**
    The number of rows affected by the last statement. This is
    semantically close to thd->row_count_func, but has a different
    life cycle. thd->row_count_func stores the value returned by
    function ROW_COUNT() and is cleared only by statements that
    update its value, such as INSERT, UPDATE, DELETE and few others.
    This member is cleared at the beginning of the next statement.

    We could possibly merge the two, but life cycle of thd->row_count_func
    can not be changed.
  */
  ha_rows    m_affected_rows;
  /**
    Similarly to the previous member, this is a replacement of
    thd->first_successful_insert_id_in_prev_stmt, which is used
    to implement LAST_INSERT_ID().
  */
1354
  ulonglong   m_last_insert_id;
1355 1356 1357 1358 1359 1360 1361 1362 1363 1364
  /** The total number of warnings. */
  uint	     m_total_warn_count;
  enum_diagnostics_status m_status;
  /**
    @todo: the following THD members belong here:
    - warn_list, warn_count,
  */
};


1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386
/**
  Storage engine specific thread local data.
*/

struct Ha_data
{
  /**
    Storage engine specific thread local data.
    Lifetime: one user connection.
  */
  void *ha_ptr;
  /**
    0: Life time: one statement within a transaction. If @@autocommit is
    on, also represents the entire transaction.
    @sa trans_register_ha()

    1: Life time: one transaction within a connection.
    If the storage engine does not participate in a transaction,
    this should not be used.
    @sa trans_register_ha()
  */
  Ha_trx_info ha_info[2];
1387 1388 1389 1390 1391
  /**
    NULL: engine is not bound to this thread
    non-NULL: engine is bound to this thread, engine shutdown forbidden
  */
  plugin_ref lock;
1392 1393 1394 1395
  Ha_data() :ha_ptr(NULL) {}
};


1396 1397
/**
  @class THD
unknown's avatar
unknown committed
1398 1399 1400
  For each client connection we create a separate thread with THD serving as
  a thread/connection descriptor
*/
1401

1402
class THD :public Statement,
1403
           public Open_tables_state
unknown's avatar
unknown committed
1404
{
unknown's avatar
unknown committed
1405
public:
1406
  /* Used to execute base64 coded binlog events in MySQL server */
1407
  Relay_log_info* rli_fake;
1408

1409 1410 1411 1412 1413 1414 1415 1416
  /*
    Constant for THD::where initialization in the beginning of every query.

    It's needed because we do not save/restore THD::where normally during
    primary (non subselect) query execution.
  */
  static const char * const DEFAULT_WHERE;

1417 1418
#ifdef EMBEDDED_LIBRARY
  struct st_mysql  *mysql;
unknown's avatar
SCRUM  
unknown committed
1419 1420
  unsigned long	 client_stmt_id;
  unsigned long  client_param_count;
unknown's avatar
unknown committed
1421
  struct st_mysql_bind *client_params;
unknown's avatar
unknown committed
1422 1423
  char *extra_data;
  ulong extra_length;
1424 1425 1426 1427 1428
  struct st_mysql_data *cur_data;
  struct st_mysql_data *first_data;
  struct st_mysql_data **data_tail;
  void clear_data_list();
  struct st_mysql_data *alloc_new_dataset();
1429 1430 1431 1432 1433 1434
  /*
    In embedded server it points to the statement that is processed
    in the current query. We store some results directly in statement
    fields then.
  */
  struct st_mysql_stmt *current_stmt;
1435
#endif
unknown's avatar
unknown committed
1436
  NET	  net;				// client connection descriptor
1437
  scheduler_functions *scheduler;       // Scheduler for this connection
1438
  MEM_ROOT warn_root;			// For warnings and errors
1439
  Protocol *protocol;			// Current protocol
unknown's avatar
unknown committed
1440 1441
  Protocol_text   protocol_text;	// Normal protocol
  Protocol_binary protocol_binary;	// Binary protocol
unknown's avatar
unknown committed
1442 1443
  HASH    user_vars;			// hash for user variables
  String  packet;			// dynamic buffer for network I/O
1444
  String  convert_buffer;               // buffer for charset conversions
unknown's avatar
unknown committed
1445
  struct  sockaddr_in remote;		// client socket address
1446
  struct  my_rnd_struct rand;		// used for authentication
unknown's avatar
unknown committed
1447
  struct  system_variables variables;	// Changeable local variables
1448
  struct  system_status_var status_var; // Per thread statistic vars
1449
  struct  system_status_var org_status_var; // For user statistics
1450
  struct  system_status_var *initial_status_var; /* used by show status */
1451 1452 1453 1454
  THR_LOCK_INFO lock_info;              // Locking info of this thread
  THR_LOCK_OWNER main_lock_id;          // To use for conventional queries
  THR_LOCK_OWNER *lock_id;              // If not main_lock_id, points to
                                        // the lock_id of a cursor.
1455 1456 1457 1458 1459 1460 1461 1462 1463
  /**
    Protects THD data accessed from other threads:
    - thd->query and thd->query_length (used by SHOW ENGINE
      INNODB STATUS and SHOW PROCESSLIST
    - thd->mysys_var (used by KILL statement and shutdown).
    Is locked when THD is deleted.
  */
  pthread_mutex_t LOCK_thd_data;

1464
  /* all prepared statements and cursors of this connection */
1465
  Statement_map stmt_map;
unknown's avatar
unknown committed
1466 1467 1468 1469 1470 1471
  /*
    A pointer to the stack frame of handle_one_connection(),
    which is called first in the thread for handling a client
  */
  char	  *thread_stack;

1472 1473 1474 1475 1476
  /**
    Currently selected catalog.
  */
  char *catalog;

unknown's avatar
unknown committed
1477 1478 1479
  /**
    @note
    Some members of THD (currently 'Statement::db',
1480 1481 1482 1483 1484 1485
    'catalog' and 'query')  are set and alloced by the slave SQL thread
    (for the THD of that thread); that thread is (and must remain, for now)
    the only responsible for freeing these 3 members. If you add members
    here, and you add code to set them in replication, don't forget to
    free_them_and_set_them_to_0 in replication properly. For details see
    the 'err:' label of the handle_slave_sql() in sql/slave.cc.
unknown's avatar
unknown committed
1486 1487

    @see handle_slave_sql
1488 1489
  */

1490 1491
  Security_context main_security_ctx;
  Security_context *security_ctx;
1492

1493 1494 1495 1496
  /*
    Points to info-string that we show in SHOW PROCESSLIST
    You are supposed to update thd->proc_info only if you have coded
    a time-consuming piece that MySQL can get stuck in for a long time.
1497 1498 1499

    Set it using the  thd_proc_info(THD *thread, const char *message)
    macro/function.
1500 1501 1502 1503

    This member is accessed and assigned without any synchronization.
    Therefore, it may point only to constant (statically
    allocated) strings, which memory won't go away over time.
1504
  */
unknown's avatar
unknown committed
1505
  const char *proc_info;
1506

1507 1508 1509 1510 1511 1512 1513 1514
  /*
    Used in error messages to tell user in what part of MySQL we found an
    error. E. g. when where= "having clause", if fix_fields() fails, user
    will know that the error was in having clause.
  */
  const char *where;

  double tmp_double_value;                    /* Used in set_var.cc */
1515
  ulong client_capabilities;		/* What the client supports */
1516
  ulong max_client_packet_length;
1517

unknown's avatar
unknown committed
1518
  HASH		handler_tables_hash;
unknown's avatar
unknown committed
1519 1520 1521
  /*
    One thread can hold up to one named user-level lock. This variable
    points to a lock object if the lock is present. See item_func.cc and
1522
    chapter 'Miscellaneous functions', for functions GET_LOCK, RELEASE_LOCK.
unknown's avatar
unknown committed
1523
  */
1524
  User_level_lock *ull;
1525 1526
#ifndef DBUG_OFF
  uint dbug_sentry; // watch out for memory corruption
1527
#endif
unknown's avatar
unknown committed
1528
  struct st_my_thread_var *mysys_var;
1529
  /*
1530
    Type of current query: COM_STMT_PREPARE, COM_QUERY, etc. Set from
1531 1532 1533
    first byte of the packet in do_command()
  */
  enum enum_server_command command;
unknown's avatar
unknown committed
1534
  uint32     server_id;
unknown's avatar
unknown committed
1535
  uint32     file_id;			// for LOAD DATA INFILE
1536
  /* remote (peer) port */
1537
  uint16     peer_port;
1538
  time_t     start_time, user_time;
1539 1540
  // track down slow pthread_create
  ulonglong  prior_thr_create_utime, thr_create_utime;
1541
  ulonglong  start_utime, utime_after_lock;
1542

unknown's avatar
unknown committed
1543
  thr_lock_type update_lock_default;
1544
  Delayed_insert *di;
1545

1546 1547
  /* <> 0 if we are inside of trigger or stored function. */
  uint in_sub_stmt;
1548 1549
  /* TRUE when the current top has SQL_LOG_BIN ON */
  bool sql_log_bin_toplevel;
1550 1551
  /* True when opt_userstat_running is set at start of query */
  bool userstat_running;
1552

1553
  /* container for handler's private per-connection data */
1554
  Ha_data ha_data[MAX_HA];
1555

1556 1557 1558 1559 1560 1561 1562 1563
  /* Place to store various things */
  union 
  { 
    /*
      Used by subquery optimizations, see Item_in_subselect::emb_on_expr_nest.
    */
    TABLE_LIST *emb_on_expr_nest;
  } thd_marker;
1564
#ifndef MYSQL_CLIENT
1565 1566
  int binlog_setup_trx_data();

1567
  /*
1568
    Public interface to write RBR events to the binlog
1569
  */
1570
  void binlog_start_trans_and_stmt();
1571
  void binlog_set_stmt_begin();
1572
  int binlog_write_table_map(TABLE *table, bool is_transactional);
1573
  int binlog_write_row(TABLE* table, bool is_transactional,
1574 1575
                       MY_BITMAP const* cols, size_t colcnt,
                       const uchar *buf);
1576
  int binlog_delete_row(TABLE* table, bool is_transactional,
1577 1578
                        MY_BITMAP const* cols, size_t colcnt,
                        const uchar *buf);
1579
  int binlog_update_row(TABLE* table, bool is_transactional,
1580 1581
                        MY_BITMAP const* cols, size_t colcnt,
                        const uchar *old_data, const uchar *new_data);
1582 1583 1584 1585 1586 1587 1588 1589 1590

  void set_server_id(uint32 sid) { server_id = sid; }

  /*
    Member functions to handle pending event for row-level logging.
  */
  template <class RowsEventT> Rows_log_event*
    binlog_prepare_pending_rows_event(TABLE* table, uint32 serv_id,
                                      MY_BITMAP const* cols,
1591 1592
                                      size_t colcnt,
                                      size_t needed,
unknown's avatar
unknown committed
1593 1594
                                      bool is_transactional,
				      RowsEventT* hint);
1595 1596 1597
  Rows_log_event* binlog_get_pending_rows_event() const;
  void            binlog_set_pending_rows_event(Rows_log_event* ev);
  int binlog_flush_pending_rows_event(bool stmt_end);
1598
  int binlog_remove_pending_rows_event(bool clear_maps);
1599

1600
private:
1601 1602 1603 1604 1605
  /*
    Number of outstanding table maps, i.e., table maps in the
    transaction cache.
  */
  uint binlog_table_maps;
1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616

  enum enum_binlog_flag {
    BINLOG_FLAG_UNSAFE_STMT_PRINTED,
    BINLOG_FLAG_COUNT
  };

  /**
     Flags with per-thread information regarding the status of the
     binary log.
   */
  uint32 binlog_flags;
1617
public:
1618 1619 1620
  uint get_binlog_table_maps() const {
    return binlog_table_maps;
  }
1621 1622
#endif /* MYSQL_CLIENT */

1623 1624
public:

unknown's avatar
unknown committed
1625
  struct st_transactions {
1626
    SAVEPOINT *savepoints;
unknown's avatar
unknown committed
1627 1628
    THD_TRANS all;			// Trans since BEGIN WORK
    THD_TRANS stmt;			// Trans for current statement
1629
    bool on;                            // see ha_enable_transaction()
1630
    XID_STATE xid_state;
Sergei Golubchik's avatar
Sergei Golubchik committed
1631
    WT_THD wt;                          ///< for deadlock detection
1632 1633
    Rows_log_event *m_pending_rows_event;

1634
    /*
1635
       Tables changed in transaction (that must be invalidated in query cache).
1636
       List contain only transactional tables, that not invalidated in query
1637 1638 1639 1640 1641 1642
       cache (instead of full list of changed in transaction tables).
    */
    CHANGED_TABLE_LIST* changed_tables;
    MEM_ROOT mem_root; // Transaction-life memory allocation pool
    void cleanup()
    {
1643 1644
      changed_tables= 0;
      savepoints= 0;
1645 1646 1647 1648 1649 1650 1651 1652
      /*
        If rm_error is raised, it means that this piece of a distributed
        transaction has failed and must be rolled back. But the user must
        rollback it explicitly, so don't start a new distributed XA until
        then.
      */
      if (!xid_state.rm_error)
        xid_state.xid.null();
1653
#ifdef USING_TRANSACTIONS
1654
      free_root(&mem_root,MYF(MY_KEEP_PREALLOC));
1655
#endif
1656
    }
1657 1658
    st_transactions()
    {
1659
#ifdef USING_TRANSACTIONS
1660
      bzero((char*)this, sizeof(*this));
1661
      xid_state.xid.null();
1662
      init_sql_alloc(&mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
1663 1664
#else
      xid_state.xa_state= XA_NOTR;
1665
#endif
1666
    }
unknown's avatar
unknown committed
1667
  } transaction;
1668
  Field      *dup_field;
unknown's avatar
unknown committed
1669
#ifndef __WIN__
unknown's avatar
unknown committed
1670
  sigset_t signals;
unknown's avatar
unknown committed
1671
#endif
1672 1673
#ifdef SIGNAL_WITH_VIO_CLOSE
  Vio* active_vio;
1674
#endif
1675 1676 1677 1678
  /*
    This is to track items changed during execution of a prepared
    statement/stored procedure. It's created by
    register_item_tree_change() in memory root of THD, and freed in
unknown's avatar
unknown committed
1679 1680
    rollback_item_tree_changes(). For conventional execution it's always
    empty.
1681 1682 1683
  */
  Item_change_list change_list;

unknown's avatar
unknown committed
1684
  /*
unknown's avatar
unknown committed
1685 1686
    A permanent memory area of the statement. For conventional
    execution, the parsed tree and execution runtime reside in the same
unknown's avatar
unknown committed
1687
    memory root. In this case stmt_arena points to THD. In case of
unknown's avatar
unknown committed
1688
    a prepared statement or a stored procedure statement, thd->mem_root
unknown's avatar
unknown committed
1689
    conventionally points to runtime memory, and thd->stmt_arena
unknown's avatar
unknown committed
1690 1691 1692
    points to the memory of the PS/SP, where the parsed tree of the
    statement resides. Whenever you need to perform a permanent
    transformation of a parsed tree, you should allocate new memory in
unknown's avatar
unknown committed
1693 1694
    stmt_arena, to allow correct re-execution of PS/SP.
    Note: in the parser, stmt_arena == thd, even for PS/SP.
unknown's avatar
unknown committed
1695
  */
unknown's avatar
unknown committed
1696
  Query_arena *stmt_arena;
1697 1698 1699 1700 1701 1702 1703

  /*
    map for tables that will be updated for a multi-table update query
    statement, for other query statements, this will be zero.
  */
  table_map table_map_for_update;

1704 1705
  /* Tells if LAST_INSERT_ID(#) was called for the current statement */
  bool arg_of_last_insert_id_function;
1706
  /*
1707 1708
    ALL OVER THIS FILE, "insert_id" means "*automatically generated* value for
    insertion into an auto_increment column".
1709 1710
  */
  /*
1711 1712 1713 1714 1715 1716
    This is the first autogenerated insert id which was *successfully*
    inserted by the previous statement (exactly, if the previous statement
    didn't successfully insert an autogenerated insert id, then it's the one
    of the statement before, etc).
    It can also be set by SET LAST_INSERT_ID=# or SELECT LAST_INSERT_ID(#).
    It is returned by LAST_INSERT_ID().
1717
  */
1718
  ulonglong  first_successful_insert_id_in_prev_stmt;
1719
  /*
1720 1721 1722 1723
    Variant of the above, used for storing in statement-based binlog. The
    difference is that the one above can change as the execution of a stored
    function progresses, while the one below is set once and then does not
    change (which is the value which statement-based binlog needs).
1724
  */
1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735
  ulonglong  first_successful_insert_id_in_prev_stmt_for_binlog;
  /*
    This is the first autogenerated insert id which was *successfully*
    inserted by the current statement. It is maintained only to set
    first_successful_insert_id_in_prev_stmt when statement ends.
  */
  ulonglong  first_successful_insert_id_in_cur_stmt;
  /*
    We follow this logic:
    - when stmt starts, first_successful_insert_id_in_prev_stmt contains the
    first insert id successfully inserted by the previous stmt.
1736 1737 1738 1739
    - as stmt makes progress, handler::insert_id_for_cur_row changes;
    every time get_auto_increment() is called,
    auto_inc_intervals_in_cur_stmt_for_binlog is augmented with the
    reserved interval (if statement-based binlogging).
1740 1741 1742
    - at first successful insertion of an autogenerated value,
    first_successful_insert_id_in_cur_stmt is set to
    handler::insert_id_for_cur_row.
1743 1744 1745
    - when stmt goes to binlog,
    auto_inc_intervals_in_cur_stmt_for_binlog is binlogged if
    non-empty.
1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770
    - when stmt ends, first_successful_insert_id_in_prev_stmt is set to
    first_successful_insert_id_in_cur_stmt.
  */
  /*
    stmt_depends_on_first_successful_insert_id_in_prev_stmt is set when
    LAST_INSERT_ID() is used by a statement.
    If it is set, first_successful_insert_id_in_prev_stmt_for_binlog will be
    stored in the statement-based binlog.
    This variable is CUMULATIVE along the execution of a stored function or
    trigger: if one substatement sets it to 1 it will stay 1 until the
    function/trigger ends, thus making sure that
    first_successful_insert_id_in_prev_stmt_for_binlog does not change anymore
    and is propagated to the caller for binlogging.
  */
  bool       stmt_depends_on_first_successful_insert_id_in_prev_stmt;
  /*
    List of auto_increment intervals reserved by the thread so far, for
    storage in the statement-based binlog.
    Note that its minimum is not first_successful_insert_id_in_cur_stmt:
    assuming a table with an autoinc column, and this happens:
    INSERT INTO ... VALUES(3);
    SET INSERT_ID=3; INSERT IGNORE ... VALUES (NULL);
    then the latter INSERT will insert no rows
    (first_successful_insert_id_in_cur_stmt == 0), but storing "INSERT_ID=3"
    in the binlog is still needed; the list's minimum will contain 3.
Guilhem Bichot's avatar
Guilhem Bichot committed
1771 1772 1773
    This variable is cumulative: if several statements are written to binlog
    as one (stored functions or triggers are used) this list is the
    concatenation of all intervals reserved by all statements.
1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784
  */
  Discrete_intervals_list auto_inc_intervals_in_cur_stmt_for_binlog;
  /* Used by replication and SET INSERT_ID */
  Discrete_intervals_list auto_inc_intervals_forced;
  /*
    There is BUG#19630 where statement-based replication of stored
    functions/triggers with two auto_increment columns breaks.
    We however ensure that it works when there is 0 or 1 auto_increment
    column; our rules are
    a) on master, while executing a top statement involving substatements,
    first top- or sub- statement to generate auto_increment values wins the
1785 1786 1787
    exclusive right to see its values be written to binlog (the write
    will be done by the statement or its caller), and the losers won't see
    their values be written to binlog.
1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813
    b) on slave, while replicating a top statement involving substatements,
    first top- or sub- statement to need to read auto_increment values from
    the master's binlog wins the exclusive right to read them (so the losers
    won't read their values from binlog but instead generate on their own).
    a) implies that we mustn't backup/restore
    auto_inc_intervals_in_cur_stmt_for_binlog.
    b) implies that we mustn't backup/restore auto_inc_intervals_forced.

    If there are more than 1 auto_increment columns, then intervals for
    different columns may mix into the
    auto_inc_intervals_in_cur_stmt_for_binlog list, which is logically wrong,
    but there is no point in preventing this mixing by preventing intervals
    from the secondly inserted column to come into the list, as such
    prevention would be wrong too.
    What will happen in the case of
    INSERT INTO t1 (auto_inc) VALUES(NULL);
    where t1 has a trigger which inserts into an auto_inc column of t2, is
    that in binlog we'll store the interval of t1 and the interval of t2 (when
    we store intervals, soon), then in slave, t1 will use both intervals, t2
    will use none; if t1 inserts the same number of rows as on master,
    normally the 2nd interval will not be used by t1, which is fine. t2's
    values will be wrong if t2's internal auto_increment counter is different
    from what it was on master (which is likely). In 5.1, in mixed binlogging
    mode, row-based binlogging is used for such cases where two
    auto_increment columns are inserted.
  */
1814
  inline void record_first_successful_insert_id_in_cur_stmt(ulonglong id_arg)
1815 1816
  {
    if (first_successful_insert_id_in_cur_stmt == 0)
1817
      first_successful_insert_id_in_cur_stmt= id_arg;
1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830
  }
  inline ulonglong read_first_successful_insert_id_in_prev_stmt(void)
  {
    if (!stmt_depends_on_first_successful_insert_id_in_prev_stmt)
    {
      /* It's the first time we read it */
      first_successful_insert_id_in_prev_stmt_for_binlog=
        first_successful_insert_id_in_prev_stmt;
      stmt_depends_on_first_successful_insert_id_in_prev_stmt= 1;
    }
    return first_successful_insert_id_in_prev_stmt;
  }
  /*
1831
    Used by Intvar_log_event::do_apply_event() and by "SET INSERT_ID=#"
1832 1833 1834 1835 1836
    (mysqlbinlog). We'll soon add a variant which can take many intervals in
    argument.
  */
  inline void force_one_auto_inc_interval(ulonglong next_id)
  {
1837
    auto_inc_intervals_forced.empty(); // in case of multiple SET INSERT_ID
1838 1839 1840
    auto_inc_intervals_forced.append(next_id, ULONGLONG_MAX, 0);
  }

1841
  ulonglong  limit_found_rows;
1842
  ulonglong  options;           /* Bitmap of states */
1843 1844 1845 1846 1847 1848 1849 1850 1851
  longlong   row_count_func;    /* For the ROW_COUNT() function */
  ha_rows    cuted_fields;

  /*
    number of rows we actually sent to the client, including "synthetic"
    rows in ROLLUP etc.
  */
  ha_rows    sent_row_count;

1852 1853 1854 1855 1856 1857 1858 1859 1860
  /**
    Number of rows read and/or evaluated for a statement. Used for
    slow log reporting.

    An examined row is defined as a row that is read and/or evaluated
    according to a statement condition, including in
    create_sort_index(). Rows may be counted more than once, e.g., a
    statement including ORDER BY could possibly evaluate the row in
    filesort() before reading it for e.g. update.
1861 1862 1863
  */
  ha_rows    examined_row_count;

unknown's avatar
unknown committed
1864 1865 1866 1867 1868 1869
  /*
    The set of those tables whose fields are referenced in all subqueries
    of the query.
    TODO: possibly this it is incorrect to have used tables in THD because
    with more than one subquery, it is not clear what does the field mean.
  */
unknown's avatar
unknown committed
1870
  table_map  used_tables;
1871
  USER_CONN *user_connect;
1872
  CHARSET_INFO *db_charset;
unknown's avatar
unknown committed
1873 1874 1875
  /*
    FIXME: this, and some other variables like 'count_cuted_fields'
    maybe should be statement/cursor local, that is, moved to Statement
1876 1877
    class. With current implementation warnings produced in each prepared
    statement/cursor settle here.
unknown's avatar
unknown committed
1878
  */
1879
  List	     <MYSQL_ERROR> warn_list;
1880
  uint	     warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_END];
unknown's avatar
unknown committed
1881
  uint	     total_warn_count;
1882
  Diagnostics_area main_da;
1883
#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
unknown's avatar
unknown committed
1884
  PROFILING  profiling;
1885
#endif
unknown's avatar
unknown committed
1886

1887 1888 1889 1890 1891 1892 1893 1894
  /*
    Id of current query. Statement can be reused to execute several queries
    query_id is global in context of the whole MySQL server.
    ID is automatically generated from mutex-protected counter.
    It's used in handler code for various purposes: to check which columns
    from table are necessary for this select, to check if it's necessary to
    update auto-updatable fields (like auto_increment and timestamp).
  */
1895
  query_id_t query_id, warn_id;
unknown's avatar
unknown committed
1896
  ulong      col_access;
1897

1898 1899 1900
#ifdef ERROR_INJECT_SUPPORT
  ulong      error_inject_value;
#endif
1901 1902
  /* Statement id is thread-wide. This counter is used to generate ids */
  ulong      statement_id_counter;
1903
  ulong	     rand_saved_seed1, rand_saved_seed2;
1904 1905 1906 1907 1908
  /*
    Row counter, mainly for errors and warnings. Not increased in
    create_sort_index(); may differ from examined_row_count.
  */
  ulong      row_count;
1909 1910
  ulong      query_plan_flags; 
  ulong      query_plan_fsort_passes; 
unknown's avatar
unknown committed
1911 1912
  pthread_t  real_id;                           /* For debugging */
  my_thread_id  thread_id;
1913
  uint	     tmp_table, global_read_lock;
1914 1915
  uint	     server_status,open_options;
  enum enum_thread_type system_thread;
unknown's avatar
unknown committed
1916
  uint       select_number;             //number of select (used for EXPLAIN)
unknown's avatar
unknown committed
1917 1918
  /* variables.transaction_isolation is reset to this after each commit */
  enum_tx_isolation session_tx_isolation;
1919
  enum_check_fields count_cuted_fields;
1920 1921 1922

  DYNAMIC_ARRAY user_var_events;        /* For user variables replication */
  MEM_ROOT      *user_var_events_alloc; /* Allocate above array elements here */
1923

1924 1925 1926 1927 1928 1929 1930 1931
  enum killed_state
  {
    NOT_KILLED=0,
    KILL_BAD_DATA=1,
    KILL_CONNECTION=ER_SERVER_SHUTDOWN,
    KILL_QUERY=ER_QUERY_INTERRUPTED,
    KILLED_NO_VALUE      /* means neither of the states */
  };
1932 1933
  killed_state volatile killed;

1934
  /* scramble - random string sent to client on handshake */
unknown's avatar
unknown committed
1935
  char	     scramble[SCRAMBLE_LENGTH+1];
1936

1937
  bool       slave_thread, one_shot_set;
1938 1939
  /* tells if current statement should binlog row-based(1) or stmt-based(0) */
  bool       current_stmt_binlog_row_based;
1940
  bool	     locked, some_tables_deleted;
1941
  bool       last_cuted_field;
1942
  bool	     no_errors, password;
1943 1944
  bool       extra_port;                        /* If extra connection */

1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970
  /**
    Set to TRUE if execution of the current compound statement
    can not continue. In particular, disables activation of
    CONTINUE or EXIT handlers of stored routines.
    Reset in the end of processing of the current user request, in
    @see mysql_reset_thd_for_next_command().
  */
  bool is_fatal_error;
  /**
    Set by a storage engine to request the entire
    transaction (that possibly spans multiple engines) to
    rollback. Reset in ha_rollback.
  */
  bool       transaction_rollback_request;
  /**
    TRUE if we are in a sub-statement and the current error can
    not be safely recovered until we left the sub-statement mode.
    In particular, disables activation of CONTINUE and EXIT
    handlers inside sub-statements. E.g. if it is a deadlock
    error and requires a transaction-wide rollback, this flag is
    raised (traditionally, MySQL first has to close all the reads
    via @see handler::ha_index_or_rnd_end() and only then perform
    the rollback).
    Reset to FALSE when we leave the sub-statement mode.
  */
  bool       is_fatal_sub_stmt_error;
1971
  bool	     query_start_used, rand_used, time_zone_used;
1972 1973
  /* for IS NULL => = last_insert_id() fix in remove_eq_conds() */
  bool       substitute_null_with_insert_id;
1974
  bool	     in_lock_tables;
1975 1976
  /**
    True if a slave error. Causes the slave to stop. Not the same
1977
    as the statement execution error (is_error()), since
1978 1979 1980 1981 1982
    a statement may be expected to return an error, e.g. because
    it returned an error on master, and this is OK on the slave.
  */
  bool       is_slave_error;
  bool       bootstrap, cleanup_done;
1983

1984 1985
  /**  is set if some thread specific value(s) used in a statement. */
  bool       thread_specific_used;
unknown's avatar
unknown committed
1986
  bool	     charset_is_system_charset, charset_is_collation_connection;
unknown's avatar
unknown committed
1987
  bool       charset_is_character_set_filesystem;
1988
  bool       enable_slow_log;   /* enable slow log for current statement */
1989
  bool	     abort_on_warning;
unknown's avatar
Merge  
unknown committed
1990
  bool 	     got_warning;       /* Set on call to push_warning() */
1991
  bool	     no_warnings_for_error; /* no warnings on call to my_error() */
1992 1993
  /* set during loop of derived table processing */
  bool       derived_tables_processing;
1994
  bool       tablespace_op;	/* This is TRUE in DISCARD/IMPORT TABLESPACE */
1995

1996
  sp_rcontext *spcont;		// SP runtime context
1997 1998
  sp_cache   *sp_proc_cache;
  sp_cache   *sp_func_cache;
unknown's avatar
unknown committed
1999

2000 2001 2002
  /** number of name_const() substitutions, see sp_head.cc:subst_spvars() */
  uint       query_name_consts;

unknown's avatar
unknown committed
2003 2004 2005 2006 2007
  /*
    If we do a purge of binary logs, log index info of the threads
    that are currently reading it needs to be adjusted. To do that
    each thread that is using LOG_INFO needs to adjust the pointer to it
  */
unknown's avatar
unknown committed
2008
  LOG_INFO*  current_linfo;
unknown's avatar
unknown committed
2009
  NET*       slave_net;			// network connection from slave -> m.
2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024

  /*
    Used to update global user stats.  The global user stats are updated
    occasionally with the 'diff' variables.  After the update, the 'diff'
    variables are reset to 0.
  */
  /* Time when the current thread connected to MySQL. */
  time_t current_connect_time;
  /* Last time when THD stats were updated in global_user_stats. */
  time_t last_global_update_time;
  /* Number of commands not reflected in global_user_stats yet. */
  uint select_commands, update_commands, other_commands;
  ulonglong start_cpu_time;
  ulonglong start_bytes_received;

unknown's avatar
unknown committed
2025 2026 2027
  /* Used by the sys_var class to store temporary values */
  union
  {
2028 2029 2030 2031
    my_bool   my_bool_value;
    long      long_value;
    ulong     ulong_value;
    ulonglong ulonglong_value;
unknown's avatar
unknown committed
2032
  } sys_var_tmp;
2033

2034
  struct {
2035 2036
    /*
      If true, mysql_bin_log::write(Log_event) call will not write events to
2037 2038 2039 2040 2041 2042 2043 2044 2045 2046
      binlog, and maintain 2 below variables instead (use
      mysql_bin_log.start_union_events to turn this on)
    */
    bool do_union;
    /*
      If TRUE, at least one mysql_bin_log::write(Log_event) call has been
      made after last mysql_bin_log.start_union_events() call.
    */
    bool unioned_events;
    /*
2047 2048
      If TRUE, at least one mysql_bin_log::write(Log_event e), where
      e.cache_stmt == TRUE call has been made after last
2049 2050 2051
      mysql_bin_log.start_union_events() call.
    */
    bool unioned_events_trans;
2052 2053

    /*
2054 2055 2056 2057
      'queries' (actually SP statements) that run under inside this binlog
      union have thd->query_id >= first_query_id.
    */
    query_id_t first_query_id;
2058
  } binlog_evt_union;
2059 2060

  /**
2061 2062 2063
    Internal parser state.
    Note that since the parser is not re-entrant, we keep only one parser
    state here. This member is valid only when executing code during parsing.
2064
  */
2065
  Parser_state *m_parser_state;
2066

unknown's avatar
unknown committed
2067
#ifdef WITH_PARTITION_STORAGE_ENGINE
unknown's avatar
unknown committed
2068
  partition_info *work_part_info;
unknown's avatar
unknown committed
2069
#endif
unknown's avatar
foo1  
unknown committed
2070

2071 2072 2073 2074 2075
#if defined(ENABLED_DEBUG_SYNC)
  /* Debug Sync facility. See debug_sync.cc. */
  struct st_debug_sync_control *debug_sync_control;
#endif /* defined(ENABLED_DEBUG_SYNC) */

unknown's avatar
unknown committed
2076 2077
  THD();
  ~THD();
2078

unknown's avatar
unknown committed
2079
  void init(void);
2080 2081 2082 2083 2084 2085 2086
  /*
    Initialize memory roots necessary for query processing and (!)
    pre-allocate memory for it. We can't do that in THD constructor because
    there are use cases (acl_init, delayed inserts, watcher threads,
    killing mysqld) where it's vital to not allocate excessive and not used
    memory. Note, that we still don't return error from init_for_queries():
    if preallocation fails, we should notice that at the first call to
2087
    alloc_root.
2088 2089
  */
  void init_for_queries();
2090 2091
  void update_all_stats();
  void update_stats(void);
unknown's avatar
unknown committed
2092
  void change_user(void);
unknown's avatar
unknown committed
2093
  void cleanup(void);
2094
  void cleanup_after_query();
unknown's avatar
unknown committed
2095
  bool store_globals();
2096
  void reset_globals();
2097 2098
#ifdef SIGNAL_WITH_VIO_CLOSE
  inline void set_active_vio(Vio* vio)
2099
  {
2100
    pthread_mutex_lock(&LOCK_thd_data);
2101
    active_vio = vio;
2102
    pthread_mutex_unlock(&LOCK_thd_data);
2103
  }
2104
  inline void clear_active_vio()
2105
  {
2106
    pthread_mutex_lock(&LOCK_thd_data);
2107
    active_vio = 0;
2108
    pthread_mutex_unlock(&LOCK_thd_data);
2109
  }
unknown's avatar
unknown committed
2110
  void close_active_vio();
2111
#endif
unknown's avatar
SCRUM  
unknown committed
2112
  void awake(THD::killed_state state_to_set);
unknown's avatar
unknown committed
2113 2114 2115 2116 2117 2118 2119

#ifndef MYSQL_CLIENT
  enum enum_binlog_query_type {
    /*
      The query can be logged row-based or statement-based
    */
    ROW_QUERY_TYPE,
2120

unknown's avatar
unknown committed
2121 2122 2123 2124
    /*
      The query has to be logged statement-based
    */
    STMT_QUERY_TYPE,
2125

unknown's avatar
unknown committed
2126 2127 2128 2129 2130 2131 2132
    /*
      The query represents a change to a table in the "mysql"
      database and is currently mapped to ROW_QUERY_TYPE.
    */
    MYSQL_QUERY_TYPE,
    QUERY_TYPE_COUNT
  };
2133

unknown's avatar
unknown committed
2134 2135 2136
  int binlog_query(enum_binlog_query_type qtype,
                   char const *query, ulong query_len,
                   bool is_trans, bool suppress_use,
2137
                   int errcode);
unknown's avatar
unknown committed
2138 2139
#endif

2140 2141
  /*
    For enter_cond() / exit_cond() to work the mutex must be got before
2142 2143
    enter_cond(); this mutex is then released by exit_cond().
    Usage must be: lock mutex; enter_cond(); your code; exit_cond().
2144
  */
unknown's avatar
unknown committed
2145 2146 2147 2148
  inline const char* enter_cond(pthread_cond_t *cond, pthread_mutex_t* mutex,
			  const char* msg)
  {
    const char* old_msg = proc_info;
2149
    safe_mutex_assert_owner(mutex);
unknown's avatar
unknown committed
2150 2151 2152 2153 2154 2155 2156
    mysys_var->current_mutex = mutex;
    mysys_var->current_cond = cond;
    proc_info = msg;
    return old_msg;
  }
  inline void exit_cond(const char* old_msg)
  {
unknown's avatar
unknown committed
2157 2158 2159 2160 2161 2162 2163
    /*
      Putting the mutex unlock in exit_cond() ensures that
      mysys_var->current_mutex is always unlocked _before_ mysys_var->mutex is
      locked (if that would not be the case, you'll get a deadlock if someone
      does a THD::awake() on you).
    */
    pthread_mutex_unlock(mysys_var->current_mutex);
unknown's avatar
unknown committed
2164 2165 2166 2167 2168 2169
    pthread_mutex_lock(&mysys_var->mutex);
    mysys_var->current_mutex = 0;
    mysys_var->current_cond = 0;
    proc_info = old_msg;
    pthread_mutex_unlock(&mysys_var->mutex);
  }
unknown's avatar
unknown committed
2170
  inline time_t query_start() { query_start_used=1; return start_time; }
2171
  inline void set_time()
2172
  {
2173 2174 2175 2176 2177 2178 2179
    if (user_time)
    {
      start_time= user_time;
      start_utime= utime_after_lock= my_micro_time();
    }
    else
      start_utime= utime_after_lock= my_micro_time_and_time(&start_time);
2180
  }
2181 2182 2183 2184 2185 2186
  inline void	set_current_time()    { start_time= my_time(MY_WME); }
  inline void	set_time(time_t t)
  {
    start_time= user_time= t;
    start_utime= utime_after_lock= my_micro_time();
  }
2187 2188 2189 2190 2191
  /*TODO: this will be obsolete when we have support for 64 bit my_time_t */
  inline bool	is_valid_time() 
  { 
    return (start_time < (time_t) MY_TIME_T_MAX); 
  }
2192 2193
  void set_time_after_lock()  { utime_after_lock= my_micro_time(); }
  ulonglong current_utime()  { return my_micro_time(); }
2194 2195 2196
  inline ulonglong found_rows(void)
  {
    return limit_found_rows;
2197
  }
2198 2199
  inline bool active_transaction()
  {
2200 2201
#ifdef USING_TRANSACTIONS
    return server_status & SERVER_STATUS_IN_TRANS;
2202 2203 2204
#else
    return 0;
#endif
2205
  }
unknown's avatar
unknown committed
2206 2207
  inline bool fill_derived_tables()
  {
unknown's avatar
unknown committed
2208
    return !stmt_arena->is_stmt_prepare() && !lex->only_view_structure();
unknown's avatar
unknown committed
2209
  }
2210 2211 2212 2213
  inline bool fill_information_schema_tables()
  {
    return !stmt_arena->is_stmt_prepare();
  }
2214
  inline void* trans_alloc(unsigned int size)
unknown's avatar
unknown committed
2215
  {
2216 2217
    return alloc_root(&transaction.mem_root,size);
  }
2218

2219 2220 2221 2222
  LEX_STRING *make_lex_string(LEX_STRING *lex_str,
                              const char* str, uint length,
                              bool allocate_lex_string);

2223 2224 2225
  bool convert_string(LEX_STRING *to, CHARSET_INFO *to_cs,
		      const char *from, uint from_length,
		      CHARSET_INFO *from_cs);
2226 2227 2228

  bool convert_string(String *s, CHARSET_INFO *from_cs, CHARSET_INFO *to_cs);

2229
  void add_changed_table(TABLE *table);
unknown's avatar
unknown committed
2230 2231
  void add_changed_table(const char *key, long key_length);
  CHANGED_TABLE_LIST * changed_table_dup(const char *key, long key_length);
unknown's avatar
unknown committed
2232
  int send_explain_fields(select_result *result);
2233
#ifndef EMBEDDED_LIBRARY
2234 2235 2236 2237 2238 2239 2240
  /**
    Clear the current error, if any.
    We do not clear is_fatal_error or is_fatal_sub_stmt_error since we
    assume this is never called if the fatal error is set.
    @todo: To silence an error, one should use Internal_error_handler
    mechanism. In future this function will be removed.
  */
unknown's avatar
unknown committed
2241 2242
  inline void clear_error()
  {
2243
    DBUG_ENTER("clear_error");
2244 2245
    if (main_da.is_error())
      main_da.reset_diagnostics_area();
2246
    is_slave_error= 0;
2247
    DBUG_VOID_RETURN;
unknown's avatar
unknown committed
2248
  }
2249
  inline bool vio_ok() const { return net.vio != 0; }
2250 2251
#else
  void clear_error();
2252
  inline bool vio_ok() const { return true; }
2253
#endif
2254 2255 2256 2257 2258
  /**
    Mark the current error as fatal. Warning: this does not
    set any error, it sets a property of the error, so must be
    followed or prefixed with my_error().
  */
2259 2260 2261
  inline void fatal_error()
  {
    is_fatal_error= 1;
unknown's avatar
unknown committed
2262
    DBUG_PRINT("error",("Fatal error set"));
2263
  }
2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276
  /**
    TRUE if there is an error in the error stack.

    Please use this method instead of direct access to
    net.report_error.

    If TRUE, the current (sub)-statement should be aborted.
    The main difference between this member and is_fatal_error
    is that a fatal error can not be handled by a stored
    procedure continue handler, whereas a normal error can.

    To raise this flag, use my_error().
  */
2277
  inline bool is_error() const { return main_da.is_error(); }
2278
  inline CHARSET_INFO *charset() { return variables.character_set_client; }
unknown's avatar
unknown committed
2279
  void update_charset();
2280

unknown's avatar
unknown committed
2281
  inline Query_arena *activate_stmt_arena_if_needed(Query_arena *backup)
unknown's avatar
unknown committed
2282 2283
  {
    /*
unknown's avatar
unknown committed
2284 2285
      Use the persistent arena if we are in a prepared statement or a stored
      procedure statement and we have not already changed to use this arena.
unknown's avatar
unknown committed
2286
    */
unknown's avatar
unknown committed
2287
    if (!stmt_arena->is_conventional() && mem_root != stmt_arena->mem_root)
unknown's avatar
unknown committed
2288
    {
unknown's avatar
unknown committed
2289 2290
      set_n_backup_active_arena(stmt_arena, backup);
      return stmt_arena;
unknown's avatar
unknown committed
2291 2292 2293 2294
    }
    return 0;
  }

2295
  void change_item_tree(Item **place, Item *new_value)
2296
  {
2297
    /* TODO: check for OOM condition here */
unknown's avatar
unknown committed
2298
    if (!stmt_arena->is_conventional())
unknown's avatar
unknown committed
2299
      nocheck_register_item_tree_change(place, *place, mem_root);
2300
    *place= new_value;
2301 2302
  }
  void nocheck_register_item_tree_change(Item **place, Item *old_value,
2303
                                         MEM_ROOT *runtime_memroot);
2304
  void rollback_item_tree_changes();
2305 2306 2307 2308 2309 2310

  /*
    Cleanup statement parse state (parse tree, lex) and execution
    state after execution of a non-prepared SQL statement.
  */
  void end_statement();
2311 2312
  inline int killed_errno() const
  {
2313 2314
    killed_state killed_val; /* to cache the volatile 'killed' */
    return (killed_val= killed) != KILL_BAD_DATA ? killed_val : 0;
2315 2316 2317
  }
  inline void send_kill_message() const
  {
unknown's avatar
unknown committed
2318
    int err= killed_errno();
2319
    if (err)
2320 2321 2322
    {
      if ((err == KILL_CONNECTION) && !shutdown_in_progress)
        err = KILL_QUERY;
2323
      my_message(err, ER(err), MYF(0));
2324
    }
2325
  }
unknown's avatar
unknown committed
2326 2327 2328 2329
  /* return TRUE if we will abort query if we make a warning now */
  inline bool really_abort_on_warning()
  {
    return (abort_on_warning &&
unknown's avatar
unknown committed
2330
            (!transaction.stmt.modified_non_trans_table ||
unknown's avatar
unknown committed
2331 2332
             (variables.sql_mode & MODE_STRICT_ALL_TABLES)));
  }
2333
  void set_status_var_init();
2334
  bool is_context_analysis_only()
unknown's avatar
unknown committed
2335
    { return stmt_arena->is_stmt_prepare() || lex->view_prepare_mode; }
2336 2337
  void reset_n_backup_open_tables_state(Open_tables_state *backup);
  void restore_backup_open_tables_state(Open_tables_state *backup);
2338 2339
  void reset_sub_statement_state(Sub_statement_state *backup, uint new_state);
  void restore_sub_statement_state(Sub_statement_state *backup);
unknown's avatar
unknown committed
2340 2341
  void set_n_backup_active_arena(Query_arena *set, Query_arena *backup);
  void restore_active_arena(Query_arena *set, Query_arena *backup);
2342

2343 2344
  inline void set_current_stmt_binlog_row_based_if_mixed()
  {
unknown's avatar
unknown committed
2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355
    /*
      If in a stored/function trigger, the caller should already have done the
      change. We test in_sub_stmt to prevent introducing bugs where people
      wouldn't ensure that, and would switch to row-based mode in the middle
      of executing a stored function/trigger (which is too late, see also
      reset_current_stmt_binlog_row_based()); this condition will make their
      tests fail and so force them to propagate the
      lex->binlog_row_based_if_mixed upwards to the caller.
    */
    if ((variables.binlog_format == BINLOG_FORMAT_MIXED) &&
        (in_sub_stmt == 0))
2356
      current_stmt_binlog_row_based= TRUE;
unknown's avatar
unknown committed
2357 2358 2359
  }
  inline void set_current_stmt_binlog_row_based()
  {
2360
    current_stmt_binlog_row_based= TRUE;
2361
  }
2362 2363
  inline void clear_current_stmt_binlog_row_based()
  {
2364
    current_stmt_binlog_row_based= FALSE;
2365
  }
2366 2367
  inline void reset_current_stmt_binlog_row_based()
  {
unknown's avatar
unknown committed
2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381
    /*
      If there are temporary tables, don't reset back to
      statement-based. Indeed it could be that:
      CREATE TEMPORARY TABLE t SELECT UUID(); # row-based
      # and row-based does not store updates to temp tables
      # in the binlog.
      INSERT INTO u SELECT * FROM t; # stmt-based
      and then the INSERT will fail as data inserted into t was not logged.
      So we continue with row-based until the temp table is dropped.
      If we are in a stored function or trigger, we mustn't reset in the
      middle of its execution (as the binary logging way of a stored function
      or trigger is decided when it starts executing, depending for example on
      the caller (for a stored function: if caller is SELECT or
      INSERT/UPDATE/DELETE...).
2382 2383

      Don't reset binlog format for NDB binlog injector thread.
unknown's avatar
unknown committed
2384
    */
2385
    DBUG_PRINT("debug",
2386 2387
               ("temporary_tables: %s, in_sub_stmt: %s, system_thread: %s",
                YESNO(temporary_tables), YESNO(in_sub_stmt),
2388
                show_system_thread(system_thread)));
2389 2390
    if ((temporary_tables == NULL) && (in_sub_stmt == 0) &&
        (system_thread != SYSTEM_THREAD_NDBCLUSTER_BINLOG))
unknown's avatar
unknown committed
2391
    {
2392
      current_stmt_binlog_row_based=
unknown's avatar
unknown committed
2393 2394
        test(variables.binlog_format == BINLOG_FORMAT_ROW);
    }
2395
  }
unknown's avatar
unknown committed
2396

2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408
  /**
    Set the current database; use deep copy of C-string.

    @param new_db     a pointer to the new database name.
    @param new_db_len length of the new database name.

    Initialize the current database from a NULL-terminated string with
    length. If we run out of memory, we free the current database and
    return TRUE.  This way the user will notice the error as there will be
    no current database selected (in addition to the error message set by
    malloc).

2409 2410 2411 2412
    @note This operation just sets {db, db_length}. Switching the current
    database usually involves other actions, like switching other database
    attributes including security context. In the future, this operation
    will be made private and more convenient interface will be provided.
2413 2414 2415 2416

    @return Operation status
      @retval FALSE Success
      @retval TRUE  Out-of-memory error
unknown's avatar
unknown committed
2417
  */
2418
  bool set_db(const char *new_db, size_t new_db_len)
unknown's avatar
unknown committed
2419
  {
2420 2421 2422 2423
    /* Do not reallocate memory if current chunk is big enough. */
    if (db && new_db && db_length >= new_db_len)
      memcpy(db, new_db, new_db_len+1);
    else
unknown's avatar
unknown committed
2424
    {
unknown's avatar
unknown committed
2425 2426
      x_free(db);
      db= new_db ? my_strndup(new_db, new_db_len, MYF(MY_WME)) : NULL;
unknown's avatar
unknown committed
2427
    }
2428 2429
    db_length= db ? new_db_len : 0;
    return new_db && !db;
unknown's avatar
unknown committed
2430
  }
2431 2432 2433 2434 2435 2436 2437

  /**
    Set the current database; use shallow copy of C-string.

    @param new_db     a pointer to the new database name.
    @param new_db_len length of the new database name.

2438 2439 2440 2441
    @note This operation just sets {db, db_length}. Switching the current
    database usually involves other actions, like switching other database
    attributes including security context. In the future, this operation
    will be made private and more convenient interface will be provided.
2442
  */
2443
  void reset_db(char *new_db, size_t new_db_len)
unknown's avatar
unknown committed
2444 2445 2446 2447 2448 2449 2450 2451 2452
  {
    db= new_db;
    db_length= new_db_len;
  }
  /*
    Copy the current database to the argument. Use the current arena to
    allocate memory for a deep copy: current database may be freed after
    a statement is parsed but before it's executed.
  */
2453
  bool copy_db_to(char **p_db, size_t *p_db_length)
unknown's avatar
unknown committed
2454 2455 2456 2457 2458 2459 2460
  {
    if (db == NULL)
    {
      my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
      return TRUE;
    }
    *p_db= strmake(db, db_length);
2461
    *p_db_length= db_length;
unknown's avatar
unknown committed
2462 2463
    return FALSE;
  }
2464
  thd_scheduler event_scheduler;
unknown's avatar
unknown committed
2465 2466

public:
2467 2468 2469
  inline Internal_error_handler *get_internal_handler()
  { return m_internal_handler; }

unknown's avatar
unknown committed
2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481
  /**
    Add an internal error handler to the thread execution context.
    @param handler the exception handler to add
  */
  void push_internal_handler(Internal_error_handler *handler);

  /**
    Handle an error condition.
    @param sql_errno the error number
    @param level the error level
    @return true if the error is handled
  */
2482
  virtual bool handle_error(uint sql_errno, const char *message,
unknown's avatar
unknown committed
2483 2484 2485 2486 2487
                            MYSQL_ERROR::enum_warning_level level);

  /**
    Remove the error handler last pushed.
  */
2488
  Internal_error_handler *pop_internal_handler();
unknown's avatar
unknown committed
2489

2490 2491 2492 2493 2494 2495 2496 2497
  /** Overloaded to guard query/query_length fields */
  virtual void set_statement(Statement *stmt);

  /**
    Assign a new value to thd->query.
    Protected with LOCK_thd_data mutex.
  */
  void set_query(char *query_arg, uint32 query_length_arg);
2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509
  void set_current_user_used() { current_user_used= TRUE; }
  bool is_current_user_used() { return current_user_used; }
  void clean_current_user_used() { current_user_used= FALSE; }
  void get_definer(LEX_USER *definer);
  void set_invoker(const LEX_STRING *user, const LEX_STRING *host)
  {
    invoker_user= *user;
    invoker_host= *host;
  }
  LEX_STRING get_invoker_user() { return invoker_user; }
  LEX_STRING get_invoker_host() { return invoker_host; }
  bool has_invoker() { return invoker_user.length > 0; }
Igor Babaev's avatar
Igor Babaev committed
2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530

private:
  /* 
    This reference points to the table arena when the expression
    for a virtual column is being evaluated
  */ 
  Query_arena *arena_for_cached_items;

public:
  void reset_arena_for_cached_items(Query_arena *new_arena)
  {
    arena_for_cached_items= new_arena;
  }
  Query_arena *switch_to_arena_for_cached_items(Query_arena *backup)
  {
    if (!arena_for_cached_items)
      return 0;
    set_n_backup_active_arena(arena_for_cached_items, backup);
    return backup;
  }

unknown's avatar
unknown committed
2531 2532 2533
private:
  /** The current internal error handler for this thread, or NULL. */
  Internal_error_handler *m_internal_handler;
2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549
  /**
    The lex to hold the parsed tree of conventional (non-prepared) queries.
    Whereas for prepared and stored procedure statements we use an own lex
    instance for each new query, for conventional statements we reuse
    the same lex. (@see mysql_parse for details).
  */
  LEX main_lex;
  /**
    This memory root is used for two purposes:
    - for conventional queries, to allocate structures stored in main_lex
    during parsing, and allocate runtime data (execution plan, etc.)
    during execution.
    - for prepared queries, only to allocate runtime data. The parsed
    tree itself is reused between executions and thus is stored elsewhere.
  */
  MEM_ROOT main_mem_root;
2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568

  /**
    It will be set TURE if CURRENT_USER() is called in account management
    statements or default definer is set in CREATE/ALTER SP, SF, Event,
    TRIGGER or VIEW statements.

    Current user will be binlogged into Query_log_event if current_user_used
    is TRUE; It will be stored into invoker_host and invoker_user by SQL thread.
   */
  bool current_user_used;

  /**
    It points to the invoker in the Query_log_event.
    SQL thread use it as the default definer in CREATE/ALTER SP, SF, Event,
    TRIGGER or VIEW statements or current user in account management
    statements if it is not NULL.
   */
  LEX_STRING invoker_user;
  LEX_STRING invoker_host;
unknown's avatar
unknown committed
2569 2570
};

2571 2572 2573
/** A short cut for thd->main_da.set_ok_status(). */

inline void
2574
my_ok(THD *thd, ha_rows affected_rows= 0, ulonglong id= 0,
2575 2576 2577 2578 2579 2580 2581 2582 2583
        const char *message= NULL)
{
  thd->main_da.set_ok_status(thd, affected_rows, id, message);
}


/** A short cut for thd->main_da.set_eof_status(). */

inline void
2584
my_eof(THD *thd)
2585 2586 2587 2588
{
  thd->main_da.set_eof_status(thd);
}

2589
#define tmp_disable_binlog(A)       \
2590
  {ulonglong tmp_disable_binlog__save_options= (A)->options; \
2591
  (A)->options&= ~OPTION_BIN_LOG
2592

2593
#define reenable_binlog(A)   (A)->options= tmp_disable_binlog__save_options;}
2594

2595

unknown's avatar
unknown committed
2596
/*
2597
  Used to hold information about file and file structure in exchange
unknown's avatar
unknown committed
2598
  via non-DB file (...INTO OUTFILE..., ...LOAD DATA...)
2599
  XXX: We never call destructor for objects of this class.
unknown's avatar
unknown committed
2600
*/
2601

unknown's avatar
unknown committed
2602 2603 2604 2605 2606 2607 2608
class sql_exchange :public Sql_alloc
{
public:
  char *file_name;
  String *field_term,*enclosed,*line_term,*line_start,*escaped;
  bool opt_enclosed;
  bool dumpfile;
2609
  ulong skip_lines;
2610
  CHARSET_INFO *cs;
unknown's avatar
unknown committed
2611
  sql_exchange(char *name,bool dumpfile_flag);
2612
  bool escaped_given(void);
unknown's avatar
unknown committed
2613 2614 2615 2616 2617
};

#include "log_event.h"

/*
2618
  This is used to get result from a select
unknown's avatar
unknown committed
2619 2620
*/

unknown's avatar
unknown committed
2621 2622
class JOIN;

unknown's avatar
unknown committed
2623 2624 2625
class select_result :public Sql_alloc {
protected:
  THD *thd;
2626
  SELECT_LEX_UNIT *unit;
2627
  int nest_level;
unknown's avatar
unknown committed
2628 2629 2630
public:
  select_result();
  virtual ~select_result() {};
2631 2632 2633 2634 2635
  virtual int prepare(List<Item> &list, SELECT_LEX_UNIT *u)
  {
    unit= u;
    return 0;
  }
2636
  virtual int prepare2(void) { return 0; }
2637 2638 2639 2640 2641 2642 2643
  /*
    Because of peculiarities of prepared statements protocol
    we need to know number of columns in the result set (if
    there is a result set) apart from sending columns metadata.
  */
  virtual uint field_count(List<Item> &fields) const
  { return fields.elements; }
2644
  virtual bool send_fields(List<Item> &list, uint flags)=0;
unknown's avatar
unknown committed
2645
  virtual bool send_data(List<Item> &items)=0;
unknown's avatar
unknown committed
2646
  virtual bool initialize_tables (JOIN *join=0) { return 0; }
2647
  virtual void send_error(uint errcode,const char *err);
unknown's avatar
unknown committed
2648
  virtual bool send_eof()=0;
2649 2650 2651 2652 2653 2654 2655 2656
  /**
    Check if this query returns a result set and therefore is allowed in
    cursors and set an error message if it is not the case.

    @retval FALSE     success
    @retval TRUE      error, an error message is set
  */
  virtual bool check_simple_select() const;
unknown's avatar
unknown committed
2657
  virtual void abort() {}
2658 2659 2660 2661 2662
  /*
    Cleanup instance of this class for next execution of a prepared
    statement/stored procedure.
  */
  virtual void cleanup();
2663
  void set_thd(THD *thd_arg) { thd= thd_arg; }
2664 2665 2666 2667 2668
  /**
     The nest level, if supported. 
     @return
     -1 if nest level is undefined, otherwise a positive integer.
   */
2669
  int get_nest_level() { return (int) nest_level; }
2670 2671 2672 2673 2674
#ifdef EMBEDDED_LIBRARY
  virtual void begin_dataset() {}
#else
  void begin_dataset() {}
#endif
unknown's avatar
unknown committed
2675 2676 2677
};


2678 2679 2680 2681 2682 2683 2684 2685 2686
/*
  Base class for select_result descendands which intercept and
  transform result set rows. As the rows are not sent to the client,
  sending of result set metadata should be suppressed as well.
*/

class select_result_interceptor: public select_result
{
public:
2687
  select_result_interceptor() {}              /* Remove gcc warning */
2688 2689 2690 2691 2692
  uint field_count(List<Item> &fields) const { return 0; }
  bool send_fields(List<Item> &fields, uint flag) { return FALSE; }
};


unknown's avatar
unknown committed
2693
class select_send :public select_result {
2694 2695 2696 2697 2698 2699
  /**
    True if we have sent result set metadata to the client.
    In this case the client always expects us to end the result
    set with an eof or error packet
  */
  bool is_result_set_started;
unknown's avatar
unknown committed
2700
public:
2701
  select_send() :is_result_set_started(FALSE) {}
2702
  bool send_fields(List<Item> &list, uint flags);
unknown's avatar
unknown committed
2703 2704
  bool send_data(List<Item> &items);
  bool send_eof();
2705
  virtual bool check_simple_select() const { return FALSE; }
2706
  void abort();
2707
  virtual void cleanup();
unknown's avatar
unknown committed
2708 2709 2710
};


2711
class select_to_file :public select_result_interceptor {
2712
protected:
unknown's avatar
unknown committed
2713 2714 2715 2716
  sql_exchange *exchange;
  File file;
  IO_CACHE cache;
  ha_rows row_count;
2717 2718 2719 2720 2721 2722 2723
  char path[FN_REFLEN];

public:
  select_to_file(sql_exchange *ex) :exchange(ex), file(-1),row_count(0L)
  { path[0]=0; }
  ~select_to_file();
  void send_error(uint errcode,const char *err);
2724 2725
  bool send_eof();
  void cleanup();
2726 2727 2728
};


unknown's avatar
unknown committed
2729 2730 2731
#define ESCAPE_CHARS "ntrb0ZN" // keep synchronous with READ_INFO::unescape


unknown's avatar
unknown committed
2732 2733 2734 2735 2736 2737
/*
 List of all possible characters of a numeric value text representation.
*/
#define NUMERIC_CHARS ".0123456789e+-"


2738
class select_export :public select_to_file {
unknown's avatar
unknown committed
2739 2740
  uint field_term_length;
  int field_sep_char,escape_char,line_sep_char;
2741
  int field_term_char; // first char of FIELDS TERMINATED BY or MAX_INT
unknown's avatar
unknown committed
2742 2743 2744 2745 2746 2747
  /*
    The is_ambiguous_field_sep field is true if a value of the field_sep_char
    field is one of the 'n', 't', 'r' etc characters
    (see the READ_INFO::unescape method and the ESCAPE_CHARS constant value).
  */
  bool is_ambiguous_field_sep;
2748 2749 2750 2751 2752 2753
  /*
     The is_ambiguous_field_term is true if field_sep_char contains the first
     char of the FIELDS TERMINATED BY (ENCLOSED BY is empty), and items can
     contain this character.
  */
  bool is_ambiguous_field_term;
unknown's avatar
unknown committed
2754 2755 2756 2757 2758 2759
  /*
    The is_unsafe_field_sep field is true if a value of the field_sep_char
    field is one of the '0'..'9', '+', '-', '.' and 'e' characters
    (see the NUMERIC_CHARS constant value).
  */
  bool is_unsafe_field_sep;
unknown's avatar
unknown committed
2760
  bool fixed_row_size;
2761
  CHARSET_INFO *write_cs; // output charset
unknown's avatar
unknown committed
2762
public:
2763
  select_export(sql_exchange *ex) :select_to_file(ex) {}
2764 2765 2766 2767
  /**
     Creates a select_export to represent INTO OUTFILE <filename> with a
     defined level of subquery nesting.
   */
2768
  select_export(sql_exchange *ex, int nest_level_arg) :select_to_file(ex) 
2769 2770 2771
  {
    nest_level= nest_level_arg;
  }
unknown's avatar
unknown committed
2772
  ~select_export();
2773
  int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
unknown's avatar
unknown committed
2774 2775 2776
  bool send_data(List<Item> &items);
};

unknown's avatar
unknown committed
2777

2778
class select_dump :public select_to_file {
unknown's avatar
unknown committed
2779
public:
2780
  select_dump(sql_exchange *ex) :select_to_file(ex) {}
2781 2782 2783 2784
  /**
     Creates a select_export to represent INTO DUMPFILE <filename> with a
     defined level of subquery nesting.
   */  
2785
  select_dump(sql_exchange *ex, int nest_level_arg) : 
2786 2787 2788 2789
    select_to_file(ex) 
  {
    nest_level= nest_level_arg;
  }
2790
  int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
unknown's avatar
unknown committed
2791 2792
  bool send_data(List<Item> &items);
};
unknown's avatar
unknown committed
2793 2794


2795
class select_insert :public select_result_interceptor {
2796 2797 2798
protected:
  virtual int write_to_binlog(bool is_trans, int errcode);
public:
unknown's avatar
VIEW  
unknown committed
2799
  TABLE_LIST *table_list;
unknown's avatar
unknown committed
2800 2801
  TABLE *table;
  List<Item> *fields;
2802
  ulonglong autoinc_value_of_last_inserted_row; // autogenerated or not
unknown's avatar
unknown committed
2803
  COPY_INFO info;
unknown's avatar
VIEW  
unknown committed
2804
  bool insert_into_view;
unknown's avatar
unknown committed
2805 2806
  select_insert(TABLE_LIST *table_list_par,
		TABLE *table_par, List<Item> *fields_par,
unknown's avatar
unknown committed
2807
		List<Item> *update_fields, List<Item> *update_values,
2808
		enum_duplicates duplic, bool ignore);
unknown's avatar
unknown committed
2809
  ~select_insert();
2810
  int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
2811
  virtual int prepare2(void);
unknown's avatar
unknown committed
2812
  bool send_data(List<Item> &items);
unknown's avatar
unknown committed
2813
  virtual void store_values(List<Item> &values);
2814
  virtual bool can_rollback_data() { return 0; }
unknown's avatar
unknown committed
2815 2816
  void send_error(uint errcode,const char *err);
  bool send_eof();
2817
  void abort();
2818 2819
  /* not implemented: select_insert is never re-used in prepared statements */
  void cleanup();
unknown's avatar
unknown committed
2820 2821
};

unknown's avatar
unknown committed
2822

unknown's avatar
unknown committed
2823 2824
class select_create: public select_insert {
  ORDER *group;
unknown's avatar
VIEW  
unknown committed
2825
  TABLE_LIST *create_table;
unknown's avatar
unknown committed
2826
  HA_CREATE_INFO *create_info;
2827
  TABLE_LIST *select_tables;
2828
  Alter_info *alter_info;
unknown's avatar
unknown committed
2829
  Field **field;
2830 2831 2832 2833
  /* lock data for tmp table */
  MYSQL_LOCK *m_lock;
  /* m_lock or thd->extra_lock */
  MYSQL_LOCK **m_plock;
2834 2835

  virtual int write_to_binlog(bool is_trans, int errcode);
unknown's avatar
unknown committed
2836
public:
unknown's avatar
unknown committed
2837
  select_create (TABLE_LIST *table_arg,
unknown's avatar
VIEW  
unknown committed
2838
		 HA_CREATE_INFO *create_info_par,
2839
                 Alter_info *alter_info_arg,
2840 2841
		 List<Item> &select_fields,enum_duplicates duplic, bool ignore,
                 TABLE_LIST *select_tables_arg)
2842
    :select_insert (NULL, NULL, &select_fields, 0, 0, duplic, ignore),
2843
    create_table(table_arg),
2844 2845
    create_info(create_info_par),
    select_tables(select_tables_arg),
2846 2847
    alter_info(alter_info_arg),
    m_plock(NULL)
unknown's avatar
unknown committed
2848
    {}
2849
  int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
2850

2851
  int binlog_show_create_table(TABLE **tables, uint count, int errcode);
unknown's avatar
unknown committed
2852
  void store_values(List<Item> &values);
2853
  void send_error(uint errcode,const char *err);
unknown's avatar
unknown committed
2854 2855
  bool send_eof();
  void abort();
2856 2857
  virtual bool can_rollback_data() { return 1; }

2858
  // Needed for access from local class MY_HOOKS in prepare(), since thd is proteted.
2859 2860
  const THD *get_thd(void) { return thd; }
  const HA_CREATE_INFO *get_create_info() { return create_info; };
2861
  int prepare2(void) { return 0; }
unknown's avatar
unknown committed
2862 2863
};

2864

Sergei Golubchik's avatar
Sergei Golubchik committed
2865
#if defined(WITH_ARIA_STORAGE_ENGINE) && defined(USE_MARIA_FOR_TMP_TABLES)
2866 2867 2868
#include <maria.h>
#define ENGINE_COLUMNDEF MARIA_COLUMNDEF
#else
2869
#include <myisam.h>
2870 2871
#define ENGINE_COLUMNDEF MI_COLUMNDEF
#endif
2872

2873 2874
/*
  Param to create temporary tables when doing SELECT:s
unknown's avatar
unknown committed
2875 2876 2877
  NOTE
    This structure is copied using memcpy as a part of JOIN.
*/
2878 2879 2880

class TMP_TABLE_PARAM :public Sql_alloc
{
2881 2882 2883 2884 2885 2886
private:
  /* Prevent use of these (not safe because of lists and copy_field) */
  TMP_TABLE_PARAM(const TMP_TABLE_PARAM &);
  void operator=(TMP_TABLE_PARAM &);

public:
2887 2888 2889 2890
  List<Item> copy_funcs;
  List<Item> save_copy_funcs;
  Copy_field *copy_field, *copy_field_end;
  Copy_field *save_copy_field, *save_copy_field_end;
2891
  uchar	    *group_buff;
2892
  Item	    **items_to_copy;			/* Fields in tmp table */
2893
  ENGINE_COLUMNDEF *recinfo, *start_recinfo;
2894 2895
  KEY *keyinfo;
  ha_rows end_write_records;
2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921
  /**
    Number of normal fields in the query, including those referred to
    from aggregate functions. Hence, "SELECT `field1`,
    SUM(`field2`) from t1" sets this counter to 2.

    @see count_field_types
  */
  uint	field_count; 
  /**
    Number of fields in the query that have functions. Includes both
    aggregate functions (e.g., SUM) and non-aggregates (e.g., RAND).
    Also counts functions referred to from aggregate functions, i.e.,
    "SELECT SUM(RAND())" sets this counter to 2.

    @see count_field_types
  */
  uint  func_count;  
  /**
    Number of fields in the query that have aggregate functions. Note
    that the optimizer may choose to optimize away these fields by
    replacing them with constants, in which case sum_func_count will
    need to be updated.

    @see opt_sum_query, count_field_types
  */
  uint  sum_func_count;   
2922 2923 2924 2925
  uint  hidden_field_count;
  uint	group_parts,group_length,group_null_parts;
  uint	quick_group;
  bool  using_indirect_summary_function;
2926
  /* If >0 convert all blob fields to varchar(convert_blob_length) */
2927 2928
  uint  convert_blob_length;
  CHARSET_INFO *table_charset;
2929
  bool schema_table;
2930 2931 2932 2933 2934 2935 2936
  /*
    True if GROUP BY and its aggregate functions are already computed
    by a table access method (e.g. by loose index scan). In this case
    query execution should not perform aggregation and should treat
    aggregate functions as normal functions.
  */
  bool precomputed_group_by;
2937
  bool force_copy_fields;
2938 2939 2940 2941 2942 2943
  /*
    If TRUE, create_tmp_field called from create_tmp_table will convert
    all BIT fields to 64-bit longs. This is a workaround the limitation
    that MEMORY tables cannot index BIT columns.
  */
  bool bit_fields_as_long;
unknown's avatar
unknown committed
2944 2945 2946 2947 2948
  /*
    Whether to create or postpone actual creation of this temporary table.
    TRUE <=> create_tmp_table will create only the TABLE structure.
  */
  bool skip_create_table;
2949 2950

  TMP_TABLE_PARAM()
unknown's avatar
unknown committed
2951
    :copy_field(0), group_parts(0),
unknown's avatar
unknown committed
2952
     group_length(0), group_null_parts(0), convert_blob_length(0),
2953
     schema_table(0), precomputed_group_by(0), force_copy_fields(0),
unknown's avatar
unknown committed
2954
     bit_fields_as_long(0), skip_create_table(0)
2955 2956 2957 2958 2959
  {}
  ~TMP_TABLE_PARAM()
  {
    cleanup();
  }
2960
  void init(void);
2961 2962 2963 2964 2965
  inline void cleanup(void)
  {
    if (copy_field)				/* Fix for Intel compiler */
    {
      delete [] copy_field;
2966
      save_copy_field= copy_field= 0;
2967 2968 2969 2970
    }
  }
};

2971 2972
class select_union :public select_result_interceptor
{
2973
protected:
2974
  TMP_TABLE_PARAM tmp_table_param;
2975 2976
public:
  TABLE *table;
unknown's avatar
unknown committed
2977

2978
  select_union() :table(0) { tmp_table_param.init(); }
2979
  int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
unknown's avatar
unknown committed
2980 2981 2982
  bool send_data(List<Item> &items);
  bool send_eof();
  bool flush();
2983
  void cleanup();
2984 2985 2986
  virtual bool create_result_table(THD *thd, List<Item> *column_types,
                                   bool is_distinct, ulonglong options,
                                   const char *alias, bool bit_fields_as_long);
unknown's avatar
unknown committed
2987 2988
};

unknown's avatar
unknown committed
2989
/* Base subselect interface class */
2990
class select_subselect :public select_result_interceptor
2991
{
unknown's avatar
unknown committed
2992
protected:
2993 2994 2995
  Item_subselect *item;
public:
  select_subselect(Item_subselect *item);
unknown's avatar
unknown committed
2996
  bool send_data(List<Item> &items)=0;
2997 2998 2999
  bool send_eof() { return 0; };
};

unknown's avatar
unknown committed
3000
/* Single value subselect interface class */
unknown's avatar
unknown committed
3001
class select_singlerow_subselect :public select_subselect
unknown's avatar
unknown committed
3002 3003
{
public:
3004 3005 3006
  select_singlerow_subselect(Item_subselect *item_arg)
    :select_subselect(item_arg)
  {}
unknown's avatar
unknown committed
3007 3008 3009
  bool send_data(List<Item> &items);
};

3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045

/*
  This class specializes select_union to collect statistics about the
  data stored in the temp table. Currently the class collects statistcs
  about NULLs.
*/

class select_materialize_with_stats : public select_union
{
protected:
  class Column_statistics
  {
  public:
    /* Count of NULLs per column. */
    ha_rows null_count;
    /* The row number that contains the first NULL in a column. */
    ha_rows min_null_row;
    /* The row number that contains the last NULL in a column. */
    ha_rows max_null_row;
  };

  /* Array of statistics data per column. */
  Column_statistics* col_stat;

  /*
    The number of columns in the biggest sub-row that consists of only
    NULL values.
  */
  ha_rows max_nulls_in_row;
  /*
    Count of rows writtent to the temp table. This is redundant as it is
    already stored in handler::stats.records, however that one is relatively
    expensive to compute (given we need that for evry row).
  */
  ha_rows count_rows;

3046 3047 3048
protected:
  void reset();

3049 3050 3051 3052 3053 3054 3055
public:
  select_materialize_with_stats() {}
  virtual bool create_result_table(THD *thd, List<Item> *column_types,
                                   bool is_distinct, ulonglong options,
                                   const char *alias, bool bit_fields_as_long);
  bool init_result_table(ulonglong select_options);
  bool send_data(List<Item> &items);
3056
  void cleanup();
3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075
  ha_rows get_null_count_of_col(uint idx)
  {
    DBUG_ASSERT(idx < table->s->fields);
    return col_stat[idx].null_count;
  }
  ha_rows get_max_null_of_col(uint idx)
  {
    DBUG_ASSERT(idx < table->s->fields);
    return col_stat[idx].max_null_row;
  }
  ha_rows get_min_null_of_col(uint idx)
  {
    DBUG_ASSERT(idx < table->s->fields);
    return col_stat[idx].min_null_row;
  }
  ha_rows get_max_nulls_in_row() { return max_nulls_in_row; }
};


3076 3077 3078 3079 3080 3081 3082
/* used in independent ALL/ANY optimisation */
class select_max_min_finder_subselect :public select_subselect
{
  Item_cache *cache;
  bool (select_max_min_finder_subselect::*op)();
  bool fmax;
public:
3083 3084
  select_max_min_finder_subselect(Item_subselect *item_arg, bool mx)
    :select_subselect(item_arg), cache(0), fmax(mx)
3085
  {}
unknown's avatar
Merge  
unknown committed
3086
  void cleanup();
3087 3088 3089
  bool send_data(List<Item> &items);
  bool cmp_real();
  bool cmp_int();
unknown's avatar
Merge  
unknown committed
3090
  bool cmp_decimal();
3091 3092 3093
  bool cmp_str();
};

unknown's avatar
unknown committed
3094 3095 3096 3097
/* EXISTS subselect interface class */
class select_exists_subselect :public select_subselect
{
public:
3098 3099
  select_exists_subselect(Item_subselect *item_arg)
    :select_subselect(item_arg){}
unknown's avatar
unknown committed
3100 3101 3102
  bool send_data(List<Item> &items);
};

3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163



/*
  Optimizer and executor structure for the materialized semi-join info. This
  structure contains
   - The sj-materialization temporary table
   - Members needed to make index lookup or a full scan of the temptable.
*/
class SJ_MATERIALIZATION_INFO : public Sql_alloc
{
public:
  /* Optimal join sub-order */
  struct st_position *positions;

  uint tables; /* Number of tables in the sj-nest */

  /* Expected #rows in the materialized table */
  double rows;

  /* 
    Cost to materialize - execute the sub-join and write rows into temp.table
  */
  COST_VECT materialization_cost;

  /* Cost to make one lookup in the temptable */
  COST_VECT lookup_cost;
  
  /* Cost of scanning the materialized table */
  COST_VECT scan_cost;

  /* --- Execution structures ---------- */
  
  /*
    TRUE <=> This structure is used for execution. We don't necessarily pick
    sj-materialization, so some of SJ_MATERIALIZATION_INFO structures are not
    used by materialization
  */
  bool is_used;
  
  bool materialized; /* TRUE <=> materialization already performed */
  /*
    TRUE  - the temptable is read with full scan
    FALSE - we use the temptable for index lookups
  */
  bool is_sj_scan; 
  
  /* The temptable and its related info */
  TMP_TABLE_PARAM sjm_table_param;
  List<Item> sjm_table_cols;
  TABLE *table;

  /* Structure used to make index lookups */
  struct st_table_ref *tab_ref;
  Item *in_equality; /* See create_subq_in_equalities() */

  Item *join_cond; /* See comments in make_join_select() */
  Copy_field *copy_field; /* Needed for SJ_Materialization scan */
};


unknown's avatar
unknown committed
3164 3165 3166 3167 3168 3169
/* Structs used when sorting */

typedef struct st_sort_field {
  Field *field;				/* Field to sort */
  Item	*item;				/* Item if not sorting fields */
  uint	 length;			/* Length of sort field */
3170
  uint   suffix_length;                 /* Length suffix (0-4) */
unknown's avatar
unknown committed
3171
  Item_result result_type;		/* Type of item */
3172 3173
  bool reverse;				/* if descending sort */
  bool need_strxnfrm;			/* If we have to use strxnfrm() */
unknown's avatar
unknown committed
3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186
} SORT_FIELD;


typedef struct st_sort_buffer {
  uint index;					/* 0 or 1 */
  uint sort_orders;
  uint change_pos;				/* If sort-fields changed */
  char **buff;
  SORT_FIELD *sortorder;
} SORT_BUFFER;

/* Structure for db & table in sql_yacc */

3187 3188
class Table_ident :public Sql_alloc
{
unknown's avatar
unknown committed
3189
public:
unknown's avatar
unknown committed
3190 3191
  LEX_STRING db;
  LEX_STRING table;
unknown's avatar
unknown committed
3192
  SELECT_LEX_UNIT *sel;
unknown's avatar
unknown committed
3193 3194
  inline Table_ident(THD *thd, LEX_STRING db_arg, LEX_STRING table_arg,
		     bool force)
unknown's avatar
unknown committed
3195
    :table(table_arg), sel((SELECT_LEX_UNIT *)0)
unknown's avatar
unknown committed
3196
  {
unknown's avatar
unknown committed
3197
    if (!force && (thd->client_capabilities & CLIENT_NO_SCHEMA))
unknown's avatar
unknown committed
3198 3199 3200 3201
      db.str=0;
    else
      db= db_arg;
  }
3202
  inline Table_ident(LEX_STRING table_arg)
unknown's avatar
unknown committed
3203 3204 3205 3206
    :table(table_arg), sel((SELECT_LEX_UNIT *)0)
  {
    db.str=0;
  }
3207 3208 3209 3210 3211 3212
  /*
    This constructor is used only for the case when we create a derived
    table. A derived table has no name and doesn't belong to any database.
    Later, if there was an alias specified for the table, it will be set
    by add_table_to_list.
  */
unknown's avatar
foo1  
unknown committed
3213
  inline Table_ident(SELECT_LEX_UNIT *s) : sel(s)
unknown's avatar
unknown committed
3214
  {
unknown's avatar
unknown committed
3215
    /* We must have a table name here as this is used with add_table_to_list */
3216 3217 3218 3219
    db.str= empty_c_string;                    /* a subject to casedn_str */
    db.length= 0;
    table.str= internal_table_name;
    table.length=1;
unknown's avatar
unknown committed
3220
  }
3221
  bool is_derived_table() const { return test(sel); }
unknown's avatar
unknown committed
3222
  inline void change_db(char *db_name)
unknown's avatar
unknown committed
3223 3224 3225
  {
    db.str= db_name; db.length= (uint) strlen(db_name);
  }
unknown's avatar
unknown committed
3226 3227 3228 3229 3230 3231
};

// this is needed for user_vars hash
class user_var_entry
{
 public:
3232
  user_var_entry() {}                         /* Remove gcc warning */
unknown's avatar
unknown committed
3233 3234
  LEX_STRING name;
  char *value;
3235 3236
  ulong length;
  query_id_t update_query_id, used_query_id;
unknown's avatar
unknown committed
3237
  Item_result type;
3238
  bool unsigned_flag;
3239

3240 3241 3242 3243
  double val_real(bool *null_value);
  longlong val_int(bool *null_value) const;
  String *val_str(bool *null_value, String *str, uint decimals);
  my_decimal *val_decimal(bool *null_value, my_decimal *result);
3244
  DTCollation collation;
unknown's avatar
unknown committed
3245 3246
};

3247
/*
3248
   Unique -- class for unique (removing of duplicates).
3249 3250 3251 3252 3253
   Puts all values to the TREE. If the tree becomes too big,
   it's dumped to the file. User can request sorted values, or
   just iterate through them. In the last case tree merging is performed in
   memory simultaneously with iteration, so it should be ~2-3x faster.
 */
3254 3255 3256 3257

class Unique :public Sql_alloc
{
  DYNAMIC_ARRAY file_ptrs;
3258 3259
  ulong max_elements;
  ulonglong max_in_memory_size;
3260 3261
  IO_CACHE file;
  TREE tree;
3262
  uchar *record_pointers;
3263
  bool flush();
3264
  uint size;
3265 3266 3267

public:
  ulong elements;
3268
  Unique(qsort_cmp2 comp_func, void *comp_func_fixed_arg,
3269
	 uint size_arg, ulonglong max_in_memory_size_arg);
3270
  ~Unique();
3271
  ulong elements_in_tree() { return tree.elements_in_tree; }
3272
  inline bool unique_add(void *ptr)
3273
  {
unknown's avatar
Merge  
unknown committed
3274
    DBUG_ENTER("unique_add");
unknown's avatar
unknown committed
3275
    DBUG_PRINT("info", ("tree %u - %lu", tree.elements_in_tree, max_elements));
3276
    if (tree.elements_in_tree > max_elements && flush())
unknown's avatar
Merge  
unknown committed
3277 3278
      DBUG_RETURN(1);
    DBUG_RETURN(!tree_insert(&tree, ptr, 0, tree.custom_arg));
3279 3280 3281
  }

  bool get(TABLE *table);
3282
  static double get_use_cost(uint *buffer, uint nkeys, uint key_size,
3283
                             ulonglong max_in_memory_size);
3284
  inline static int get_cost_calc_buff_size(ulong nkeys, uint key_size,
3285
                                            ulonglong max_in_memory_size)
3286
  {
3287
    register ulonglong max_elems_in_tree=
3288
      max_in_memory_size / ALIGN_SIZE(sizeof(TREE_ELEMENT)+key_size);
3289
    return (int) (sizeof(uint)*(1 + nkeys/max_elems_in_tree));
3290 3291
  }

3292 3293 3294
  void reset();
  bool walk(tree_walk_action action, void *walk_action_arg);

3295 3296 3297
  uint get_size() const { return size; }
  ulonglong get_max_in_memory_size() const { return max_in_memory_size; }

3298 3299
  friend int unique_write_to_file(uchar* key, element_count count, Unique *unique);
  friend int unique_write_to_ptrs(uchar* key, element_count count, Unique *unique);
3300
};
3301

unknown's avatar
unknown committed
3302

3303
class multi_delete :public select_result_interceptor
unknown's avatar
unknown committed
3304 3305
{
  TABLE_LIST *delete_tables, *table_being_deleted;
unknown's avatar
unknown committed
3306
  Unique **tempfiles;
3307
  ha_rows deleted, found;
unknown's avatar
unknown committed
3308 3309
  uint num_of_tables;
  int error;
3310 3311 3312 3313 3314 3315
  bool do_delete;
  /* True if at least one table we delete from is transactional */
  bool transactional_tables;
  /* True if at least one table we delete from is not transactional */
  bool normal_tables;
  bool delete_while_scanning;
3316 3317 3318 3319 3320
  /*
     error handling (rollback and binlogging) can happen in send_eof()
     so that afterward send_error() needs to find out that.
  */
  bool error_handled;
3321

unknown's avatar
unknown committed
3322
public:
3323
  multi_delete(TABLE_LIST *dt, uint num_of_tables);
unknown's avatar
unknown committed
3324 3325 3326 3327 3328
  ~multi_delete();
  int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
  bool send_data(List<Item> &items);
  bool initialize_tables (JOIN *join);
  void send_error(uint errcode,const char *err);
3329 3330
  int do_deletes();
  int do_table_deletes(TABLE *table, bool ignore);
unknown's avatar
unknown committed
3331
  bool send_eof();
3332
  virtual void abort();
unknown's avatar
unknown committed
3333 3334
};

3335

3336
class multi_update :public select_result_interceptor
unknown's avatar
unknown committed
3337
{
3338 3339 3340
  TABLE_LIST *all_tables; /* query/update command tables */
  TABLE_LIST *leaves;     /* list of leves of join table tree */
  TABLE_LIST *update_tables, *table_being_updated;
unknown's avatar
unknown committed
3341
  TABLE **tmp_tables, *main_table, *table_to_update;
unknown's avatar
unknown committed
3342 3343 3344 3345 3346
  TMP_TABLE_PARAM *tmp_table_param;
  ha_rows updated, found;
  List <Item> *fields, *values;
  List <Item> **fields_for_table, **values_for_table;
  uint table_count;
unknown's avatar
unknown committed
3347 3348
  /*
   List of tables referenced in the CHECK OPTION condition of
3349
   the updated view excluding the updated table.
unknown's avatar
unknown committed
3350 3351
  */
  List <TABLE> unupdated_check_opt_tables;
unknown's avatar
unknown committed
3352 3353
  Copy_field *copy_field;
  enum enum_duplicates handle_duplicates;
3354 3355 3356 3357
  bool do_update, trans_safe;
  /* True if the update operation has made a change in a transactional table */
  bool transactional_tables;
  bool ignore;
3358 3359 3360 3361 3362
  /* 
     error handling (rollback and binlogging) can happen in send_eof()
     so that afterward send_error() needs to find out that.
  */
  bool error_handled;
unknown's avatar
unknown committed
3363 3364

public:
3365
  multi_update(TABLE_LIST *ut, TABLE_LIST *leaves_list,
3366
	       List<Item> *fields, List<Item> *values,
3367
	       enum_duplicates handle_duplicates, bool ignore);
unknown's avatar
unknown committed
3368
  ~multi_update();
unknown's avatar
unknown committed
3369
  int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
unknown's avatar
unknown committed
3370 3371 3372
  bool send_data(List<Item> &items);
  bool initialize_tables (JOIN *join);
  void send_error(uint errcode,const char *err);
3373
  int  do_updates();
unknown's avatar
unknown committed
3374
  bool send_eof();
3375
  virtual void abort();
unknown's avatar
unknown committed
3376
};
3377

unknown's avatar
unknown committed
3378 3379 3380
class my_var : public Sql_alloc  {
public:
  LEX_STRING s;
unknown's avatar
unknown committed
3381
#ifndef DBUG_OFF
3382 3383 3384 3385
  /*
    Routine to which this Item_splocal belongs. Used for checking if correct
    runtime context is used for variable handling.
  */
3386
  sp_head *sp;
3387
#endif
unknown's avatar
unknown committed
3388 3389
  bool local;
  uint offset;
3390 3391 3392 3393
  enum_field_types type;
  my_var (LEX_STRING& j, bool i, uint o, enum_field_types t)
    :s(j), local(i), offset(o), type(t)
  {}
unknown's avatar
unknown committed
3394 3395
  ~my_var() {}
};
3396

3397
class select_dumpvar :public select_result_interceptor {
unknown's avatar
unknown committed
3398 3399
  ha_rows row_count;
public:
unknown's avatar
unknown committed
3400
  List<my_var> var_list;
3401
  select_dumpvar()  { var_list.empty(); row_count= 0;}
3402 3403 3404 3405
  /**
     Creates a select_dumpvar to represent INTO <variable> with a defined 
     level of subquery nesting.
   */
3406
  select_dumpvar(int nest_level_arg)
3407 3408 3409 3410 3411
  {
    var_list.empty();
    row_count= 0;
    nest_level= nest_level_arg;
  }
unknown's avatar
unknown committed
3412
  ~select_dumpvar() {}
3413
  int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
unknown's avatar
unknown committed
3414 3415
  bool send_data(List<Item> &items);
  bool send_eof();
3416
  virtual bool check_simple_select() const;
3417
  void cleanup();
unknown's avatar
unknown committed
3418
};
3419

3420 3421 3422 3423 3424 3425
/* Bits in sql_command_flags */

#define CF_CHANGES_DATA		1
#define CF_HAS_ROW_COUNT	2
#define CF_STATUS_COMMAND	4
#define CF_SHOW_TABLE_COMMAND	8
3426
#define CF_WRITE_LOGS_COMMAND  16
3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439
/**
  Must be set for SQL statements that may contain
  Item expressions and/or use joins and tables.
  Indicates that the parse tree of such statement may
  contain rule-based optimizations that depend on metadata
  (i.e. number of columns in a table), and consequently
  that the statement must be re-prepared whenever
  referenced metadata changes. Must not be set for
  statements that themselves change metadata, e.g. RENAME,
  ALTER and other DDL, since otherwise will trigger constant
  reprepare. Consequently, complex item expressions and
  joins are currently prohibited in these statements.
*/
unknown's avatar
unknown committed
3440
#define CF_REEXECUTION_FRAGILE 32
3441

3442 3443 3444
/* Functions in sql_class.cc */

void add_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var);
3445

3446 3447
void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var,
                        STATUS_VAR *dec_var);
3448 3449
void mark_transaction_to_rollback(THD *thd, bool all);

3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595
/*
  inline handler methods that need to know TABLE and THD structures
*/
inline void handler::increment_statistics(ulong SSV::*offset) const
{
  status_var_increment(table->in_use->status_var.*offset);
}

inline void handler::decrement_statistics(ulong SSV::*offset) const
{
  status_var_decrement(table->in_use->status_var.*offset);
}

inline int handler::ha_index_read_map(uchar * buf, const uchar * key,
                                      key_part_map keypart_map,
                                      enum ha_rkey_function find_flag)
{
  DBUG_ASSERT(inited==INDEX);
  increment_statistics(&SSV::ha_read_key_count);
  int error= index_read_map(buf, key, keypart_map, find_flag);
  if (!error)
    update_index_statistics();
  table->status=error ? STATUS_NOT_FOUND: 0;
  return error;
}

inline int handler::ha_index_read_idx_map(uchar * buf, uint index,
                                          const uchar * key,
                                          key_part_map keypart_map,
                                          enum ha_rkey_function find_flag)
{
  increment_statistics(&SSV::ha_read_key_count);
  int error= index_read_idx_map(buf, index, key, keypart_map, find_flag);
  if (!error)
  {
    rows_read++;
    index_rows_read[index]++;
  }
  table->status=error ? STATUS_NOT_FOUND: 0;
  return error;
}

inline int handler::ha_index_next(uchar * buf)
{
  DBUG_ASSERT(inited==INDEX);
  increment_statistics(&SSV::ha_read_next_count);
  int error= index_next(buf);
  if (!error)
    update_index_statistics();
  table->status=error ? STATUS_NOT_FOUND: 0;
  return error;
}

inline int handler::ha_index_prev(uchar * buf)
{
  DBUG_ASSERT(inited==INDEX);
  increment_statistics(&SSV::ha_read_prev_count);
  int error= index_prev(buf);
  if (!error)
    update_index_statistics();
  table->status=error ? STATUS_NOT_FOUND: 0;
  return error;
}

inline int handler::ha_index_first(uchar * buf)
{
  DBUG_ASSERT(inited==INDEX);
  increment_statistics(&SSV::ha_read_first_count);
  int error= index_first(buf);
  if (!error)
    update_index_statistics();
  table->status=error ? STATUS_NOT_FOUND: 0;
  return error;
}

inline int handler::ha_index_last(uchar * buf)
{
  DBUG_ASSERT(inited==INDEX);
  increment_statistics(&SSV::ha_read_last_count);
  int error= index_last(buf);
  if (!error)
    update_index_statistics();
  table->status=error ? STATUS_NOT_FOUND: 0;
  return error;
}

inline int handler::ha_index_next_same(uchar *buf, const uchar *key,
                                       uint keylen)
{
  DBUG_ASSERT(inited==INDEX);
  increment_statistics(&SSV::ha_read_next_count);
  int error= index_next_same(buf, key, keylen);
  if (!error)
    update_index_statistics();
  table->status=error ? STATUS_NOT_FOUND: 0;
  return error;
}

inline int handler::ha_ft_read(uchar *buf)
{
  int error= ft_read(buf);
  if (!error)
    rows_read++;
  table->status=error ? STATUS_NOT_FOUND: 0;
  return error;
}

inline int handler::ha_rnd_next(uchar *buf)
{
  increment_statistics(&SSV::ha_read_rnd_next_count);
  int error= rnd_next(buf);
  if (!error)
    rows_read++;
  table->status=error ? STATUS_NOT_FOUND: 0;
  return error;
}

inline int handler::ha_rnd_pos(uchar *buf, uchar *pos)
{
  increment_statistics(&SSV::ha_read_rnd_count);
  int error= rnd_pos(buf, pos);
  if (!error)
    rows_read++;
  table->status=error ? STATUS_NOT_FOUND: 0;
  return error;
}

inline int handler::ha_rnd_pos_by_record(uchar *buf)
{
  int error= rnd_pos_by_record(buf);
  if (!error)
    rows_read++;
  table->status=error ? STATUS_NOT_FOUND: 0;
  return error;
}

inline int handler::ha_read_first_row(uchar *buf, uint primary_key)
{
  int error= read_first_row(buf, primary_key);
  if (!error)
    rows_read++;
  table->status=error ? STATUS_NOT_FOUND: 0;
  return error;
}


3596
#endif /* MYSQL_SERVER */