sql_class.h 32.7 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
  sys_var_datetime_format datetime_formats[3];
unknown's avatar
unknown committed
425 426
};

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

unknown's avatar
unknown committed
433 434
class THD :public ilink
{
unknown's avatar
unknown committed
435
public:
436 437
#ifdef EMBEDDED_LIBRARY
  struct st_mysql  *mysql;
unknown's avatar
SCRUM  
unknown committed
438 439 440
  struct st_mysql_data *data;
  unsigned long	 client_stmt_id;
  unsigned long  client_param_count;
unknown's avatar
unknown committed
441
  struct st_mysql_bind *client_params;
unknown's avatar
unknown committed
442 443
  char *extra_data;
  ulong extra_length;
444
#endif
unknown's avatar
unknown committed
445 446 447
  NET	  net;				// client connection descriptor
  LEX	  lex;				// parse tree descriptor
  MEM_ROOT mem_root;			// 1 command-life memory pool
unknown's avatar
unknown committed
448
  MEM_ROOT con_root;                    // connection-life memory
449
  MEM_ROOT warn_root;			// For warnings and errors
450 451 452
  Protocol *protocol;			// Current protocol
  Protocol_simple protocol_simple;	// Normal protocol
  Protocol_prep protocol_prep;		// Binary protocol
unknown's avatar
unknown committed
453
  HASH    user_vars;			// hash for user variables
454
  TREE	  prepared_statements;
unknown's avatar
unknown committed
455 456 457 458
  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
459 460
  pthread_mutex_t LOCK_delete;		// Locked before thd is deleted

unknown's avatar
unknown committed
461 462 463 464 465 466 467
  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;

468 469 470 471
  /*
    host - host of the client
    user - user of the client, set to NULL until the user has been read from
     the connection
472
    priv_user - The user privilege we are using. May be '' for anonymous user.
473 474 475
    db - currently selected database
    ip - client IP
   */
unknown's avatar
unknown committed
476
  char	  *host,*user,*priv_user,*db,*ip;
477
  char	  priv_host[MAX_HOSTNAME];
unknown's avatar
unknown committed
478 479
  /* remote (peer) port */
  uint16 peer_port;
unknown's avatar
unknown committed
480 481 482 483
  /* Points to info-string that will show in SHOW PROCESSLIST */
  const char *proc_info;
  /* points to host if host is available, otherwise points to ip */
  const char *host_or_ip;
484

485
  ulong client_capabilities;		/* What the client supports */
486
  ulong max_client_packet_length;
unknown's avatar
unknown committed
487 488
  ulong master_access;			/* Global privileges from mysql.user */
  ulong db_access;			/* Privileges for current db */
489 490 491 492 493 494

  /*
    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
495
  */
496
  TABLE   *open_tables,*temporary_tables, *handler_tables, *derived_tables;
497
  // TODO: document the variables below
498 499 500 501
  MYSQL_LOCK	*lock;				/* Current locks */
  MYSQL_LOCK	*locked_tables;			/* Tables locked with LOCK */
  ULL		*ull;
  PREP_STMT	*last_prepared_stmt;
502 503 504
#ifndef DBUG_OFF
  uint dbug_sentry; // watch out for memory corruption
#endif  
unknown's avatar
unknown committed
505 506
  struct st_my_thread_var *mysys_var;
  enum enum_server_command command;
unknown's avatar
unknown committed
507
  uint32     server_id;
unknown's avatar
unknown committed
508
  uint32     file_id;			// for LOAD DATA INFILE
unknown's avatar
unknown committed
509
  const char *where;
unknown's avatar
unknown committed
510 511
  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
512 513
  thr_lock_type update_lock_default;
  delayed_insert *di;
unknown's avatar
unknown committed
514
  my_bool    tablespace_op;	/* This is TRUE in DISCARD/IMPORT TABLESPACE */
unknown's avatar
unknown committed
515
  struct st_transactions {
516
    IO_CACHE trans_log;
unknown's avatar
unknown committed
517 518
    THD_TRANS all;			// Trans since BEGIN WORK
    THD_TRANS stmt;			// Trans for current statement
unknown's avatar
unknown committed
519
    uint bdb_lock_count;
520 521 522 523 524 525 526 527 528 529 530 531 532

    /* 
       Tables changed in transaction (that must be invalidated in query cache).
       List contain only transactional tables, that not invalidated in query 
       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
533
  } transaction;
unknown's avatar
unknown committed
534
  Item	     *free_list, *handler_items;
unknown's avatar
unknown committed
535 536 537 538
  Field      *dupp_field;
#ifndef __WIN__
  sigset_t signals,block_signals;
#endif
539 540
#ifdef SIGNAL_WITH_VIO_CLOSE
  Vio* active_vio;
541
#endif  
542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558
  /*
    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
559
  ha_rows    cuted_fields,
unknown's avatar
unknown committed
560
             sent_row_count, examined_row_count;
unknown's avatar
unknown committed
561
  table_map  used_tables;
562
  USER_CONN *user_connect;
unknown's avatar
unknown committed
563
  CHARSET_INFO *db_charset;   
564
  List<TABLE> temporary_tables_should_be_free; // list of temporary tables
565 566
  List	     <MYSQL_ERROR> warn_list;  
  uint	     warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_END];
unknown's avatar
unknown committed
567
  uint	     total_warn_count;
568
  ulong	     query_id, warn_id, version, options, thread_id, col_access;
569
  ulong      current_stmt_id;
570
  ulong	     rand_saved_seed1, rand_saved_seed2;
571
  ulong      row_count;  // Row counter, mainly for errors and warnings
unknown's avatar
unknown committed
572
  long	     dbug_thread_id;
unknown's avatar
unknown committed
573
  pthread_t  real_id;
574
  uint	     current_tablenr,tmp_table;
unknown's avatar
unknown committed
575 576
  uint	     server_status,open_options;
  uint32     query_length;
unknown's avatar
unknown committed
577
  uint32     db_length;
unknown's avatar
unknown committed
578
  uint       select_number;             //number of select (used for EXPLAIN)
unknown's avatar
unknown committed
579 580
  /* variables.transaction_isolation is reset to this after each commit */
  enum_tx_isolation session_tx_isolation;
581
  enum_check_fields count_cuted_fields;
unknown's avatar
unknown committed
582 583
  /* for user variables replication*/
  DYNAMIC_ARRAY user_var_events;
584 585

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

unknown's avatar
unknown committed
588
  bool       slave_thread;
589
  bool	     set_query_id,locked,some_tables_deleted;
590
  bool       last_cuted_field;
591
  bool	     no_errors, allow_sum_func, password, is_fatal_error;
unknown's avatar
unknown committed
592
  bool	     query_start_used,last_insert_id_used,insert_id_used,rand_used;
unknown's avatar
unknown committed
593
  bool	     system_thread,in_lock_tables,global_read_lock;
unknown's avatar
unknown committed
594
  bool       query_error, bootstrap, cleanup_done;
unknown's avatar
unknown committed
595
  bool	     volatile killed;
unknown's avatar
unknown committed
596
  bool       prepare_command;
unknown's avatar
unknown committed
597
  bool	     tmp_table_used;
unknown's avatar
unknown committed
598
  bool	     charset_is_system_charset, charset_is_collation_connection;
unknown's avatar
unknown committed
599

unknown's avatar
unknown committed
600 601 602 603 604
  /*
    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
605
  LOG_INFO*  current_linfo;
unknown's avatar
unknown committed
606
  NET*       slave_net;			// network connection from slave -> m.
unknown's avatar
unknown committed
607 608 609 610 611 612 613
  /* 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
614 615
  THD();
  ~THD();
616

unknown's avatar
unknown committed
617 618
  void init(void);
  void change_user(void);
unknown's avatar
unknown committed
619
  void init_for_queries();
unknown's avatar
unknown committed
620
  void cleanup(void);
unknown's avatar
unknown committed
621
  bool store_globals();
622 623
#ifdef SIGNAL_WITH_VIO_CLOSE
  inline void set_active_vio(Vio* vio)
624
  {
625
    pthread_mutex_lock(&LOCK_delete);
626
    active_vio = vio;
627
    pthread_mutex_unlock(&LOCK_delete);
628
  }
629
  inline void clear_active_vio()
630
  {
631
    pthread_mutex_lock(&LOCK_delete);
632
    active_vio = 0;
633
    pthread_mutex_unlock(&LOCK_delete);
634
  }
unknown's avatar
unknown committed
635
  void close_active_vio();
636
#endif  
637
  void awake(bool prepare_to_die);
unknown's avatar
unknown committed
638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654
  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
655
  inline time_t query_start() { query_start_used=1; return start_time; }
unknown's avatar
unknown committed
656
  inline void	set_time()    { if (user_time) start_time=time_after_lock=user_time; else time_after_lock=time(&start_time); }
657
  inline void	end_time()    { time(&start_time); }
unknown's avatar
unknown committed
658
  inline void	set_time(time_t t) { time_after_lock=start_time=user_time=t; }
659
  inline void	lock_time()   { time(&time_after_lock); }
unknown's avatar
unknown committed
660 661 662 663 664 665 666 667 668 669 670
  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;
  }
671 672 673 674
  inline ulonglong found_rows(void)
  {
    return limit_found_rows;
  }                                                                         
675 676
  inline bool active_transaction()
  {
677
#ifdef USING_TRANSACTIONS    
678
    return (transaction.all.bdb_tid != 0 ||
unknown's avatar
unknown committed
679
	    transaction.all.innodb_active_trans != 0);
680 681 682
#else
    return 0;
#endif
683
  }
684 685 686 687 688 689 690 691 692 693
  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); }
694 695 696
  inline char *strmake(const char *str, uint size)
  { return strmake_root(&mem_root,str,size); }
  inline char *memdup(const char *str, uint size)
697
  { return memdup_root(&mem_root,str,size); }
unknown's avatar
unknown committed
698 699 700 701 702 703 704
  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
705 706 707
  bool convert_string(LEX_STRING *to, CHARSET_INFO *to_cs,
		      const char *from, uint from_length,
		      CHARSET_INFO *from_cs);
708 709 710 711 712
  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
713 714
  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
715
  int send_explain_fields(select_result *result);
716
#ifndef EMBEDDED_LIBRARY
unknown's avatar
unknown committed
717 718 719 720 721 722
  inline void clear_error()
  {
    net.last_error[0]= 0;
    net.last_errno= 0;
    net.report_error= 0;
  }
723 724 725
#else
  void clear_error();
#endif
726 727 728 729
  inline void fatal_error()
  {
    is_fatal_error= 1;
    net.report_error= 1; 
unknown's avatar
unknown committed
730
    DBUG_PRINT("error",("Fatal error set"));
731
  }
732
  inline CHARSET_INFO *charset() { return variables.character_set_client; }
unknown's avatar
unknown committed
733
  void update_charset();
unknown's avatar
unknown committed
734 735
};

unknown's avatar
unknown committed
736 737 738 739
/*
  Used to hold information about file and file structure in exchainge 
  via non-DB file (...INTO OUTFILE..., ...LOAD DATA...)
*/
unknown's avatar
unknown committed
740 741 742 743 744 745 746 747 748 749 750 751 752 753 754
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"

/*
755
  This is used to get result from a select
unknown's avatar
unknown committed
756 757
*/

unknown's avatar
unknown committed
758 759
class JOIN;

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

unknown's avatar
unknown committed
762 763 764
class select_result :public Sql_alloc {
protected:
  THD *thd;
765
  SELECT_LEX_UNIT *unit;
unknown's avatar
unknown committed
766 767 768
public:
  select_result();
  virtual ~select_result() {};
769 770 771 772 773
  virtual int prepare(List<Item> &list, SELECT_LEX_UNIT *u)
  {
    unit= u;
    return 0;
  }
unknown's avatar
unknown committed
774 775
  virtual bool send_fields(List<Item> &list,uint flag)=0;
  virtual bool send_data(List<Item> &items)=0;
unknown's avatar
unknown committed
776
  virtual bool initialize_tables (JOIN *join=0) { return 0; }
777
  virtual void send_error(uint errcode,const char *err);
unknown's avatar
unknown committed
778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802
  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();
803
  int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
unknown's avatar
unknown committed
804 805 806 807 808 809 810
  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
811

unknown's avatar
unknown committed
812 813 814 815 816 817 818 819 820 821
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();
822
  int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
unknown's avatar
unknown committed
823 824 825 826 827 828
  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
829 830


unknown's avatar
unknown committed
831
class select_insert :public select_result {
unknown's avatar
unknown committed
832
 public:
unknown's avatar
unknown committed
833 834 835 836 837
  TABLE *table;
  List<Item> *fields;
  ulonglong last_insert_id;
  COPY_INFO info;

unknown's avatar
unknown committed
838
  select_insert(TABLE *table_par,List<Item> *fields_par,enum_duplicates duplic)
unknown's avatar
unknown committed
839 840
    :table(table_par),fields(fields_par), last_insert_id(0)
  {
unknown's avatar
unknown committed
841 842 843
    bzero((char*) &info,sizeof(info));
    info.handle_duplicates=duplic;
  }
unknown's avatar
unknown committed
844
  ~select_insert();
845
  int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
unknown's avatar
unknown committed
846 847
  bool send_fields(List<Item> &list, uint flag)
  { return 0; }
unknown's avatar
unknown committed
848 849 850 851 852
  bool send_data(List<Item> &items);
  void send_error(uint errcode,const char *err);
  bool send_eof();
};

unknown's avatar
unknown committed
853

unknown's avatar
unknown committed
854 855 856 857 858 859 860 861 862 863 864 865 866 867
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
868 869
		 List<Item> &select_fields,enum_duplicates duplic)
    :select_insert (NULL, &select_fields, duplic), db(db_name),
unknown's avatar
unknown committed
870
    name(table_name), extra_fields(&fields_par),keys(&keys_par),
871
    create_info(create_info_par), lock(0)
unknown's avatar
unknown committed
872
    {}
873
  int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
unknown's avatar
unknown committed
874 875 876 877 878
  bool send_data(List<Item> &values);
  bool send_eof();
  void abort();
};

879 880 881 882 883 884 885 886 887 888 889 890 891 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
#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
920 921 922 923
class select_union :public select_result {
 public:
  TABLE *table;
  COPY_INFO info;
924
  TMP_TABLE_PARAM tmp_table_param;
unknown's avatar
unknown committed
925
  bool not_describe;
unknown's avatar
unknown committed
926 927 928

  select_union(TABLE *table_par);
  ~select_union();
929
  int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
unknown's avatar
unknown committed
930 931 932 933 934 935 936
  bool send_fields(List<Item> &list, uint flag)
  { return 0; }
  bool send_data(List<Item> &items);
  bool send_eof();
  bool flush();
};

unknown's avatar
unknown committed
937
/* Base subselect interface class */
938 939
class select_subselect :public select_result
{
unknown's avatar
unknown committed
940
protected:
941 942 943 944
  Item_subselect *item;
public:
  select_subselect(Item_subselect *item);
  bool send_fields(List<Item> &list, uint flag) { return 0; };
unknown's avatar
unknown committed
945
  bool send_data(List<Item> &items)=0;
946
  bool send_eof() { return 0; };
unknown's avatar
unknown committed
947

948 949 950
  friend class Ttem_subselect;
};

unknown's avatar
unknown committed
951
/* Single value subselect interface class */
unknown's avatar
unknown committed
952
class select_singlerow_subselect :public select_subselect
unknown's avatar
unknown committed
953 954
{
public:
unknown's avatar
unknown committed
955
  select_singlerow_subselect(Item_subselect *item):select_subselect(item){}
unknown's avatar
unknown committed
956 957 958
  bool send_data(List<Item> &items);
};

959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974
/* 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
975 976 977 978 979 980 981 982
/* 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
983 984 985 986 987 988 989
/* 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 */
990 991
  bool reverse;				/* if descending sort */
  bool need_strxnfrm;			/* If we have to use strxnfrm() */
unknown's avatar
unknown committed
992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004
} 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 */

1005 1006
class Table_ident :public Sql_alloc
{
unknown's avatar
unknown committed
1007 1008 1009
 public:
  LEX_STRING db;
  LEX_STRING table;
unknown's avatar
unknown committed
1010
  SELECT_LEX_UNIT *sel;
unknown's avatar
unknown committed
1011 1012
  inline Table_ident(THD *thd, LEX_STRING db_arg, LEX_STRING table_arg,
		     bool force)
unknown's avatar
unknown committed
1013
    :table(table_arg), sel((SELECT_LEX_UNIT *)0)
unknown's avatar
unknown committed
1014
  {
unknown's avatar
unknown committed
1015
    if (!force && (thd->client_capabilities & CLIENT_NO_SCHEMA))
unknown's avatar
unknown committed
1016 1017 1018 1019
      db.str=0;
    else
      db= db_arg;
  }
unknown's avatar
unknown committed
1020 1021 1022 1023 1024 1025 1026
  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
1027 1028
    /* 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
1029
  }
unknown's avatar
unknown committed
1030
  inline void change_db(char *db_name)
unknown's avatar
unknown committed
1031 1032 1033
  {
    db.str= db_name; db.length= (uint) strlen(db_name);
  }
unknown's avatar
unknown committed
1034 1035 1036 1037 1038 1039 1040 1041
};

// this is needed for user_vars hash
class user_var_entry
{
 public:
  LEX_STRING name;
  char *value;
unknown's avatar
unknown committed
1042
  ulong length, update_query_id, used_query_id;
unknown's avatar
unknown committed
1043
  Item_result type;
1044 1045 1046 1047

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

1051

1052 1053 1054 1055 1056 1057 1058 1059
/* 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
1060
  byte *record_pointers;
1061
  bool flush();
1062
  uint size;
1063 1064 1065

public:
  ulong elements;
1066
  Unique(qsort_cmp2 comp_func, void * comp_func_fixed_arg,
1067
	 uint size_arg, ulong max_in_memory_size_arg);
1068
  ~Unique();
unknown's avatar
unknown committed
1069
  inline bool unique_add(gptr ptr)
1070 1071 1072
  {
    if (tree.elements_in_tree > max_elements && flush())
      return 1;
1073
    return !tree_insert(&tree, ptr, 0, tree.custom_arg);
1074 1075 1076 1077
  }

  bool get(TABLE *table);

1078 1079
  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);
1080
};
1081

unknown's avatar
unknown committed
1082 1083

class multi_delete :public select_result
unknown's avatar
unknown committed
1084 1085
{
  TABLE_LIST *delete_tables, *table_being_deleted;
unknown's avatar
unknown committed
1086
  Unique **tempfiles;
unknown's avatar
unknown committed
1087 1088 1089 1090 1091 1092 1093 1094 1095 1096
  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,
1097
 		   uint flag) { return 0; }
unknown's avatar
unknown committed
1098 1099 1100 1101 1102 1103 1104
  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();
};

1105

unknown's avatar
unknown committed
1106
class multi_update :public select_result
unknown's avatar
unknown committed
1107 1108 1109
{
  TABLE_LIST *all_tables, *update_tables, *table_being_updated;
  THD *thd;
unknown's avatar
unknown committed
1110
  TABLE **tmp_tables, *main_table, *table_to_update;
unknown's avatar
unknown committed
1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123
  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
1124
  int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
unknown's avatar
unknown committed
1125 1126 1127 1128 1129 1130 1131
  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();
};
1132 1133


unknown's avatar
unknown committed
1134 1135 1136
class select_dumpvar :public select_result {
  ha_rows row_count;
public:
1137 1138 1139
  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
1140
  ~select_dumpvar() {}
1141 1142
  int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
  bool send_fields(List<Item> &list, uint flag) {return 0;}
unknown's avatar
unknown committed
1143 1144 1145
  bool send_data(List<Item> &items);
  bool send_eof();
};