sql_class.h 28.3 KB
Newer Older
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
2

bk@work.mysql.com's avatar
bk@work.mysql.com 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.
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
7

bk@work.mysql.com's avatar
bk@work.mysql.com 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.
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
12

bk@work.mysql.com's avatar
bk@work.mysql.com 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

bk@work.mysql.com's avatar
bk@work.mysql.com committed
26 27
class Query_log_event;
class Load_log_event;
28
class Slave_log_event;
bk@work.mysql.com's avatar
bk@work.mysql.com 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 };
bk@work.mysql.com's avatar
bk@work.mysql.com committed
33
enum enum_log_type { LOG_CLOSED, 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 };
bk@work.mysql.com's avatar
bk@work.mysql.com committed
36

37
// log info errors
bk@work.mysql.com's avatar
bk@work.mysql.com committed
38 39 40 41
#define LOG_INFO_EOF -1
#define LOG_INFO_IO  -2
#define LOG_INFO_INVALID -3
#define LOG_INFO_SEEK -4
42 43 44 45
#define LOG_INFO_PURGE_NO_ROTATE -5
#define LOG_INFO_MEM -6
#define LOG_INFO_FATAL -7
#define LOG_INFO_IN_USE -8
bk@work.mysql.com's avatar
bk@work.mysql.com committed
46

47 48
struct st_relay_log_info;

bk@work.mysql.com's avatar
bk@work.mysql.com committed
49 50 51
typedef struct st_log_info
{
  char log_file_name[FN_REFLEN];
52
  my_off_t index_file_offset, index_file_start_offset;
53 54 55
  my_off_t pos;
  bool fatal; // if the purge happens to give us a negative offset
  pthread_mutex_t lock;
56
  st_log_info():fatal(0) { pthread_mutex_init(&lock, MY_MUTEX_INIT_FAST);}
57
  ~st_log_info() { pthread_mutex_destroy(&lock);}
bk@work.mysql.com's avatar
bk@work.mysql.com committed
58 59
} LOG_INFO;

monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
60
class Log_event;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
61 62 63 64

class MYSQL_LOG {
 private:
  pthread_mutex_t LOCK_log, LOCK_index;
65 66
  pthread_cond_t update_cond;
  ulonglong bytes_written;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
67
  time_t last_time,query_start;
68
  IO_CACHE log_file;
69
  IO_CACHE index_file;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
70 71 72
  char *name;
  char time_buff[20],db[NAME_LEN+1];
  char log_file_name[FN_REFLEN],index_file_name[FN_REFLEN];
73 74 75
  // current file sequence number for load data infile binary logging
  uint file_id;
  uint open_count;				// For replication
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
76 77
  volatile enum_log_type log_type;
  enum cache_type io_cache_type;
78
  bool write_error,inited;
79 80 81 82 83 84
  /*
    For binlog - if log name can never change we should not try to rotate it
    or write any rotation events. The user should use FLUSH MASTER instead
    of FLUSH LOGS for purging.
  */
  bool no_rotate;
85
  bool need_start_event;
86
  bool no_auto_events; // for relay binlog
87 88
  friend class Log_event;

bk@work.mysql.com's avatar
bk@work.mysql.com committed
89 90 91
public:
  MYSQL_LOG();
  ~MYSQL_LOG();
92
  void reset_bytes_written()
93 94 95
  {
    bytes_written = 0;
  }
96
  void harvest_bytes_written(ulonglong* counter)
97
  {
98
#ifndef DBUG_OFF
99
    char buf1[22],buf2[22];
100
#endif	
101 102 103 104 105 106 107
    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;
  }
108 109
  void signal_update() { pthread_cond_broadcast(&update_cond);}
  void wait_for_update(THD* thd);
110 111
  void set_need_start_event() { need_start_event = 1; }
  void init(enum_log_type log_type_arg,
112 113
	    enum cache_type io_cache_type_arg = WRITE_CACHE,
	    bool no_auto_events_arg = 0);
114 115 116
  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,
117
	    bool no_auto_events_arg);
118
  void new_file(bool need_lock= 1);
119 120
  bool write(THD *thd, enum enum_server_command command,
	     const char *format,...);
121
  bool write(THD *thd, const char *query, uint query_length,
122
	     time_t query_start=0);
123
  bool write(Log_event* event_info); // binary log write
124
  bool write(THD *thd, IO_CACHE *cache);
125

126 127 128 129
  /*
    v stands for vector
    invoked as appendv(buf1,len1,buf2,len2,...,bufn,lenn,0)
  */
130
  bool appendv(const char* buf,uint len,...);
131
  bool append(Log_event* ev);
132
  
bk@work.mysql.com's avatar
bk@work.mysql.com committed
133 134 135
  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);
136
  int purge_logs(THD* thd, const char* to_log);
137
  int purge_first_log(struct st_relay_log_info* rli); 
138
  bool reset_logs(THD* thd);
139 140
  // if we are exiting, we also want to close the index file
  void close(bool exiting = 0);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
141 142

  // iterating through the log index file
143
  int find_log_pos(LOG_INFO* linfo, const char* log_name,
144 145
		   bool need_mutex);
  int find_next_log(LOG_INFO* linfo, bool need_mutex);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
146
  int get_current_log(LOG_INFO* linfo);
147
  uint next_file_id();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
148

149
  inline bool is_open() { return log_type != LOG_CLOSED; }
150 151 152 153 154 155 156
  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);}
157
  inline IO_CACHE *get_index_file() { return &index_file;}
158
  inline uint32 get_open_count() { return open_count; }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
159 160 161 162
};

/* character conversion tables */

163 164 165
class CONVERT;
CONVERT *get_convert_set(const char *name_ptr);

bk@work.mysql.com's avatar
bk@work.mysql.com committed
166 167 168 169 170 171
class CONVERT
{
  const uchar *from_map,*to_map;
  void convert_array(const uchar *mapping,uchar *buff,uint length);
public:
  const char *name;
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
172 173 174
  uint numb;
  CONVERT(const char *name_par,uchar *from_par,uchar *to_par, uint number)
    :from_map(from_par),to_map(to_par),name(name_par),numb(number) {}
bk@work.mysql.com's avatar
bk@work.mysql.com committed
175 176 177 178 179 180
  friend CONVERT *get_convert_set(const char *name_ptr);
  inline void convert(char *a,uint length)
  {
    convert_array(from_map, (uchar*) a,length);
  }
  bool store(String *, const char *,uint);
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
181
  inline uint number() { return numb; }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
182 183 184 185 186 187
};

typedef struct st_copy_info {
  ha_rows records;
  ha_rows deleted;
  ha_rows copied;
188
  ha_rows error_count;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
189
  enum enum_duplicates handle_duplicates;
190
  int escape_char, last_errno;
191 192 193
/* for INSERT ... UPDATE */
  List<Item> *update_fields;
  List<Item> *update_values;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
} 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:
226
  enum Keytype { PRIMARY, UNIQUE, MULTIPLE, FULLTEXT, SPATIAL, FOREIGN_KEY};
bk@work.mysql.com's avatar
bk@work.mysql.com committed
227
  enum Keytype type;
228
  enum ha_key_alg algorithm;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
229
  List<key_part_spec> columns;
230
  const char *name;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
231

232 233 234
  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)
235
  {}
bk@work.mysql.com's avatar
bk@work.mysql.com committed
236 237 238
  ~Key() {}
};

239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259
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)
  {}
};
bk@work.mysql.com's avatar
bk@work.mysql.com committed
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278

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

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

bk@work.mysql.com's avatar
bk@work.mysql.com committed
281 282 283 284 285 286 287 288
class i_string: public ilink
{
public:
  char* ptr;
  i_string():ptr(0) { }
  i_string(char* s) : ptr(s) {}
};

289
/* needed for linked list of two strings for replicate-rewrite-db */
sasha@mysql.sashanet.com's avatar
sasha@mysql.sashanet.com committed
290 291 292 293 294 295
class i_string_pair: public ilink
{
public:
  char* key;
  char* val;
  i_string_pair():key(0),val(0) { }
296
  i_string_pair(char* key_arg, char* val_arg) : key(key_arg),val(val_arg) {}
sasha@mysql.sashanet.com's avatar
sasha@mysql.sashanet.com committed
297 298 299
};


300
class MYSQL_ERROR: public Sql_alloc
301 302
{
public:
303 304 305
  enum enum_warning_level
  { WARN_LEVEL_NOTE, WARN_LEVEL_WARN, WARN_LEVEL_ERROR, WARN_LEVEL_END};

306
  uint code;
307 308
  enum_warning_level level;
  char *msg;
309
  
310 311 312
  MYSQL_ERROR(uint code_arg, enum_warning_level level_arg,
	      const char *msg_arg)
    :code(code_arg), level(level_arg)
313
  {
314
    msg=sql_strdup(msg_arg);
315 316
  }
};
sasha@mysql.sashanet.com's avatar
sasha@mysql.sashanet.com committed
317

318 319 320 321 322 323

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

typedef struct st_prep_stmt
{
  THD *thd;
venu@myvenu.com's avatar
venu@myvenu.com committed
324
  Item_param **param;
325 326 327 328 329 330
  Item *free_list;
  MEM_ROOT mem_root;
  ulong stmt_id;
  uint param_count;
  uint last_errno;
  char last_error[MYSQL_ERRMSG_SIZE];
venu@myvenu.com's avatar
venu@myvenu.com committed
331
  bool error_in_prepare, long_data_used;
332 333 334
} PREP_STMT;


bk@work.mysql.com's avatar
bk@work.mysql.com committed
335
class delayed_insert;
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
336
class select_result;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
337

338 339 340 341 342
#define THD_SENTRY_MAGIC 0xfeedd1ff
#define THD_SENTRY_GONE  0xdeadbeef

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

343 344
struct system_variables
{
345 346
  ulonglong myisam_max_extra_sort_file_size;
  ulonglong myisam_max_sort_file_size;
347 348
  ulonglong select_limit;
  ulonglong max_join_size;
349
  ulong bulk_insert_buff_size;
350 351
  ulong join_buff_size;
  ulong long_query_time;
352
  ulong max_allowed_packet;
353
  ulong max_error_count;
354
  ulong max_heap_table_size;
355 356
  ulong max_prep_stmt_count;
  ulong max_sort_length;
357
  ulong max_tmp_tables;
358 359
  ulong myisam_sort_buff_size;
  ulong net_buffer_length;
360
  ulong net_interactive_timeout;
361
  ulong net_read_timeout;
362
  ulong net_retry_count;
363
  ulong net_wait_timeout;
364 365 366 367
  ulong net_write_timeout;
  ulong query_cache_type;
  ulong read_buff_size;
  ulong read_rnd_buff_size;
368
  ulong sortbuff_size;
369
  ulong table_type;
370
  ulong tmp_table_size;
371
  ulong tx_isolation;
372

373 374
  my_bool log_warnings;
  my_bool low_priority_updates; 
375

376 377
  CONVERT	*convert_set;
  CHARSET_INFO 	*thd_charset;
378 379 380 381 382 383 384
};


/*
  For each client connection we create a separate thread with THD serving as
  a thread/connection descriptor
*/
385

bk@work.mysql.com's avatar
bk@work.mysql.com committed
386 387
class THD :public ilink {
public:
388 389 390
  NET	  net;				// client connection descriptor
  LEX	  lex;				// parse tree descriptor
  MEM_ROOT mem_root;			// 1 command-life memory pool
391
  MEM_ROOT con_root;                    // connection-life memory
392
  MEM_ROOT warn_root;			// For warnings and errors
393 394 395
  Protocol *protocol;			// Current protocol
  Protocol_simple protocol_simple;	// Normal protocol
  Protocol_prep protocol_prep;		// Binary protocol
396
  HASH    user_vars;			// hash for user variables
397
  TREE	  prepared_statements;
398 399 400 401
  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
402 403
  pthread_mutex_t LOCK_delete;		// Locked before thd is deleted

404 405 406 407 408 409 410
  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;

411 412 413 414
  /*
    host - host of the client
    user - user of the client, set to NULL until the user has been read from
     the connection
415
    priv_user - The user privilege we are using. May be '' for anonymous user.
416 417 418 419
    db - currently selected database
    ip - client IP
   */
  
bk@work.mysql.com's avatar
bk@work.mysql.com committed
420
  char	  *host,*user,*priv_user,*db,*ip;
421 422 423 424 425 426 427 428
  /* 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;
 
  uint client_capabilities;		/* What the client supports */
  /* Determines if which non-standard SQL behaviour should be enabled */
  uint sql_mode;
429
  uint max_client_packet_length;
430 431
  ulong master_access;			/* Global privileges from mysql.user */
  ulong db_access;			/* Privileges for current db */
432 433 434 435 436 437

  /*
    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
438
  */
serg@serg.mysql.com's avatar
serg@serg.mysql.com committed
439
  TABLE   *open_tables,*temporary_tables, *handler_tables;
440
  // TODO: document the variables below
441 442 443 444
  MYSQL_LOCK	*lock;				/* Current locks */
  MYSQL_LOCK	*locked_tables;			/* Tables locked with LOCK */
  ULL		*ull;
  PREP_STMT	*last_prepared_stmt;
445 446 447
#ifndef DBUG_OFF
  uint dbug_sentry; // watch out for memory corruption
#endif  
bk@work.mysql.com's avatar
bk@work.mysql.com committed
448 449
  struct st_my_thread_var *mysys_var;
  enum enum_server_command command;
450
  uint32     server_id;
451
  uint32     file_id;			// for LOAD DATA INFILE
bk@work.mysql.com's avatar
bk@work.mysql.com committed
452
  const char *where;
453 454
  time_t     start_time,time_after_lock,user_time;
  time_t     connect_time,thr_create_time; // track down slow pthread_create
bk@work.mysql.com's avatar
bk@work.mysql.com committed
455 456 457
  thr_lock_type update_lock_default;
  delayed_insert *di;
  struct st_transactions {
458
    IO_CACHE trans_log;
459 460
    THD_TRANS all;			// Trans since BEGIN WORK
    THD_TRANS stmt;			// Trans for current statement
bk@work.mysql.com's avatar
bk@work.mysql.com committed
461
    uint bdb_lock_count;
462 463 464 465 466 467 468 469 470 471 472 473 474

    /* 
       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));
    }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
475
  } transaction;
serg@serg.mysql.com's avatar
serg@serg.mysql.com committed
476
  Item	     *free_list, *handler_items;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
477 478 479 480
  Field      *dupp_field;
#ifndef __WIN__
  sigset_t signals,block_signals;
#endif
481 482
#ifdef SIGNAL_WITH_VIO_CLOSE
  Vio* active_vio;
483
#endif  
484 485
  ulonglong  next_insert_id,last_insert_id,current_insert_id,
             limit_found_rows;
486 487
  ha_rows    select_limit, offset_limit, cuted_fields,
             sent_row_count, examined_row_count;
488
  table_map  used_tables;
489
  USER_CONN *user_connect;
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
490
  CHARSET_INFO *db_charset;   
491
  List<Item> *possible_loops; // Items that may cause loops in subselects
492 493 494
  List	     <MYSQL_ERROR> warn_list;  
  uint	     warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_END];
  uint	     total_warn_count, old_total_warn_count;
495
  ulong	     query_id, warn_id, version, options, thread_id, col_access;
496
  ulong      current_stmt_id;
497
  ulong	     rand_saved_seed1, rand_saved_seed2;
498
  long	     dbug_thread_id;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
499
  pthread_t  real_id;
500
  uint	     current_tablenr,tmp_table,cond_count;
501 502
  uint	     server_status,open_options;
  uint32     query_length;
503
  uint32     db_length;
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
504
  uint       select_number;             //number of select (used for EXPLAIN)
505
  uint       check_loops_counter;       //last id used to check loops
506 507
  /* variables.transaction_isolation is reset to this after each commit */
  enum_tx_isolation session_tx_isolation;
peter@mysql.com's avatar
peter@mysql.com committed
508 509 510 511
             // extend scramble to handle new auth
  char	     scramble[SCRAMBLE41_LENGTH+1];
             // old scramble is needed to handle old clients
  char       old_scramble[SCRAMBLE_LENGTH+1];
512
  uint8	     query_cache_type;		// type of query cache processing
513
  bool       slave_thread;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
514 515
  bool	     set_query_id,locked,count_cuted_fields,some_tables_deleted;
  bool	     no_errors, allow_sum_func, password, fatal_error;
nick@mysql.com's avatar
nick@mysql.com committed
516
  bool	     query_start_used,last_insert_id_used,insert_id_used,rand_used;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
517
  bool	     system_thread,in_lock_tables,global_read_lock;
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
518
  bool       query_error, bootstrap, cleanup_done;
519
  bool	     volatile killed;
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
520
  bool       prepare_command;
521

522 523 524 525 526
  /*
    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
  */
527
  LOG_INFO*  current_linfo;
528 529 530 531 532 533
  /*
    In slave thread we need to know in behalf of which
    thread the query is being run to replicate temp tables properly
  */
  ulong	     slave_proxy_id;
  NET*       slave_net;			// network connection from slave -> m.
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
534
  my_off_t   log_pos;
535 536 537 538 539 540 541
  /* Used by the sys_var class to store temporary values */
  union
  {
    my_bool my_bool_value;
    long    long_value;
  } sys_var_tmp;

bk@work.mysql.com's avatar
bk@work.mysql.com committed
542 543
  THD();
  ~THD();
544 545
  void init(void);
  void change_user(void);
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
546
  void cleanup(void);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
547
  bool store_globals();
548 549
#ifdef SIGNAL_WITH_VIO_CLOSE
  inline void set_active_vio(Vio* vio)
550
  {
551
    pthread_mutex_lock(&LOCK_delete);
552
    active_vio = vio;
553
    pthread_mutex_unlock(&LOCK_delete);
554
  }
555
  inline void clear_active_vio()
556
  {
557
    pthread_mutex_lock(&LOCK_delete);
558
    active_vio = 0;
559
    pthread_mutex_unlock(&LOCK_delete);
560
  }
561
  void THD::close_active_vio();
562
#endif  
563
  void awake(bool prepare_to_die);
564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580
  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);
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
581
  inline time_t query_start() { query_start_used=1; return start_time; }
monty@donna.mysql.com's avatar
monty@donna.mysql.com committed
582
  inline void	set_time()    { if (user_time) start_time=time_after_lock=user_time; else time_after_lock=time(&start_time); }
583
  inline void	end_time()    { time(&start_time); }
monty@donna.mysql.com's avatar
monty@donna.mysql.com committed
584
  inline void	set_time(time_t t) { time_after_lock=start_time=user_time=t; }
585
  inline void	lock_time()   { time(&time_after_lock); }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
586 587 588 589 590 591 592 593 594 595 596
  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;
  }
597 598 599 600
  inline ulonglong found_rows(void)
  {
    return limit_found_rows;
  }                                                                         
601 602
  inline bool active_transaction()
  {
603
#ifdef USING_TRANSACTIONS    
604
    return (transaction.all.bdb_tid != 0 ||
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
605
	    transaction.all.innodb_active_trans != 0);
606 607 608
#else
    return 0;
#endif
609
  }
610 611 612 613 614 615 616 617 618 619
  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); }
620 621 622
  inline char *strmake(const char *str, uint size)
  { return strmake_root(&mem_root,str,size); }
  inline char *memdup(const char *str, uint size)
623
  { return memdup_root(&mem_root,str,size); }
624 625 626 627 628 629 630
  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;
  }
631 632 633 634 635
  inline gptr trans_alloc(unsigned int size) 
  { 
    return alloc_root(&transaction.mem_root,size);
  }
  void add_changed_table(TABLE *table);
636 637
  void add_changed_table(const char *key, long key_length);
  CHANGED_TABLE_LIST * changed_table_dup(const char *key, long key_length);
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
638
  int send_explain_fields(select_result *result);
639 640 641 642 643 644
  inline void clear_error()
  {
    net.last_error[0]= 0;
    net.last_errno= 0;
    net.report_error= 0;
  }
645
  void add_possible_loop(Item *);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
646 647
};

bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
648 649 650 651
/*
  Used to hold information about file and file structure in exchainge 
  via non-DB file (...INTO OUTFILE..., ...LOAD DATA...)
*/
bk@work.mysql.com's avatar
bk@work.mysql.com committed
652 653 654 655 656 657 658 659 660 661 662 663 664 665 666
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"

/*
667
  This is used to get result from a select
bk@work.mysql.com's avatar
bk@work.mysql.com committed
668 669
*/

670 671
class JOIN;

672
void send_error(THD *thd, uint sql_errno=0, const char *err=0);
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
673

bk@work.mysql.com's avatar
bk@work.mysql.com committed
674 675 676
class select_result :public Sql_alloc {
protected:
  THD *thd;
677
  SELECT_LEX_UNIT *unit;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
678 679 680
public:
  select_result();
  virtual ~select_result() {};
681 682 683 684 685
  virtual int prepare(List<Item> &list, SELECT_LEX_UNIT *u)
  {
    unit= u;
    return 0;
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
686 687
  virtual bool send_fields(List<Item> &list,uint flag)=0;
  virtual bool send_data(List<Item> &items)=0;
688
  virtual bool initialize_tables (JOIN *join=0) { return 0; }
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
689 690
  virtual void send_error(uint errcode,const char *err)
  {
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
691
    my_message(errcode, err, MYF(0));
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
692
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717
  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();
718
  int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
719 720 721 722 723 724 725
  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();
};

monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
726

bk@work.mysql.com's avatar
bk@work.mysql.com committed
727 728 729 730 731 732 733 734 735 736
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();
737
  int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
738 739 740 741 742 743
  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();
};
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
744 745


bk@work.mysql.com's avatar
bk@work.mysql.com committed
746
class select_insert :public select_result {
747
 public:
bk@work.mysql.com's avatar
bk@work.mysql.com committed
748 749 750 751 752
  TABLE *table;
  List<Item> *fields;
  ulonglong last_insert_id;
  COPY_INFO info;

monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
753
  select_insert(TABLE *table_par,List<Item> *fields_par,enum_duplicates duplic)
754 755
    :table(table_par),fields(fields_par), last_insert_id(0)
  {
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
756 757 758
    bzero((char*) &info,sizeof(info));
    info.handle_duplicates=duplic;
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
759
  ~select_insert();
760
  int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
761 762
  bool send_fields(List<Item> &list, uint flag)
  { return 0; }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
763 764 765 766 767
  bool send_data(List<Item> &items);
  void send_error(uint errcode,const char *err);
  bool send_eof();
};

monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
768

bk@work.mysql.com's avatar
bk@work.mysql.com committed
769 770 771 772 773 774 775 776 777 778 779 780 781 782
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,
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
783 784
		 List<Item> &select_fields,enum_duplicates duplic)
    :select_insert (NULL, &select_fields, duplic), db(db_name),
bk@work.mysql.com's avatar
bk@work.mysql.com committed
785 786 787 788
    name(table_name), extra_fields(&fields_par),keys(&keys_par),
    create_info(create_info_par),
    lock(0)
    {}
789
  int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
790 791 792 793 794
  bool send_data(List<Item> &values);
  bool send_eof();
  void abort();
};

monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
795 796 797 798
class select_union :public select_result {
 public:
  TABLE *table;
  COPY_INFO info;
799
  TMP_TABLE_PARAM *tmp_table_param;
800
  bool not_describe;
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
801 802 803

  select_union(TABLE *table_par);
  ~select_union();
804
  int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
805 806 807 808 809 810 811
  bool send_fields(List<Item> &list, uint flag)
  { return 0; }
  bool send_data(List<Item> &items);
  bool send_eof();
  bool flush();
};

812
/* Base subselect interface class */
813 814
class select_subselect :public select_result
{
815
protected:
816 817 818 819
  Item_subselect *item;
public:
  select_subselect(Item_subselect *item);
  bool send_fields(List<Item> &list, uint flag) { return 0; };
820
  bool send_data(List<Item> &items)=0;
821
  bool send_eof() { return 0; };
822

823 824 825
  friend class Ttem_subselect;
};

826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841
/* Single value subselect interface class */
class select_singleval_subselect :public select_subselect
{
public:
  select_singleval_subselect(Item_subselect *item):select_subselect(item){}
  bool send_data(List<Item> &items);
};

/* 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);
};

bk@work.mysql.com's avatar
bk@work.mysql.com committed
842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867
/* 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 */
  my_bool reverse;			/* if descending sort */
  Item_result result_type;		/* Type of item */
} 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 */

class Table_ident :public Sql_alloc {
 public:
  LEX_STRING db;
  LEX_STRING table;
868 869 870
  SELECT_LEX_UNIT *sel;
  inline Table_ident(LEX_STRING db_arg, LEX_STRING table_arg, bool force)
    :table(table_arg), sel((SELECT_LEX_UNIT *)0)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
871 872 873 874 875 876
  {
    if (!force && (current_thd->client_capabilities & CLIENT_NO_SCHEMA))
      db.str=0;
    else
      db= db_arg;
  }
877 878 879 880 881 882 883 884 885
  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) 
  {
    db.str=0; table.str=(char *)""; table.length=0;
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
886
  inline void change_db(char *db_name)
887 888 889
  {
    db.str= db_name; db.length= (uint) strlen(db_name);
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
890 891 892 893 894 895 896 897
};

// this is needed for user_vars hash
class user_var_entry
{
 public:
  LEX_STRING name;
  char *value;
898
  ulong length, update_query_id;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
899
  Item_result type;
900
  CHARSET_INFO *var_charset;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
901 902
};

903 904 905 906 907 908 909 910
/* 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;
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
911
  byte *record_pointers;
912 913 914 915
  bool flush();

public:
  ulong elements;
916 917
  Unique(qsort_cmp2 comp_func, void * comp_func_fixed_arg,
	 uint size, ulong max_in_memory_size_arg);
918
  ~Unique();
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
919
  inline bool unique_add(gptr ptr)
920 921 922
  {
    if (tree.elements_in_tree > max_elements && flush())
      return 1;
923
    return !tree_insert(&tree, ptr, 0, tree.custom_arg);
924 925 926 927
  }

  bool get(TABLE *table);

928 929
  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);
930
};
931

monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
932 933 934
class multi_delete : public select_result
{
  TABLE_LIST *delete_tables, *table_being_deleted;
935
#ifdef SINISAS_STRIP
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
936 937
  IO_CACHE **tempfiles;
  byte *memory_lane;
938
#else
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
939
  Unique  **tempfiles;
940
#endif
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
941 942 943 944 945 946 947 948 949 950
  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,
951
 		   uint flag) { return 0; }
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
952 953 954 955 956 957 958
  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();
};

959

960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977
class multi_update : public select_result
{
  TABLE_LIST *all_tables, *update_tables, *table_being_updated;
  THD *thd;
  TABLE **tmp_tables, *main_table;
  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();
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
978
  int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
979 980 981 982 983 984 985
  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();
};
986 987


Sinisa@sinisa.nasamreza.org's avatar
Sinisa@sinisa.nasamreza.org committed
988 989 990
class select_dumpvar :public select_result {
  ha_rows row_count;
public:
991 992 993
  List<LEX_STRING> var_list;
  List<Item_func_set_user_var> vars;
  select_dumpvar(void)  { var_list.empty(); vars.empty(); row_count=0;}
Sinisa@sinisa.nasamreza.org's avatar
Sinisa@sinisa.nasamreza.org committed
994
  ~select_dumpvar() {}
995 996
  int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
  bool send_fields(List<Item> &list, uint flag) {return 0;}
Sinisa@sinisa.nasamreza.org's avatar
Sinisa@sinisa.nasamreza.org committed
997 998 999
  bool send_data(List<Item> &items);
  bool send_eof();
};