sql_class.h 33.1 KB
Newer Older
unknown's avatar
unknown committed
1
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
unknown's avatar
unknown committed
2

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

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

unknown's avatar
unknown committed
13 14 15 16 17 18 19 20 21 22 23
   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 */

#ifdef __GNUC__
#pragma interface			/* gcc class implementation */
#endif

24 25
// TODO: create log.h and move all the log header stuff there

unknown's avatar
unknown committed
26 27
class Query_log_event;
class Load_log_event;
28
class Slave_log_event;
unknown's avatar
unknown committed
29

30
enum enum_enable_or_disable { LEAVE_AS_IS, ENABLE, DISABLE };
31
enum enum_ha_read_modes { RFIRST, RNEXT, RPREV, RLAST, RKEY };
32
enum enum_duplicates { DUP_ERROR, DUP_REPLACE, DUP_IGNORE, DUP_UPDATE };
33
enum enum_log_type { LOG_CLOSED, LOG_TO_BE_OPENED, LOG_NORMAL, LOG_NEW, LOG_BIN};
34 35
enum enum_delay_key_write { DELAY_KEY_WRITE_NONE, DELAY_KEY_WRITE_ON,
			    DELAY_KEY_WRITE_ALL };
unknown's avatar
unknown committed
36

37 38 39
enum enum_check_fields { CHECK_FIELD_IGNORE, CHECK_FIELD_WARN,
			 CHECK_FIELD_ERROR_FOR_NULL };

unknown's avatar
unknown committed
40 41
extern char internal_table_name[2];

42
/* log info errors */
unknown's avatar
unknown committed
43 44 45 46
#define LOG_INFO_EOF -1
#define LOG_INFO_IO  -2
#define LOG_INFO_INVALID -3
#define LOG_INFO_SEEK -4
unknown's avatar
unknown committed
47 48 49
#define LOG_INFO_MEM -6
#define LOG_INFO_FATAL -7
#define LOG_INFO_IN_USE -8
unknown's avatar
unknown committed
50

51 52 53 54 55
/* bitmap to SQL_LOG::close() */
#define LOG_CLOSE_INDEX		1
#define LOG_CLOSE_TO_BE_OPENED	2
#define LOG_CLOSE_STOP_EVENT	4

56 57
struct st_relay_log_info;

unknown's avatar
unknown committed
58 59 60
typedef struct st_log_info
{
  char log_file_name[FN_REFLEN];
61
  my_off_t index_file_offset, index_file_start_offset;
unknown's avatar
unknown committed
62 63 64
  my_off_t pos;
  bool fatal; // if the purge happens to give us a negative offset
  pthread_mutex_t lock;
65
  st_log_info():fatal(0) { pthread_mutex_init(&lock, MY_MUTEX_INIT_FAST);}
unknown's avatar
unknown committed
66
  ~st_log_info() { pthread_mutex_destroy(&lock);}
unknown's avatar
unknown committed
67 68
} LOG_INFO;

unknown's avatar
unknown committed
69 70 71 72 73 74 75 76 77
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;

unknown's avatar
unknown committed
78
class Log_event;
unknown's avatar
unknown committed
79

unknown's avatar
unknown committed
80 81
class MYSQL_LOG
 {
unknown's avatar
unknown committed
82
 private:
unknown's avatar
unknown committed
83
  /* LOCK_log and LOCK_index are inited by init_pthread_objects() */
unknown's avatar
unknown committed
84
  pthread_mutex_t LOCK_log, LOCK_index;
unknown's avatar
unknown committed
85 86
  pthread_cond_t update_cond;
  ulonglong bytes_written;
unknown's avatar
unknown committed
87
  time_t last_time,query_start;
88
  IO_CACHE log_file;
89
  IO_CACHE index_file;
unknown's avatar
unknown committed
90 91 92
  char *name;
  char time_buff[20],db[NAME_LEN+1];
  char log_file_name[FN_REFLEN],index_file_name[FN_REFLEN];
unknown's avatar
unknown committed
93 94 95
  // current file sequence number for load data infile binary logging
  uint file_id;
  uint open_count;				// For replication
unknown's avatar
unknown committed
96 97
  volatile enum_log_type log_type;
  enum cache_type io_cache_type;
unknown's avatar
unknown committed
98
  bool write_error, inited;
99
  bool need_start_event;
unknown's avatar
unknown committed
100
  bool no_auto_events;				// For relay binlog
101 102 103 104 105 106 107 108 109 110 111
  /* 
     The max size before rotation (usable only if log_type == LOG_BIN: binary
     logs and relay logs).
     For a binlog, max_size should be max_binlog_size.
     For a relay log, it should be max_relay_log_size if this is non-zero,
     max_binlog_size otherwise.
     max_size is set in init(), and dynamically changed (when one does SET
     GLOBAL MAX_BINLOG_SIZE|MAX_RELAY_LOG_SIZE) by fix_max_binlog_size and
     fix_max_relay_log_size). 
  */
  ulong max_size;
112 113
  friend class Log_event;

unknown's avatar
unknown committed
114 115 116
public:
  MYSQL_LOG();
  ~MYSQL_LOG();
unknown's avatar
unknown committed
117
  void reset_bytes_written()
unknown's avatar
unknown committed
118 119 120
  {
    bytes_written = 0;
  }
unknown's avatar
unknown committed
121
  void harvest_bytes_written(ulonglong* counter)
unknown's avatar
unknown committed
122
  {
unknown's avatar
unknown committed
123
#ifndef DBUG_OFF
unknown's avatar
unknown committed
124
    char buf1[22],buf2[22];
unknown's avatar
unknown committed
125
#endif	
unknown's avatar
unknown committed
126 127 128 129 130 131 132
    DBUG_ENTER("harvest_bytes_written");
    (*counter)+=bytes_written;
    DBUG_PRINT("info",("counter: %s  bytes_written: %s", llstr(*counter,buf1),
		       llstr(bytes_written,buf2)));
    bytes_written=0;
    DBUG_VOID_RETURN;
  }
133
  void set_max_size(ulong max_size_arg);
134
  void signal_update() { pthread_cond_broadcast(&update_cond);}
135
  void wait_for_update(THD* thd, bool master_or_slave);
136 137
  void set_need_start_event() { need_start_event = 1; }
  void init(enum_log_type log_type_arg,
138 139
	    enum cache_type io_cache_type_arg,
	    bool no_auto_events_arg, ulong max_size);
unknown's avatar
unknown committed
140
  void init_pthread_objects();
unknown's avatar
unknown committed
141
  void cleanup();
142 143 144
  bool open(const char *log_name,enum_log_type log_type,
	    const char *new_name, const char *index_file_name_arg,
	    enum cache_type io_cache_type_arg,
145
	    bool no_auto_events_arg, ulong max_size);
146
  void new_file(bool need_lock= 1);
147 148
  bool write(THD *thd, enum enum_server_command command,
	     const char *format,...);
149
  bool write(THD *thd, const char *query, uint query_length,
150
	     time_t query_start=0);
151
  bool write(Log_event* event_info); // binary log write
unknown's avatar
unknown committed
152
  bool write(THD *thd, IO_CACHE *cache, bool commit_or_rollback);
153

unknown's avatar
unknown committed
154 155 156 157
  /*
    v stands for vector
    invoked as appendv(buf1,len1,buf2,len2,...,bufn,lenn,0)
  */
158
  bool appendv(const char* buf,uint len,...);
159
  bool append(Log_event* ev);
160
  
unknown's avatar
unknown committed
161 162 163
  int generate_new_name(char *new_name,const char *old_name);
  void make_log_name(char* buf, const char* log_ident);
  bool is_active(const char* log_file_name);
164 165 166 167 168 169
  int update_log_index(LOG_INFO* linfo, bool need_update_threads);
  int purge_logs(const char *to_log, bool included, 
                 bool need_mutex, bool need_update_threads,
                 ulonglong *decrease_log_space);
  int purge_logs_before_date(time_t purge_time);
  int purge_first_log(struct st_relay_log_info* rli, bool included); 
170
  bool reset_logs(THD* thd);
171
  void close(uint exiting);
unknown's avatar
unknown committed
172 173

  // iterating through the log index file
174
  int find_log_pos(LOG_INFO* linfo, const char* log_name,
175 176
		   bool need_mutex);
  int find_next_log(LOG_INFO* linfo, bool need_mutex);
unknown's avatar
unknown committed
177
  int get_current_log(LOG_INFO* linfo);
unknown's avatar
unknown committed
178
  uint next_file_id();
179
  inline bool is_open() { return log_type != LOG_CLOSED; }
unknown's avatar
unknown committed
180 181 182 183 184 185 186
  inline char* get_index_fname() { return index_file_name;}
  inline char* get_log_fname() { return log_file_name; }
  inline pthread_mutex_t* get_log_lock() { return &LOCK_log; }
  inline IO_CACHE* get_log_file() { return &log_file; }

  inline void lock_index() { pthread_mutex_lock(&LOCK_index);}
  inline void unlock_index() { pthread_mutex_unlock(&LOCK_index);}
187
  inline IO_CACHE *get_index_file() { return &index_file;}
unknown's avatar
unknown committed
188
  inline uint32 get_open_count() { return open_count; }
unknown's avatar
unknown committed
189 190 191 192 193 194 195 196 197
};

/* character conversion tables */


typedef struct st_copy_info {
  ha_rows records;
  ha_rows deleted;
  ha_rows copied;
198
  ha_rows error_count;
unknown's avatar
unknown committed
199
  enum enum_duplicates handle_duplicates;
200
  int escape_char, last_errno;
201 202 203
/* for INSERT ... UPDATE */
  List<Item> *update_fields;
  List<Item> *update_values;
unknown's avatar
unknown committed
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
} COPY_INFO;


class key_part_spec :public Sql_alloc {
public:
  const char *field_name;
  uint length;
  key_part_spec(const char *name,uint len=0) :field_name(name), length(len) {}
};


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) {}
};


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) {}
};


class Key :public Sql_alloc {
public:
236
  enum Keytype { PRIMARY, UNIQUE, MULTIPLE, FULLTEXT, SPATIAL, FOREIGN_KEY};
unknown's avatar
unknown committed
237
  enum Keytype type;
238
  enum ha_key_alg algorithm;
unknown's avatar
unknown committed
239
  List<key_part_spec> columns;
240
  const char *name;
unknown's avatar
unknown committed
241

242 243 244
  Key(enum Keytype type_par, const char *name_arg, enum ha_key_alg alg_par,
      List<key_part_spec> &cols)
    :type(type_par), algorithm(alg_par), columns(cols), name(name_arg)
245
  {}
unknown's avatar
unknown committed
246 247 248
  ~Key() {}
};

249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269
class Table_ident;

class foreign_key: public Key {
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;
  List<key_part_spec> ref_columns;
  uint delete_opt, update_opt, match_opt;
  foreign_key(const char *name_arg, List<key_part_spec> &cols,
	      Table_ident *table,   List<key_part_spec> &ref_cols,
	      uint delete_opt_arg, uint update_opt_arg, uint match_opt_arg)
    :Key(FOREIGN_KEY, name_arg, HA_KEY_ALG_UNDEF, cols),
    ref_table(table), ref_columns(cols),
    delete_opt(delete_opt_arg), update_opt(update_opt_arg),
    match_opt(match_opt_arg)
  {}
};
unknown's avatar
unknown committed
270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288

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 */

289 290
/* Needed to be able to have an I_List of char* strings in mysqld.cc. */

unknown's avatar
unknown committed
291 292 293 294 295 296 297 298
class i_string: public ilink
{
public:
  char* ptr;
  i_string():ptr(0) { }
  i_string(char* s) : ptr(s) {}
};

299
/* needed for linked list of two strings for replicate-rewrite-db */
unknown's avatar
unknown committed
300 301 302 303 304 305
class i_string_pair: public ilink
{
public:
  char* key;
  char* val;
  i_string_pair():key(0),val(0) { }
unknown's avatar
unknown committed
306
  i_string_pair(char* key_arg, char* val_arg) : key(key_arg),val(val_arg) {}
unknown's avatar
unknown committed
307 308 309
};


310
class MYSQL_ERROR: public Sql_alloc
unknown's avatar
unknown committed
311 312
{
public:
313 314 315
  enum enum_warning_level
  { WARN_LEVEL_NOTE, WARN_LEVEL_WARN, WARN_LEVEL_ERROR, WARN_LEVEL_END};

unknown's avatar
unknown committed
316
  uint code;
317 318
  enum_warning_level level;
  char *msg;
unknown's avatar
unknown committed
319
  
320
  MYSQL_ERROR(THD *thd, uint code_arg, enum_warning_level level_arg,
321 322
	      const char *msg_arg)
    :code(code_arg), level(level_arg)
unknown's avatar
unknown committed
323
  {
unknown's avatar
SCRUM  
unknown committed
324
    if (msg_arg)
325
      set_msg(thd, msg_arg);
unknown's avatar
unknown committed
326
  }
327
  void set_msg(THD *thd, const char *msg_arg);
unknown's avatar
unknown committed
328
};
unknown's avatar
unknown committed
329

330 331 332 333 334 335

/* This is a struct as it's allocated in tree_insert */

typedef struct st_prep_stmt
{
  THD *thd;
336
  LEX  lex; 
unknown's avatar
unknown committed
337
  Item_param **param;
338 339
  Item *free_list;
  MEM_ROOT mem_root;
340
  String *query;
341 342 343 344
  ulong stmt_id;
  uint param_count;
  uint last_errno;
  char last_error[MYSQL_ERRMSG_SIZE];
unknown's avatar
unknown committed
345
  bool error_in_prepare, long_data_used;
346
  bool log_full_query;
unknown's avatar
unknown committed
347
#ifndef EMBEDDED_LIBRARY
348
  bool (*setup_params)(st_prep_stmt *stmt, uchar *pos, uchar *read_pos);
unknown's avatar
unknown committed
349 350 351
#else
  bool (*setup_params_data)(st_prep_stmt *stmt);
#endif
352 353 354
} PREP_STMT;


unknown's avatar
unknown committed
355
class delayed_insert;
unknown's avatar
unknown committed
356
class select_result;
unknown's avatar
unknown committed
357

358 359 360 361 362
#define THD_SENTRY_MAGIC 0xfeedd1ff
#define THD_SENTRY_GONE  0xdeadbeef

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

363 364
struct system_variables
{
unknown's avatar
unknown committed
365 366
  ulonglong myisam_max_extra_sort_file_size;
  ulonglong myisam_max_sort_file_size;
367 368
  ha_rows select_limit;
  ha_rows max_join_size;
unknown's avatar
unknown committed
369
  ulong bulk_insert_buff_size;
370 371
  ulong join_buff_size;
  ulong long_query_time;
unknown's avatar
unknown committed
372
  ulong max_allowed_packet;
373
  ulong max_error_count;
374
  ulong max_heap_table_size;
unknown's avatar
unknown committed
375
  ulong max_length_for_sort_data;
376 377
  ulong max_prep_stmt_count;
  ulong max_sort_length;
378
  ulong max_tmp_tables;
379
  ulong myisam_repair_threads;
unknown's avatar
unknown committed
380 381
  ulong myisam_sort_buff_size;
  ulong net_buffer_length;
382
  ulong net_interactive_timeout;
unknown's avatar
unknown committed
383
  ulong net_read_timeout;
384
  ulong net_retry_count;
385
  ulong net_wait_timeout;
unknown's avatar
unknown committed
386
  ulong net_write_timeout;
unknown's avatar
unknown committed
387
  ulong preload_buff_size;
unknown's avatar
unknown committed
388 389 390
  ulong query_cache_type;
  ulong read_buff_size;
  ulong read_rnd_buff_size;
391
  ulong sortbuff_size;
392
  ulong table_type;
393
  ulong tmp_table_size;
unknown's avatar
unknown committed
394
  ulong tx_isolation;
395
  /* Determines which non-standard SQL behaviour should be enabled */
396
  ulong sql_mode;
unknown's avatar
unknown committed
397
  ulong default_week_format;
398
  ulong max_seeks_for_key;
399 400 401 402 403
  ulong range_alloc_block_size;
  ulong query_alloc_block_size;
  ulong query_prealloc_size;
  ulong trans_alloc_block_size;
  ulong trans_prealloc_size;
404
  ulong group_concat_max_len;
unknown's avatar
unknown committed
405 406 407 408 409 410
  /*
    In slave thread we need to know in behalf of which
    thread the query is being run to replicate temp tables properly
  */
  ulong pseudo_thread_id;

unknown's avatar
unknown committed
411
  my_bool log_warnings;
unknown's avatar
unknown committed
412 413
  my_bool low_priority_updates;
  my_bool new_mode;
414
  my_bool old_passwords;
415
  
416
  /* Only charset part of these variables is sensible */
417 418
  CHARSET_INFO 	*character_set_client;
  CHARSET_INFO  *character_set_results;
419 420 421 422
  
  /* Both charset and collation parts of these variables are important */
  CHARSET_INFO	*collation_server;
  CHARSET_INFO	*collation_database;
unknown's avatar
unknown committed
423
  CHARSET_INFO  *collation_connection;
424 425 426 427 428

  /* DATE, DATETIME and TIME formats */
  DATE_TIME_FORMAT *date_format;
  DATE_TIME_FORMAT *datetime_format;
  DATE_TIME_FORMAT *time_format;
unknown's avatar
unknown committed
429 430
};

431
void free_tmp_table(THD *thd, TABLE *entry);
unknown's avatar
unknown committed
432 433 434 435
/*
  For each client connection we create a separate thread with THD serving as
  a thread/connection descriptor
*/
436

unknown's avatar
unknown committed
437 438
class THD :public ilink
{
unknown's avatar
unknown committed
439
public:
440 441
#ifdef EMBEDDED_LIBRARY
  struct st_mysql  *mysql;
unknown's avatar
SCRUM  
unknown committed
442 443 444
  struct st_mysql_data *data;
  unsigned long	 client_stmt_id;
  unsigned long  client_param_count;
unknown's avatar
unknown committed
445
  struct st_mysql_bind *client_params;
unknown's avatar
unknown committed
446 447
  char *extra_data;
  ulong extra_length;
448
#endif
unknown's avatar
unknown committed
449 450 451
  NET	  net;				// client connection descriptor
  LEX	  lex;				// parse tree descriptor
  MEM_ROOT mem_root;			// 1 command-life memory pool
unknown's avatar
unknown committed
452
  MEM_ROOT con_root;                    // connection-life memory
453
  MEM_ROOT warn_root;			// For warnings and errors
454 455 456
  Protocol *protocol;			// Current protocol
  Protocol_simple protocol_simple;	// Normal protocol
  Protocol_prep protocol_prep;		// Binary protocol
unknown's avatar
unknown committed
457
  HASH    user_vars;			// hash for user variables
458
  TREE	  prepared_statements;
unknown's avatar
unknown committed
459 460 461 462
  String  packet;			// dynamic buffer for network I/O
  struct  sockaddr_in remote;		// client socket address
  struct  rand_struct rand;		// used for authentication
  struct  system_variables variables;	// Changeable local variables
463 464
  pthread_mutex_t LOCK_delete;		// Locked before thd is deleted

unknown's avatar
unknown committed
465 466 467 468 469 470 471
  char	  *query;			// Points to the current query,
  /*
    A pointer to the stack frame of handle_one_connection(),
    which is called first in the thread for handling a client
  */
  char	  *thread_stack;

472 473 474 475
  /*
    host - host of the client
    user - user of the client, set to NULL until the user has been read from
     the connection
476
    priv_user - The user privilege we are using. May be '' for anonymous user.
477 478 479
    db - currently selected database
    ip - client IP
   */
unknown's avatar
unknown committed
480
  char	  *host,*user,*priv_user,*db,*ip;
481
  char	  priv_host[MAX_HOSTNAME];
unknown's avatar
unknown committed
482 483
  /* remote (peer) port */
  uint16 peer_port;
484 485 486 487 488
  /*
    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.
  */
unknown's avatar
unknown committed
489 490 491
  const char *proc_info;
  /* points to host if host is available, otherwise points to ip */
  const char *host_or_ip;
492

493
  ulong client_capabilities;		/* What the client supports */
494
  ulong max_client_packet_length;
unknown's avatar
unknown committed
495 496
  ulong master_access;			/* Global privileges from mysql.user */
  ulong db_access;			/* Privileges for current db */
497 498 499 500 501 502

  /*
    open_tables - list of regular tables in use by this thread
    temporary_tables - list of temp tables in use by this thread
    handler_tables - list of tables that were opened with HANDLER OPEN
     and are still in use by this thread
unknown's avatar
unknown committed
503
  */
504
  TABLE   *open_tables,*temporary_tables, *handler_tables, *derived_tables;
505
  // TODO: document the variables below
506 507 508 509
  MYSQL_LOCK	*lock;				/* Current locks */
  MYSQL_LOCK	*locked_tables;			/* Tables locked with LOCK */
  ULL		*ull;
  PREP_STMT	*last_prepared_stmt;
510 511
#ifndef DBUG_OFF
  uint dbug_sentry; // watch out for memory corruption
512
#endif
unknown's avatar
unknown committed
513 514
  struct st_my_thread_var *mysys_var;
  enum enum_server_command command;
unknown's avatar
unknown committed
515
  uint32     server_id;
unknown's avatar
unknown committed
516
  uint32     file_id;			// for LOAD DATA INFILE
517 518 519 520 521
  /*
    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.
  */
unknown's avatar
unknown committed
522
  const char *where;
unknown's avatar
unknown committed
523 524
  time_t     start_time,time_after_lock,user_time;
  time_t     connect_time,thr_create_time; // track down slow pthread_create
unknown's avatar
unknown committed
525 526
  thr_lock_type update_lock_default;
  delayed_insert *di;
unknown's avatar
unknown committed
527
  my_bool    tablespace_op;	/* This is TRUE in DISCARD/IMPORT TABLESPACE */
unknown's avatar
unknown committed
528
  struct st_transactions {
529
    IO_CACHE trans_log;
unknown's avatar
unknown committed
530 531
    THD_TRANS all;			// Trans since BEGIN WORK
    THD_TRANS stmt;			// Trans for current statement
unknown's avatar
unknown committed
532
    uint bdb_lock_count;
533

534
    /*
535
       Tables changed in transaction (that must be invalidated in query cache).
536
       List contain only transactional tables, that not invalidated in query
537 538 539 540 541 542 543 544 545
       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()
    {
      changed_tables = 0;
      free_root(&mem_root,MYF(MY_KEEP_PREALLOC));
    }
unknown's avatar
unknown committed
546
  } transaction;
unknown's avatar
unknown committed
547
  Item	     *free_list, *handler_items;
unknown's avatar
unknown committed
548 549 550 551
  Field      *dupp_field;
#ifndef __WIN__
  sigset_t signals,block_signals;
#endif
552 553
#ifdef SIGNAL_WITH_VIO_CLOSE
  Vio* active_vio;
554
#endif
555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571
  /*
    next_insert_id is set on SET INSERT_ID= #. This is used as the next
    generated auto_increment value in handler.cc
  */
  ulonglong  next_insert_id;
  /*
    The insert_id used for the last statement or set by SET LAST_INSERT_ID=#
    or SELECT LAST_INSERT_ID(#).  Used for binary log and returned by
    LAST_INSERT_ID()
  */
  ulonglong  last_insert_id;
  /*
    Set to the first value that LAST_INSERT_ID() returned for the last
    statement.  When this is set, last_insert_id_used is set to true.
  */
  ulonglong  current_insert_id;
  ulonglong  limit_found_rows;
unknown's avatar
unknown committed
572
  ha_rows    cuted_fields,
unknown's avatar
unknown committed
573
             sent_row_count, examined_row_count;
unknown's avatar
unknown committed
574
  table_map  used_tables;
575
  USER_CONN *user_connect;
576
  CHARSET_INFO *db_charset;
577
  List<TABLE> temporary_tables_should_be_free; // list of temporary tables
578
  List	     <MYSQL_ERROR> warn_list;
579
  uint	     warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_END];
unknown's avatar
unknown committed
580
  uint	     total_warn_count;
581
  ulong	     query_id, warn_id, version, options, thread_id, col_access;
582
  ulong      current_stmt_id;
583
  ulong	     rand_saved_seed1, rand_saved_seed2;
584
  ulong      row_count;  // Row counter, mainly for errors and warnings
unknown's avatar
unknown committed
585
  long	     dbug_thread_id;
unknown's avatar
unknown committed
586
  pthread_t  real_id;
587
  uint	     current_tablenr,tmp_table;
unknown's avatar
unknown committed
588 589
  uint	     server_status,open_options;
  uint32     query_length;
unknown's avatar
unknown committed
590
  uint32     db_length;
unknown's avatar
unknown committed
591
  uint       select_number;             //number of select (used for EXPLAIN)
unknown's avatar
unknown committed
592 593
  /* variables.transaction_isolation is reset to this after each commit */
  enum_tx_isolation session_tx_isolation;
594
  enum_check_fields count_cuted_fields;
unknown's avatar
unknown committed
595 596
  /* for user variables replication*/
  DYNAMIC_ARRAY user_var_events;
597 598

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

unknown's avatar
unknown committed
601
  bool       slave_thread;
602
  bool	     set_query_id,locked,some_tables_deleted;
603
  bool       last_cuted_field;
604
  bool	     no_errors, allow_sum_func, password, is_fatal_error;
unknown's avatar
unknown committed
605
  bool	     query_start_used,last_insert_id_used,insert_id_used,rand_used;
unknown's avatar
unknown committed
606
  bool	     system_thread,in_lock_tables,global_read_lock;
unknown's avatar
unknown committed
607
  bool       query_error, bootstrap, cleanup_done;
unknown's avatar
unknown committed
608
  bool	     volatile killed;
unknown's avatar
unknown committed
609
  bool	     tmp_table_used;
unknown's avatar
unknown committed
610
  bool	     charset_is_system_charset, charset_is_collation_connection;
611
  bool       slow_command;
unknown's avatar
unknown committed
612

unknown's avatar
unknown committed
613 614 615 616 617
  /*
    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
618
  LOG_INFO*  current_linfo;
unknown's avatar
unknown committed
619
  NET*       slave_net;			// network connection from slave -> m.
unknown's avatar
unknown committed
620 621 622 623 624 625 626
  /* Used by the sys_var class to store temporary values */
  union
  {
    my_bool my_bool_value;
    long    long_value;
  } sys_var_tmp;

unknown's avatar
unknown committed
627 628
  THD();
  ~THD();
629

unknown's avatar
unknown committed
630 631
  void init(void);
  void change_user(void);
unknown's avatar
unknown committed
632
  void init_for_queries();
unknown's avatar
unknown committed
633
  void cleanup(void);
unknown's avatar
unknown committed
634
  bool store_globals();
635 636
#ifdef SIGNAL_WITH_VIO_CLOSE
  inline void set_active_vio(Vio* vio)
637
  {
638
    pthread_mutex_lock(&LOCK_delete);
639
    active_vio = vio;
640
    pthread_mutex_unlock(&LOCK_delete);
641
  }
642
  inline void clear_active_vio()
643
  {
644
    pthread_mutex_lock(&LOCK_delete);
645
    active_vio = 0;
646
    pthread_mutex_unlock(&LOCK_delete);
647
  }
unknown's avatar
unknown committed
648
  void close_active_vio();
649
#endif  
650
  void awake(bool prepare_to_die);
unknown's avatar
unknown committed
651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667
  inline const char* enter_cond(pthread_cond_t *cond, pthread_mutex_t* mutex,
			  const char* msg)
  {
    const char* old_msg = proc_info;
    mysys_var->current_mutex = mutex;
    mysys_var->current_cond = cond;
    proc_info = msg;
    return old_msg;
  }
  inline void exit_cond(const char* old_msg)
  {
    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
668
  inline time_t query_start() { query_start_used=1; return start_time; }
unknown's avatar
unknown committed
669
  inline void	set_time()    { if (user_time) start_time=time_after_lock=user_time; else time_after_lock=time(&start_time); }
670
  inline void	end_time()    { time(&start_time); }
unknown's avatar
unknown committed
671
  inline void	set_time(time_t t) { time_after_lock=start_time=user_time=t; }
672
  inline void	lock_time()   { time(&time_after_lock); }
unknown's avatar
unknown committed
673 674 675 676 677 678 679 680 681 682 683
  inline void	insert_id(ulonglong id)
  { last_insert_id=id; insert_id_used=1; }
  inline ulonglong insert_id(void)
  {
    if (!last_insert_id_used)
    {      
      last_insert_id_used=1;
      current_insert_id=last_insert_id;
    }
    return last_insert_id;
  }
684 685 686 687
  inline ulonglong found_rows(void)
  {
    return limit_found_rows;
  }                                                                         
688 689
  inline bool active_transaction()
  {
690
#ifdef USING_TRANSACTIONS    
691
    return (transaction.all.bdb_tid != 0 ||
unknown's avatar
unknown committed
692
	    transaction.all.innodb_active_trans != 0);
693 694 695
#else
    return 0;
#endif
696
  }
697 698 699 700 701 702 703 704 705 706
  inline gptr alloc(unsigned int size) { return alloc_root(&mem_root,size); }
  inline gptr calloc(unsigned int size)
  {
    gptr ptr;
    if ((ptr=alloc_root(&mem_root,size)))
      bzero((char*) ptr,size);
    return ptr;
  }
  inline char *strdup(const char *str)
  { return strdup_root(&mem_root,str); }
707 708 709
  inline char *strmake(const char *str, uint size)
  { return strmake_root(&mem_root,str,size); }
  inline char *memdup(const char *str, uint size)
710
  { return memdup_root(&mem_root,str,size); }
unknown's avatar
unknown committed
711 712 713 714 715 716 717
  inline char *memdup_w_gap(const char *str, uint size, uint gap)
  {
    gptr ptr;
    if ((ptr=alloc_root(&mem_root,size+gap)))
      memcpy(ptr,str,size);
    return ptr;
  }
unknown's avatar
unknown committed
718 719 720
  bool convert_string(LEX_STRING *to, CHARSET_INFO *to_cs,
		      const char *from, uint from_length,
		      CHARSET_INFO *from_cs);
721 722 723 724 725
  inline gptr trans_alloc(unsigned int size) 
  { 
    return alloc_root(&transaction.mem_root,size);
  }
  void add_changed_table(TABLE *table);
unknown's avatar
unknown committed
726 727
  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
728
  int send_explain_fields(select_result *result);
729
#ifndef EMBEDDED_LIBRARY
unknown's avatar
unknown committed
730 731 732 733 734 735
  inline void clear_error()
  {
    net.last_error[0]= 0;
    net.last_errno= 0;
    net.report_error= 0;
  }
736 737 738
#else
  void clear_error();
#endif
739 740 741 742
  inline void fatal_error()
  {
    is_fatal_error= 1;
    net.report_error= 1; 
unknown's avatar
unknown committed
743
    DBUG_PRINT("error",("Fatal error set"));
744
  }
745
  inline CHARSET_INFO *charset() { return variables.character_set_client; }
unknown's avatar
unknown committed
746
  void update_charset();
unknown's avatar
unknown committed
747 748
};

unknown's avatar
unknown committed
749 750 751 752
/*
  Used to hold information about file and file structure in exchainge 
  via non-DB file (...INTO OUTFILE..., ...LOAD DATA...)
*/
unknown's avatar
unknown committed
753 754 755 756 757 758 759 760 761 762 763 764 765 766 767
class sql_exchange :public Sql_alloc
{
public:
  char *file_name;
  String *field_term,*enclosed,*line_term,*line_start,*escaped;
  bool opt_enclosed;
  bool dumpfile;
  uint skip_lines;
  sql_exchange(char *name,bool dumpfile_flag);
  ~sql_exchange() {}
};

#include "log_event.h"

/*
768
  This is used to get result from a select
unknown's avatar
unknown committed
769 770
*/

unknown's avatar
unknown committed
771 772
class JOIN;

773
void send_error(THD *thd, uint sql_errno=0, const char *err=0);
unknown's avatar
unknown committed
774

unknown's avatar
unknown committed
775 776 777
class select_result :public Sql_alloc {
protected:
  THD *thd;
778
  SELECT_LEX_UNIT *unit;
unknown's avatar
unknown committed
779 780 781
public:
  select_result();
  virtual ~select_result() {};
782 783 784 785 786
  virtual int prepare(List<Item> &list, SELECT_LEX_UNIT *u)
  {
    unit= u;
    return 0;
  }
unknown's avatar
unknown committed
787 788
  virtual bool send_fields(List<Item> &list,uint flag)=0;
  virtual bool send_data(List<Item> &items)=0;
unknown's avatar
unknown committed
789
  virtual bool initialize_tables (JOIN *join=0) { return 0; }
790
  virtual void send_error(uint errcode,const char *err);
unknown's avatar
unknown committed
791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815
  virtual bool send_eof()=0;
  virtual void abort() {}
};


class select_send :public select_result {
public:
  select_send() {}
  bool send_fields(List<Item> &list,uint flag);
  bool send_data(List<Item> &items);
  bool send_eof();
};


class select_export :public select_result {
  sql_exchange *exchange;
  File file;
  IO_CACHE cache;
  ha_rows row_count;
  uint field_term_length;
  int field_sep_char,escape_char,line_sep_char;
  bool fixed_row_size;
public:
  select_export(sql_exchange *ex) :exchange(ex),file(-1),row_count(0L) {}
  ~select_export();
816
  int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
unknown's avatar
unknown committed
817 818 819 820 821 822 823
  bool send_fields(List<Item> &list,
		   uint flag) { return 0; }
  bool send_data(List<Item> &items);
  void send_error(uint errcode,const char *err);
  bool send_eof();
};

unknown's avatar
unknown committed
824

unknown's avatar
unknown committed
825 826 827 828 829 830 831 832 833 834
class select_dump :public select_result {
  sql_exchange *exchange;
  File file;
  IO_CACHE cache;
  ha_rows row_count;
  char path[FN_REFLEN];
public:
  select_dump(sql_exchange *ex) :exchange(ex),file(-1),row_count(0L)
  { path[0]=0; }
  ~select_dump();
835
  int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
unknown's avatar
unknown committed
836 837 838 839 840 841
  bool send_fields(List<Item> &list,
		   uint flag) { return 0; }
  bool send_data(List<Item> &items);
  void send_error(uint errcode,const char *err);
  bool send_eof();
};
unknown's avatar
unknown committed
842 843


unknown's avatar
unknown committed
844
class select_insert :public select_result {
unknown's avatar
unknown committed
845
 public:
unknown's avatar
unknown committed
846 847 848 849 850
  TABLE *table;
  List<Item> *fields;
  ulonglong last_insert_id;
  COPY_INFO info;

unknown's avatar
unknown committed
851
  select_insert(TABLE *table_par,List<Item> *fields_par,enum_duplicates duplic)
unknown's avatar
unknown committed
852 853
    :table(table_par),fields(fields_par), last_insert_id(0)
  {
unknown's avatar
unknown committed
854 855 856
    bzero((char*) &info,sizeof(info));
    info.handle_duplicates=duplic;
  }
unknown's avatar
unknown committed
857
  ~select_insert();
858
  int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
unknown's avatar
unknown committed
859 860
  bool send_fields(List<Item> &list, uint flag)
  { return 0; }
unknown's avatar
unknown committed
861 862 863 864 865
  bool send_data(List<Item> &items);
  void send_error(uint errcode,const char *err);
  bool send_eof();
};

unknown's avatar
unknown committed
866

unknown's avatar
unknown committed
867 868 869 870 871 872 873 874 875 876 877 878 879 880
class select_create: public select_insert {
  ORDER *group;
  const char *db;
  const char *name;
  List<create_field> *extra_fields;
  List<Key> *keys;
  HA_CREATE_INFO *create_info;
  MYSQL_LOCK *lock;
  Field **field;
public:
  select_create (const char *db_name, const char *table_name,
		 HA_CREATE_INFO *create_info_par,
		 List<create_field> &fields_par,
		 List<Key> &keys_par,
unknown's avatar
unknown committed
881 882
		 List<Item> &select_fields,enum_duplicates duplic)
    :select_insert (NULL, &select_fields, duplic), db(db_name),
unknown's avatar
unknown committed
883
    name(table_name), extra_fields(&fields_par),keys(&keys_par),
884
    create_info(create_info_par), lock(0)
unknown's avatar
unknown committed
885
    {}
886
  int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
unknown's avatar
unknown committed
887 888 889 890 891
  bool send_data(List<Item> &values);
  bool send_eof();
  void abort();
};

892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932
#include <myisam.h>

/* Param to create temporary tables when doing SELECT:s */

class TMP_TABLE_PARAM :public Sql_alloc
{
 public:
  List<Item> copy_funcs;
  List<Item> save_copy_funcs;
  List_iterator_fast<Item> copy_funcs_it;
  Copy_field *copy_field, *copy_field_end;
  Copy_field *save_copy_field, *save_copy_field_end;
  byte	    *group_buff;
  Item	    **items_to_copy;			/* Fields in tmp table */
  MI_COLUMNDEF *recinfo,*start_recinfo;
  KEY *keyinfo;
  ha_rows end_write_records;
  uint	field_count,sum_func_count,func_count;
  uint  hidden_field_count;
  uint	group_parts,group_length,group_null_parts;
  uint	quick_group;
  bool  using_indirect_summary_function;

  TMP_TABLE_PARAM()
    :copy_funcs_it(copy_funcs), copy_field(0), group_parts(0),
    group_length(0), group_null_parts(0)
  {}
  ~TMP_TABLE_PARAM()
  {
    cleanup();
  }
  inline void cleanup(void)
  {
    if (copy_field)				/* Fix for Intel compiler */
    {
      delete [] copy_field;
      copy_field=0;
    }
  }
};

unknown's avatar
unknown committed
933 934 935 936
class select_union :public select_result {
 public:
  TABLE *table;
  COPY_INFO info;
937
  TMP_TABLE_PARAM tmp_table_param;
unknown's avatar
unknown committed
938
  bool not_describe;
unknown's avatar
unknown committed
939 940 941

  select_union(TABLE *table_par);
  ~select_union();
942
  int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
unknown's avatar
unknown committed
943 944 945 946 947
  bool send_fields(List<Item> &list, uint flag)
  { return 0; }
  bool send_data(List<Item> &items);
  bool send_eof();
  bool flush();
948
  void set_table(TABLE *tbl) { table= tbl; }
unknown's avatar
unknown committed
949 950
};

unknown's avatar
unknown committed
951
/* Base subselect interface class */
952 953
class select_subselect :public select_result
{
unknown's avatar
unknown committed
954
protected:
955 956 957 958
  Item_subselect *item;
public:
  select_subselect(Item_subselect *item);
  bool send_fields(List<Item> &list, uint flag) { return 0; };
unknown's avatar
unknown committed
959
  bool send_data(List<Item> &items)=0;
960
  bool send_eof() { return 0; };
unknown's avatar
unknown committed
961

962 963 964
  friend class Ttem_subselect;
};

unknown's avatar
unknown committed
965
/* Single value subselect interface class */
unknown's avatar
unknown committed
966
class select_singlerow_subselect :public select_subselect
unknown's avatar
unknown committed
967 968
{
public:
unknown's avatar
unknown committed
969
  select_singlerow_subselect(Item_subselect *item):select_subselect(item){}
unknown's avatar
unknown committed
970 971 972
  bool send_data(List<Item> &items);
};

973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988
/* 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:
  select_max_min_finder_subselect(Item_subselect *item, bool mx)
    :select_subselect(item), cache(0), fmax(mx)
  {}
  bool send_data(List<Item> &items);
  bool cmp_real();
  bool cmp_int();
  bool cmp_str();
};

unknown's avatar
unknown committed
989 990 991 992 993 994 995 996
/* EXISTS subselect interface class */
class select_exists_subselect :public select_subselect
{
public:
  select_exists_subselect(Item_subselect *item):select_subselect(item){}
  bool send_data(List<Item> &items);
};

unknown's avatar
unknown committed
997 998 999 1000 1001 1002 1003
/* 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 */
  Item_result result_type;		/* Type of item */
1004 1005
  bool reverse;				/* if descending sort */
  bool need_strxnfrm;			/* If we have to use strxnfrm() */
unknown's avatar
unknown committed
1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018
} 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 */

1019 1020
class Table_ident :public Sql_alloc
{
unknown's avatar
unknown committed
1021 1022 1023
 public:
  LEX_STRING db;
  LEX_STRING table;
unknown's avatar
unknown committed
1024
  SELECT_LEX_UNIT *sel;
unknown's avatar
unknown committed
1025 1026
  inline Table_ident(THD *thd, LEX_STRING db_arg, LEX_STRING table_arg,
		     bool force)
unknown's avatar
unknown committed
1027
    :table(table_arg), sel((SELECT_LEX_UNIT *)0)
unknown's avatar
unknown committed
1028
  {
unknown's avatar
unknown committed
1029
    if (!force && (thd->client_capabilities & CLIENT_NO_SCHEMA))
unknown's avatar
unknown committed
1030 1031 1032 1033
      db.str=0;
    else
      db= db_arg;
  }
unknown's avatar
unknown committed
1034 1035 1036 1037 1038 1039 1040
  inline Table_ident(LEX_STRING table_arg) 
    :table(table_arg), sel((SELECT_LEX_UNIT *)0)
  {
    db.str=0;
  }
  inline Table_ident(SELECT_LEX_UNIT *s) : sel(s) 
  {
unknown's avatar
unknown committed
1041 1042
    /* We must have a table name here as this is used with add_table_to_list */
    db.str=0; table.str= internal_table_name; table.length=1;
unknown's avatar
unknown committed
1043
  }
unknown's avatar
unknown committed
1044
  inline void change_db(char *db_name)
unknown's avatar
unknown committed
1045 1046 1047
  {
    db.str= db_name; db.length= (uint) strlen(db_name);
  }
unknown's avatar
unknown committed
1048 1049 1050 1051 1052 1053 1054 1055
};

// this is needed for user_vars hash
class user_var_entry
{
 public:
  LEX_STRING name;
  char *value;
unknown's avatar
unknown committed
1056
  ulong length, update_query_id, used_query_id;
unknown's avatar
unknown committed
1057
  Item_result type;
1058 1059 1060 1061

  double val(my_bool *null_value);
  longlong val_int(my_bool *null_value);
  String *val_str(my_bool *null_value, String *str, uint decimals);
1062
  DTCollation collation;
unknown's avatar
unknown committed
1063 1064
};

1065

1066 1067 1068 1069 1070 1071 1072 1073
/* Class for unique (removing of duplicates) */

class Unique :public Sql_alloc
{
  DYNAMIC_ARRAY file_ptrs;
  ulong max_elements, max_in_memory_size;
  IO_CACHE file;
  TREE tree;
unknown's avatar
unknown committed
1074
  byte *record_pointers;
1075
  bool flush();
1076
  uint size;
1077 1078 1079

public:
  ulong elements;
1080
  Unique(qsort_cmp2 comp_func, void * comp_func_fixed_arg,
1081
	 uint size_arg, ulong max_in_memory_size_arg);
1082
  ~Unique();
unknown's avatar
unknown committed
1083
  inline bool unique_add(gptr ptr)
1084 1085 1086
  {
    if (tree.elements_in_tree > max_elements && flush())
      return 1;
1087
    return !tree_insert(&tree, ptr, 0, tree.custom_arg);
1088 1089 1090 1091
  }

  bool get(TABLE *table);

1092 1093
  friend int unique_write_to_file(gptr key, element_count count, Unique *unique);
  friend int unique_write_to_ptrs(gptr key, element_count count, Unique *unique);
1094
};
1095

unknown's avatar
unknown committed
1096 1097

class multi_delete :public select_result
unknown's avatar
unknown committed
1098 1099
{
  TABLE_LIST *delete_tables, *table_being_deleted;
unknown's avatar
unknown committed
1100
  Unique **tempfiles;
unknown's avatar
unknown committed
1101 1102 1103 1104 1105 1106 1107 1108 1109 1110
  THD *thd;
  ha_rows deleted;
  uint num_of_tables;
  int error;
  bool do_delete, transactional_tables, log_delayed, normal_tables;
public:
  multi_delete(THD *thd, TABLE_LIST *dt, uint num_of_tables);
  ~multi_delete();
  int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
  bool send_fields(List<Item> &list,
1111
 		   uint flag) { return 0; }
unknown's avatar
unknown committed
1112 1113 1114 1115 1116 1117 1118
  bool send_data(List<Item> &items);
  bool initialize_tables (JOIN *join);
  void send_error(uint errcode,const char *err);
  int  do_deletes (bool from_send_error);
  bool send_eof();
};

1119

unknown's avatar
unknown committed
1120
class multi_update :public select_result
unknown's avatar
unknown committed
1121 1122 1123
{
  TABLE_LIST *all_tables, *update_tables, *table_being_updated;
  THD *thd;
unknown's avatar
unknown committed
1124
  TABLE **tmp_tables, *main_table, *table_to_update;
unknown's avatar
unknown committed
1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137
  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;
  Copy_field *copy_field;
  enum enum_duplicates handle_duplicates;
  bool do_update, trans_safe, transactional_tables, log_delayed;

public:
  multi_update(THD *thd_arg, TABLE_LIST *ut, List<Item> *fields,
	       List<Item> *values, enum_duplicates handle_duplicates);
  ~multi_update();
unknown's avatar
unknown committed
1138
  int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
unknown's avatar
unknown committed
1139 1140 1141 1142 1143 1144 1145
  bool send_fields(List<Item> &list, uint flag) { return 0; }
  bool send_data(List<Item> &items);
  bool initialize_tables (JOIN *join);
  void send_error(uint errcode,const char *err);
  int  do_updates (bool from_send_error);
  bool send_eof();
};
1146 1147


unknown's avatar
unknown committed
1148 1149 1150
class select_dumpvar :public select_result {
  ha_rows row_count;
public:
1151 1152 1153
  List<LEX_STRING> var_list;
  List<Item_func_set_user_var> vars;
  select_dumpvar(void)  { var_list.empty(); vars.empty(); row_count=0;}
unknown's avatar
unknown committed
1154
  ~select_dumpvar() {}
1155 1156
  int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
  bool send_fields(List<Item> &list, uint flag) {return 0;}
unknown's avatar
unknown committed
1157 1158 1159
  bool send_data(List<Item> &items);
  bool send_eof();
};