~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_class.cc

  • Committer: Monty Taylor
  • Date: 2008-08-04 19:37:18 UTC
  • mto: (261.2.2 codestyle)
  • mto: This revision was merged to the branch mainline in revision 262.
  • Revision ID: monty@inaugust.com-20080804193718-f0rz13uli4429ozb
Changed gettext_noop() to N_()

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 
 *
4
 
 *  Copyright (C) 2008 Sun Microsystems
5
 
 *
6
 
 *  This program is free software; you can redistribute it and/or modify
7
 
 *  it under the terms of the GNU General Public License as published by
8
 
 *  the Free Software Foundation; version 2 of the License.
9
 
 *
10
 
 *  This program is distributed in the hope that it will be useful,
11
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 *  GNU General Public License for more details.
14
 
 *
15
 
 *  You should have received a copy of the GNU General Public License
16
 
 *  along with this program; if not, write to the Free Software
17
 
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
 
 */
 
1
/* Copyright (C) 2000-2006 MySQL AB
 
2
 
 
3
   This program is free software; you can redistribute it and/or modify
 
4
   it under the terms of the GNU General Public License as published by
 
5
   the Free Software Foundation; version 2 of the License.
 
6
 
 
7
   This program is distributed in the hope that it will be useful,
 
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
   GNU General Public License for more details.
 
11
 
 
12
   You should have received a copy of the GNU General Public License
 
13
   along with this program; if not, write to the Free Software
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
19
15
 
20
16
 
21
17
/*****************************************************************************
22
18
**
23
 
** This file implements classes defined in session.h
 
19
** This file implements classes defined in sql_class.h
24
20
** Especially the classes to handle a result from a select
25
21
**
26
22
*****************************************************************************/
27
 
#include <drizzled/server_includes.h>
28
 
#include <drizzled/session.h>
29
 
#include <drizzled/replication/rli.h>
30
 
#include <drizzled/replication/record.h>
31
 
#include <drizzled/log_event.h>
 
23
 
 
24
#ifdef USE_PRAGMA_IMPLEMENTATION
 
25
#pragma implementation                          // gcc: Class implementation
 
26
#endif
 
27
 
 
28
#include "mysql_priv.h"
 
29
#include "rpl_rli.h"
 
30
#include "rpl_record.h"
 
31
#include "slave.h"
 
32
#include "log_event.h"
32
33
#include <sys/stat.h>
33
34
#include <mysys/thr_alarm.h>
34
35
#include <mysys/mysys_err.h>
35
 
#include <drizzled/error.h>
36
 
#include <drizzled/query_id.h>
37
 
#include <drizzled/data_home.h>
38
 
#include <drizzled/sql_base.h>
 
36
#include <drizzled/drizzled_error_messages.h>
39
37
 
40
 
extern scheduler_functions thread_scheduler;
41
38
/*
42
39
  The following is used to initialise Table_ident with a internal
43
40
  table name
45
42
char internal_table_name[2]= "*";
46
43
char empty_c_string[1]= {0};    /* used for not defined db */
47
44
 
48
 
const char * const Session::DEFAULT_WHERE= "field list";
 
45
const char * const THD::DEFAULT_WHERE= "field list";
49
46
 
50
47
 
51
48
/*****************************************************************************
68
65
** User variables
69
66
****************************************************************************/
70
67
 
71
 
extern "C" unsigned char *get_var_key(user_var_entry *entry, size_t *length,
 
68
extern "C" uchar *get_var_key(user_var_entry *entry, size_t *length,
72
69
                              bool not_used __attribute__((unused)))
73
70
{
74
71
  *length= entry->name.length;
75
 
  return (unsigned char*) entry->name.str;
 
72
  return (uchar*) entry->name.str;
76
73
}
77
74
 
78
75
extern "C" void free_user_var(user_var_entry *entry)
79
76
{
80
77
  char *pos= (char*) entry+ALIGN_SIZE(sizeof(*entry));
81
78
  if (entry->value && entry->value != pos)
82
 
    free(entry->value);
83
 
  free((char*) entry);
 
79
    my_free(entry->value, MYF(0));
 
80
  my_free((char*) entry,MYF(0));
84
81
}
85
82
 
86
83
bool Key_part_spec::operator==(const Key_part_spec& other) const
94
91
  Construct an (almost) deep copy of this key. Only those
95
92
  elements that are known to never change are not copied.
96
93
  If out of memory, a partial copy is returned and an error is set
97
 
  in Session.
 
94
  in THD.
98
95
*/
99
96
 
100
97
Key::Key(const Key &rhs, MEM_ROOT *mem_root)
111
108
  Construct an (almost) deep copy of this foreign key. Only those
112
109
  elements that are known to never change are not copied.
113
110
  If out of memory, a partial copy is returned and an error is set
114
 
  in Session.
 
111
  in THD.
115
112
*/
116
113
 
117
114
Foreign_key::Foreign_key(const Foreign_key &rhs, MEM_ROOT *mem_root)
146
143
  if (a->generated)
147
144
  {
148
145
    if (b->generated && a->columns.elements > b->columns.elements)
149
 
      std::swap(a, b);                       // Put shorter key in 'a'
 
146
      swap_variables(Key*, a, b);               // Put shorter key in 'a'
150
147
  }
151
148
  else
152
149
  {
153
150
    if (!b->generated)
154
151
      return true;                              // No foreign key
155
 
    std::swap(a, b);                       // Put generated key in 'a'
 
152
    swap_variables(Key*, a, b);                 // Put generated key in 'a'
156
153
  }
157
154
 
158
155
  /* Test if 'a' is a prefix of 'b' */
192
189
}
193
190
 
194
191
 
195
 
/*
196
 
  Check if the foreign key options are compatible with columns
197
 
  on which the FK is created.
198
 
 
199
 
  RETURN
200
 
    0   Key valid
201
 
    1   Key invalid
202
 
*/
203
 
bool Foreign_key::validate(List<Create_field> &table_fields)
204
 
{
205
 
  Create_field  *sql_field;
206
 
  Key_part_spec *column;
207
 
  List_iterator<Key_part_spec> cols(columns);
208
 
  List_iterator<Create_field> it(table_fields);
209
 
  while ((column= cols++))
210
 
  {
211
 
    it.rewind();
212
 
    while ((sql_field= it++) &&
213
 
           my_strcasecmp(system_charset_info,
214
 
                         column->field_name.str,
215
 
                         sql_field->field_name)) {}
216
 
    if (!sql_field)
217
 
    {
218
 
      my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name.str);
219
 
      return true;
220
 
    }
221
 
    if (type == Key::FOREIGN_KEY && sql_field->vcol_info)
222
 
    {
223
 
      if (delete_opt == FK_OPTION_SET_NULL)
224
 
      {
225
 
        my_error(ER_WRONG_FK_OPTION_FOR_VIRTUAL_COLUMN, MYF(0), 
226
 
                 "ON DELETE SET NULL");
227
 
        return true;
228
 
      }
229
 
      if (update_opt == FK_OPTION_SET_NULL)
230
 
      {
231
 
        my_error(ER_WRONG_FK_OPTION_FOR_VIRTUAL_COLUMN, MYF(0), 
232
 
                 "ON UPDATE SET NULL");
233
 
        return true;
234
 
      }
235
 
      if (update_opt == FK_OPTION_CASCADE)
236
 
      {
237
 
        my_error(ER_WRONG_FK_OPTION_FOR_VIRTUAL_COLUMN, MYF(0), 
238
 
                 "ON UPDATE CASCADE");
239
 
        return true;
240
 
      }
241
 
    }
242
 
  }
243
 
  return false;
244
 
}
245
 
 
246
 
 
247
192
/****************************************************************************
248
193
** Thread specific functions
249
194
****************************************************************************/
261
206
extern "C" int mysql_tmpfile(const char *prefix)
262
207
{
263
208
  char filename[FN_REFLEN];
264
 
  File fd = create_temp_file(filename, drizzle_tmpdir, prefix,
265
 
                             O_CREAT | O_EXCL | O_RDWR,
 
209
  File fd = create_temp_file(filename, mysql_tmpdir, prefix,
 
210
                             O_CREAT | O_EXCL | O_RDWR | O_TEMPORARY,
266
211
                             MYF(MY_WME));
267
212
  if (fd >= 0) {
 
213
    /*
 
214
      This can be removed once the following bug is fixed:
 
215
      Bug #28903  create_temp_file() doesn't honor O_TEMPORARY option
 
216
                  (file not removed) (Unix)
 
217
    */
268
218
    unlink(filename);
269
219
  }
270
220
 
273
223
 
274
224
 
275
225
extern "C"
276
 
int session_in_lock_tables(const Session *session)
277
 
{
278
 
  return test(session->in_lock_tables);
279
 
}
280
 
 
281
 
 
282
 
extern "C"
283
 
int session_tablespace_op(const Session *session)
284
 
{
285
 
  return test(session->tablespace_op);
286
 
}
287
 
 
288
 
 
289
 
/**
290
 
   Set the process info field of the Session structure.
291
 
 
292
 
   This function is used by plug-ins. Internally, the
293
 
   Session::set_proc_info() function should be used.
294
 
 
295
 
   @see Session::set_proc_info
296
 
 */
297
 
extern "C" void
298
 
set_session_proc_info(Session *session, const char *info)
299
 
{
300
 
  session->set_proc_info(info);
301
 
}
302
 
 
303
 
extern "C"
304
 
const char *get_session_proc_info(Session *session)
305
 
{
306
 
  return session->get_proc_info();
307
 
}
308
 
 
309
 
extern "C"
310
 
void **session_ha_data(const Session *session, const struct handlerton *hton)
311
 
{
312
 
  return (void **) &session->ha_data[hton->slot].ha_ptr;
313
 
}
314
 
 
315
 
extern "C"
316
 
int64_t session_test_options(const Session *session, int64_t test_options)
317
 
{
318
 
  return session->options & test_options;
319
 
}
320
 
 
321
 
extern "C"
322
 
int session_sql_command(const Session *session)
323
 
{
324
 
  return (int) session->lex->sql_command;
325
 
}
326
 
 
327
 
extern "C"
328
 
int session_tx_isolation(const Session *session)
329
 
{
330
 
  return (int) session->variables.tx_isolation;
331
 
}
332
 
 
333
 
extern "C"
334
 
void session_inc_row_count(Session *session)
335
 
{
336
 
  session->row_count++;
 
226
int thd_in_lock_tables(const THD *thd)
 
227
{
 
228
  return test(thd->in_lock_tables);
 
229
}
 
230
 
 
231
 
 
232
extern "C"
 
233
int thd_tablespace_op(const THD *thd)
 
234
{
 
235
  return test(thd->tablespace_op);
 
236
}
 
237
 
 
238
 
 
239
extern "C"
 
240
const char *set_thd_proc_info(THD *thd, const char *info,
 
241
                              const char *calling_function __attribute__((unused)),
 
242
                              const char *calling_file __attribute__((unused)),
 
243
                              const unsigned int calling_line __attribute__((unused)))
 
244
{
 
245
  const char *old_info= thd->proc_info;
 
246
  thd->proc_info= info;
 
247
  return old_info;
 
248
}
 
249
 
 
250
extern "C"
 
251
void **thd_ha_data(const THD *thd, const struct handlerton *hton)
 
252
{
 
253
  return (void **) &thd->ha_data[hton->slot].ha_ptr;
 
254
}
 
255
 
 
256
extern "C"
 
257
int64_t thd_test_options(const THD *thd, int64_t test_options)
 
258
{
 
259
  return thd->options & test_options;
 
260
}
 
261
 
 
262
extern "C"
 
263
int thd_sql_command(const THD *thd)
 
264
{
 
265
  return (int) thd->lex->sql_command;
 
266
}
 
267
 
 
268
extern "C"
 
269
int thd_tx_isolation(const THD *thd)
 
270
{
 
271
  return (int) thd->variables.tx_isolation;
 
272
}
 
273
 
 
274
extern "C"
 
275
void thd_inc_row_count(THD *thd)
 
276
{
 
277
  thd->row_count++;
 
278
}
 
279
 
 
280
/*
 
281
  Dumps a text description of a thread, its security context
 
282
  (user, host) and the current query.
 
283
 
 
284
  SYNOPSIS
 
285
    thd_security_context()
 
286
    thd                 current thread context
 
287
    buffer              pointer to preferred result buffer
 
288
    length              length of buffer
 
289
    max_query_len       how many chars of query to copy (0 for all)
 
290
 
 
291
  RETURN VALUES
 
292
    pointer to string
 
293
*/
 
294
extern "C"
 
295
char *thd_security_context(THD *thd, char *buffer, unsigned int length,
 
296
                           unsigned int max_query_len)
 
297
{
 
298
  String str(buffer, length, &my_charset_latin1);
 
299
  const Security_context *sctx= &thd->main_security_ctx;
 
300
  char header[64];
 
301
  int len;
 
302
 
 
303
  len= snprintf(header, sizeof(header),
 
304
                "MySQL thread id %lu, query id %lu",
 
305
                thd->thread_id, (ulong) thd->query_id);
 
306
  str.length(0);
 
307
  str.append(header, len);
 
308
 
 
309
  if (sctx->host)
 
310
  {
 
311
    str.append(' ');
 
312
    str.append(sctx->host);
 
313
  }
 
314
 
 
315
  if (sctx->ip)
 
316
  {
 
317
    str.append(' ');
 
318
    str.append(sctx->ip);
 
319
  }
 
320
 
 
321
  if (sctx->user)
 
322
  {
 
323
    str.append(' ');
 
324
    str.append(sctx->user);
 
325
  }
 
326
 
 
327
  if (thd->proc_info)
 
328
  {
 
329
    str.append(' ');
 
330
    str.append(thd->proc_info);
 
331
  }
 
332
 
 
333
  if (thd->query)
 
334
  {
 
335
    if (max_query_len < 1)
 
336
      len= thd->query_length;
 
337
    else
 
338
      len= min(thd->query_length, max_query_len);
 
339
    str.append('\n');
 
340
    str.append(thd->query, len);
 
341
  }
 
342
  if (str.c_ptr_safe() == buffer)
 
343
    return buffer;
 
344
  return thd->strmake(str.ptr(), str.length());
337
345
}
338
346
 
339
347
/**
365
373
*/
366
374
 
367
375
void
368
 
Diagnostics_area::set_ok_status(Session *session, ha_rows affected_rows_arg,
 
376
Diagnostics_area::set_ok_status(THD *thd, ha_rows affected_rows_arg,
369
377
                                uint64_t last_insert_id_arg,
370
378
                                const char *message_arg)
371
379
{
378
386
    return;
379
387
  /** Only allowed to report success if has not yet reported an error */
380
388
 
381
 
  m_server_status= session->server_status;
382
 
  m_total_warn_count= session->total_warn_count;
 
389
  m_server_status= thd->server_status;
 
390
  m_total_warn_count= thd->total_warn_count;
383
391
  m_affected_rows= affected_rows_arg;
384
392
  m_last_insert_id= last_insert_id_arg;
385
393
  if (message_arg)
395
403
*/
396
404
 
397
405
void
398
 
Diagnostics_area::set_eof_status(Session *session)
 
406
Diagnostics_area::set_eof_status(THD *thd)
399
407
{
400
408
  /** Only allowed to report eof if has not yet reported an error */
401
409
 
407
415
  if (is_error() || is_disabled())
408
416
    return;
409
417
 
410
 
  m_server_status= session->server_status;
 
418
  m_server_status= thd->server_status;
411
419
  /*
412
420
    If inside a stored procedure, do not return the total
413
421
    number of warnings, since they are not available to the client
414
422
    anyway.
415
423
  */
416
 
  m_total_warn_count= session->total_warn_count;
 
424
  m_total_warn_count= thd->total_warn_count;
417
425
 
418
426
  m_status= DA_EOF;
419
427
}
423
431
*/
424
432
 
425
433
void
426
 
Diagnostics_area::set_error_status(Session *session __attribute__((unused)),
427
 
                                   uint32_t sql_errno_arg,
 
434
Diagnostics_area::set_error_status(THD *thd __attribute__((unused)),
 
435
                                   uint sql_errno_arg,
428
436
                                   const char *message_arg)
429
437
{
430
438
  /*
463
471
}
464
472
 
465
473
 
466
 
Session::Session()
467
 
   :Statement(&main_lex, &main_mem_root,
 
474
THD::THD()
 
475
   :Statement(&main_lex, &main_mem_root, CONVENTIONAL_EXECUTION,
468
476
              /* statement id */ 0),
469
477
   Open_tables_state(refresh_version), rli_fake(0),
470
478
   lock_id(&main_lock_id),
471
 
   user_time(0),
 
479
   user_time(0), in_sub_stmt(0),
472
480
   binlog_table_maps(0), binlog_flags(0UL),
473
481
   arg_of_last_insert_id_function(false),
474
482
   first_successful_insert_id_in_prev_stmt(0),
 
483
   first_successful_insert_id_in_prev_stmt_for_binlog(0),
475
484
   first_successful_insert_id_in_cur_stmt(0),
476
485
   stmt_depends_on_first_successful_insert_id_in_prev_stmt(false),
477
486
   global_read_lock(0),
478
487
   is_fatal_error(0),
479
488
   transaction_rollback_request(0),
480
489
   is_fatal_sub_stmt_error(0),
 
490
   rand_used(0),
 
491
   time_zone_used(0),
481
492
   in_lock_tables(0),
 
493
   bootstrap(0),
482
494
   derived_tables_processing(false),
483
495
   m_lip(NULL)
484
496
{
490
502
    will be re-initialized in init_for_queries().
491
503
  */
492
504
  init_sql_alloc(&main_mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
 
505
  stmt_arena= this;
493
506
  thread_stack= 0;
494
507
  catalog= (char*)"std"; // the only catalog we have for now
495
508
  main_security_ctx.init();
507
520
  limit_found_rows= 0;
508
521
  row_count_func= -1;
509
522
  statement_id_counter= 0UL;
510
 
  // Must be reset to handle error with Session's created for init of mysqld
 
523
  // Must be reset to handle error with THD's created for init of mysqld
511
524
  lex->current_select= 0;
512
525
  start_time=(time_t) 0;
513
526
  start_utime= 0L;
516
529
  slave_thread = 0;
517
530
  memset(&variables, 0, sizeof(variables));
518
531
  thread_id= 0;
 
532
  one_shot_set= 0;
519
533
  file_id = 0;
520
534
  query_id= 0;
521
535
  warn_id= 0;
523
537
  memset(ha_data, 0, sizeof(ha_data));
524
538
  mysys_var=0;
525
539
  binlog_evt_union.do_union= false;
526
 
  dbug_sentry=Session_SENTRY_MAGIC;
 
540
  enable_slow_log= 0;
 
541
  dbug_sentry=THD_SENTRY_MAGIC;
527
542
  net.vio=0;
528
543
  client_capabilities= 0;                       // minimalistic client
529
544
  system_thread= NON_SYSTEM_THREAD;
531
546
  peer_port= 0;                                 // For SHOW PROCESSLIST
532
547
  transaction.m_pending_rows_event= 0;
533
548
  transaction.on= 1;
 
549
#ifdef SIGNAL_WITH_VIO_CLOSE
 
550
  active_vio = 0;
 
551
#endif
534
552
  pthread_mutex_init(&LOCK_delete, MY_MUTEX_INIT_FAST);
535
553
 
536
554
  /* Variables with default values */
537
555
  proc_info="login";
538
 
  where= Session::DEFAULT_WHERE;
 
556
  where= THD::DEFAULT_WHERE;
539
557
  server_id = ::server_id;
540
558
  slave_net = 0;
541
559
  command=COM_CONNECT;
560
578
  protocol= &protocol_text;                     // Default protocol
561
579
  protocol_text.init(this);
562
580
 
563
 
  const Query_id& query_id= Query_id::get_query_id();
564
581
  tablespace_op= false;
565
582
  tmp= sql_rnd();
566
 
  randominit(&rand, tmp + (ulong) &rand, tmp + query_id.value());
 
583
  randominit(&rand, tmp + (ulong) &rand, tmp + (ulong) ::global_query_id);
567
584
  substitute_null_with_insert_id = false;
568
585
  thr_lock_info_init(&lock_info); /* safety: will be reset after start */
569
586
  thr_lock_owner_init(&main_lock_id, &lock_info);
572
589
}
573
590
 
574
591
 
575
 
void Session::push_internal_handler(Internal_error_handler *handler)
 
592
void THD::push_internal_handler(Internal_error_handler *handler)
576
593
{
577
594
  /*
578
595
    TODO: The current implementation is limited to 1 handler at a time only.
579
 
    Session and sp_rcontext need to be modified to use a common handler stack.
 
596
    THD and sp_rcontext need to be modified to use a common handler stack.
580
597
  */
581
598
  assert(m_internal_handler == NULL);
582
599
  m_internal_handler= handler;
583
600
}
584
601
 
585
602
 
586
 
bool Session::handle_error(uint32_t sql_errno, const char *message,
587
 
                       DRIZZLE_ERROR::enum_warning_level level)
 
603
bool THD::handle_error(uint sql_errno, const char *message,
 
604
                       MYSQL_ERROR::enum_warning_level level)
588
605
{
589
606
  if (m_internal_handler)
590
607
  {
595
612
}
596
613
 
597
614
 
598
 
void Session::pop_internal_handler()
 
615
void THD::pop_internal_handler()
599
616
{
600
617
  assert(m_internal_handler != NULL);
601
618
  m_internal_handler= NULL;
602
619
}
603
620
 
604
 
#if defined(__cplusplus)
605
 
extern "C" {
606
 
#endif
607
 
 
608
 
void *session_alloc(Session *session, unsigned int size)
609
 
{
610
 
  return session->alloc(size);
611
 
}
612
 
 
613
 
void *session_calloc(Session *session, unsigned int size)
614
 
{
615
 
  return session->calloc(size);
616
 
}
617
 
 
618
 
char *session_strdup(Session *session, const char *str)
619
 
{
620
 
  return session->strdup(str);
621
 
}
622
 
 
623
 
char *session_strmake(Session *session, const char *str, unsigned int size)
624
 
{
625
 
  return session->strmake(str, size);
626
 
}
627
 
 
628
 
void *session_memdup(Session *session, const void* str, unsigned int size)
629
 
{
630
 
  return session->memdup(str, size);
631
 
}
632
 
 
633
 
void session_get_xid(const Session *session, DRIZZLE_XID *xid)
634
 
{
635
 
  *xid = *(DRIZZLE_XID *) &session->transaction.xid_state.xid;
636
 
}
637
 
 
638
 
#if defined(__cplusplus)
639
 
}
640
 
#endif
 
621
extern "C"
 
622
void *thd_alloc(MYSQL_THD thd, unsigned int size)
 
623
{
 
624
  return thd->alloc(size);
 
625
}
 
626
 
 
627
extern "C"
 
628
void *thd_calloc(MYSQL_THD thd, unsigned int size)
 
629
{
 
630
  return thd->calloc(size);
 
631
}
 
632
 
 
633
extern "C"
 
634
char *thd_strdup(MYSQL_THD thd, const char *str)
 
635
{
 
636
  return thd->strdup(str);
 
637
}
 
638
 
 
639
extern "C"
 
640
char *thd_strmake(MYSQL_THD thd, const char *str, unsigned int size)
 
641
{
 
642
  return thd->strmake(str, size);
 
643
}
 
644
 
 
645
extern "C"
 
646
LEX_STRING *thd_make_lex_string(THD *thd, LEX_STRING *lex_str,
 
647
                                const char *str, unsigned int size,
 
648
                                int allocate_lex_string)
 
649
{
 
650
  return thd->make_lex_string(lex_str, str, size,
 
651
                              (bool) allocate_lex_string);
 
652
}
 
653
 
 
654
extern "C"
 
655
void *thd_memdup(MYSQL_THD thd, const void* str, unsigned int size)
 
656
{
 
657
  return thd->memdup(str, size);
 
658
}
 
659
 
 
660
extern "C"
 
661
void thd_get_xid(const MYSQL_THD thd, MYSQL_XID *xid)
 
662
{
 
663
  *xid = *(MYSQL_XID *) &thd->transaction.xid_state.xid;
 
664
}
641
665
 
642
666
/*
643
667
  Init common variables that has to be reset on start and on change_user
644
668
*/
645
669
 
646
 
void Session::init(void)
 
670
void THD::init(void)
647
671
{
648
672
  pthread_mutex_lock(&LOCK_global_system_variables);
649
 
  plugin_sessionvar_init(this);
650
 
  variables.time_format= date_time_format_copy((Session*) 0,
 
673
  plugin_thdvar_init(this);
 
674
  variables.time_format= date_time_format_copy((THD*) 0,
651
675
                                               variables.time_format);
652
 
  variables.date_format= date_time_format_copy((Session*) 0,
 
676
  variables.date_format= date_time_format_copy((THD*) 0,
653
677
                                               variables.date_format);
654
 
  variables.datetime_format= date_time_format_copy((Session*) 0,
 
678
  variables.datetime_format= date_time_format_copy((THD*) 0,
655
679
                                                   variables.datetime_format);
656
680
  /*
657
681
    variables= global_system_variables above has reset
661
685
  variables.pseudo_thread_id= thread_id;
662
686
  pthread_mutex_unlock(&LOCK_global_system_variables);
663
687
  server_status= SERVER_STATUS_AUTOCOMMIT;
664
 
  options= session_startup_options;
 
688
  options= thd_startup_options;
665
689
 
666
690
  if (variables.max_join_size == HA_POS_ERROR)
667
691
    options |= OPTION_BIG_SELECTS;
675
699
                        TL_WRITE);
676
700
  session_tx_isolation= (enum_tx_isolation) variables.tx_isolation;
677
701
  warn_list.empty();
678
 
  memset(warn_count, 0, sizeof(warn_count));
 
702
  memset((char*) warn_count, 0, sizeof(warn_count));
679
703
  total_warn_count= 0;
680
704
  update_charset();
681
 
  memset(&status_var, 0, sizeof(status_var));
 
705
  reset_current_stmt_binlog_row_based();
 
706
  memset((char *) &status_var, 0, sizeof(status_var));
682
707
}
683
708
 
684
709
 
685
710
/*
686
 
  Init Session for query processing.
 
711
  Init THD for query processing.
687
712
  This has to be called once before we call mysql_parse.
688
 
  See also comments in session.h.
 
713
  See also comments in sql_class.h.
689
714
*/
690
715
 
691
 
void Session::init_for_queries()
 
716
void THD::init_for_queries()
692
717
{
693
718
  set_time(); 
694
719
  ha_enable_transaction(this,true);
699
724
                      variables.trans_alloc_block_size,
700
725
                      variables.trans_prealloc_size);
701
726
  transaction.xid_state.xid.null();
702
 
  transaction.xid_state.in_session=1;
 
727
  transaction.xid_state.in_thd=1;
703
728
}
704
729
 
705
730
 
706
731
/* Do operations that may take a long time */
707
732
 
708
 
void Session::cleanup(void)
 
733
void THD::cleanup(void)
709
734
{
710
735
  assert(cleanup_done == 0);
711
736
 
729
754
  delete_dynamic(&user_var_events);
730
755
  hash_free(&user_vars);
731
756
  close_temporary_tables(this);
732
 
  free((char*) variables.time_format);
733
 
  free((char*) variables.date_format);
734
 
  free((char*) variables.datetime_format);
 
757
  my_free((char*) variables.time_format, MYF(MY_ALLOW_ZERO_PTR));
 
758
  my_free((char*) variables.date_format, MYF(MY_ALLOW_ZERO_PTR));
 
759
  my_free((char*) variables.datetime_format, MYF(MY_ALLOW_ZERO_PTR));
735
760
  
736
761
  if (global_read_lock)
737
762
    unlock_global_read_lock(this);
740
765
  return;
741
766
}
742
767
 
743
 
Session::~Session()
 
768
THD::~THD()
744
769
{
745
 
  Session_CHECK_SENTRY(this);
746
 
  /* Ensure that no one is using Session */
 
770
  THD_CHECK_SENTRY(this);
 
771
  /* Ensure that no one is using THD */
747
772
  pthread_mutex_lock(&LOCK_delete);
748
773
  pthread_mutex_unlock(&LOCK_delete);
749
774
  add_to_status(&global_status_var, &status_var);
751
776
  /* Close connection */
752
777
  if (net.vio)
753
778
  {
754
 
    net_close(&net);
 
779
    vio_delete(net.vio);
755
780
    net_end(&net);
756
781
  }
757
782
  if (!cleanup_done)
758
783
    cleanup();
759
784
 
760
785
  ha_close_connection(this);
761
 
  plugin_sessionvar_cleanup(this);
 
786
  plugin_thdvar_cleanup(this);
762
787
 
763
788
  main_security_ctx.destroy();
764
 
  if (db)
765
 
  {
766
 
    free(db);
767
 
    db= NULL;
768
 
  }
 
789
  safeFree(db);
769
790
  free_root(&warn_root,MYF(0));
770
791
  free_root(&transaction.mem_root,MYF(0));
771
792
  mysys_var=0;                                  // Safety (shouldn't be needed)
772
793
  pthread_mutex_destroy(&LOCK_delete);
773
 
  dbug_sentry= Session_SENTRY_GONE;
 
794
  dbug_sentry= THD_SENTRY_GONE;
774
795
  if (rli_fake)
775
796
  {
776
797
    delete rli_fake;
798
819
 
799
820
void add_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var)
800
821
{
801
 
  ulong *end= (ulong*) ((unsigned char*) to_var +
 
822
  ulong *end= (ulong*) ((uchar*) to_var +
802
823
                        offsetof(STATUS_VAR, last_system_status_var) +
803
824
                        sizeof(ulong));
804
825
  ulong *to= (ulong*) to_var, *from= (ulong*) from_var;
823
844
void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var,
824
845
                        STATUS_VAR *dec_var)
825
846
{
826
 
  ulong *end= (ulong*) ((unsigned char*) to_var + offsetof(STATUS_VAR,
 
847
  ulong *end= (ulong*) ((uchar*) to_var + offsetof(STATUS_VAR,
827
848
                                                  last_system_status_var) +
828
849
                        sizeof(ulong));
829
850
  ulong *to= (ulong*) to_var, *from= (ulong*) from_var, *dec= (ulong*) dec_var;
833
854
}
834
855
 
835
856
 
836
 
void Session::awake(Session::killed_state state_to_set)
 
857
void THD::awake(THD::killed_state state_to_set)
837
858
{
838
 
  Session_CHECK_SENTRY(this);
 
859
  THD_CHECK_SENTRY(this);
839
860
  safe_mutex_assert_owner(&LOCK_delete); 
840
861
 
841
862
  killed= state_to_set;
842
 
  if (state_to_set != Session::KILL_QUERY)
 
863
  if (state_to_set != THD::KILL_QUERY)
843
864
  {
844
865
    thr_alarm_kill(thread_id);
845
866
    if (!slave_thread)
846
867
      thread_scheduler.post_kill_notification(this);
 
868
#ifdef SIGNAL_WITH_VIO_CLOSE
 
869
    if (this != current_thd)
 
870
    {
 
871
      /*
 
872
        In addition to a signal, let's close the socket of the thread that
 
873
        is being killed. This is to make sure it does not block if the
 
874
        signal is lost. This needs to be done only on platforms where
 
875
        signals are not a reliable interruption mechanism.
 
876
 
 
877
        If we're killing ourselves, we know that we're not blocked, so this
 
878
        hack is not used.
 
879
      */
 
880
 
 
881
      close_active_vio();
 
882
    }
 
883
#endif    
847
884
  }
848
885
  if (mysys_var)
849
886
  {
866
903
      current_cond and current_mutex are 0), then the victim will not get
867
904
      a signal and it may wait "forever" on the cond (until
868
905
      we issue a second KILL or the status it's waiting for happens).
869
 
      It's true that we have set its session->killed but it may not
 
906
      It's true that we have set its thd->killed but it may not
870
907
      see it immediately and so may have time to reach the cond_wait().
871
908
    */
872
909
    if (mysys_var->current_cond && mysys_var->current_mutex)
885
922
  sql_alloc() and the structure for the net buffer
886
923
*/
887
924
 
888
 
bool Session::store_globals()
 
925
bool THD::store_globals()
889
926
{
890
927
  /*
891
928
    Assert that thread_stack is initialized: it's necessary to be able
893
930
  */
894
931
  assert(thread_stack);
895
932
 
896
 
  if (pthread_setspecific(THR_Session,  this) ||
897
 
      pthread_setspecific(THR_MALLOC, &mem_root))
 
933
  if (my_pthread_setspecific_ptr(THR_THD,  this) ||
 
934
      my_pthread_setspecific_ptr(THR_MALLOC, &mem_root))
898
935
    return 1;
899
936
  mysys_var=my_thread_var;
900
937
  /*
901
938
    Let mysqld define the thread id (not mysys)
902
 
    This allows us to move Session to different threads if needed.
 
939
    This allows us to move THD to different threads if needed.
903
940
  */
904
941
  mysys_var->id= thread_id;
905
942
  real_id= pthread_self();                      // For debugging
906
943
 
907
944
  /*
908
 
    We have to call thr_lock_info_init() again here as Session may have been
 
945
    We have to call thr_lock_info_init() again here as THD may have been
909
946
    created in another thread
910
947
  */
911
948
  thr_lock_info_init(&lock_info);
917
954
  Cleanup after query.
918
955
 
919
956
  SYNOPSIS
920
 
    Session::cleanup_after_query()
 
957
    THD::cleanup_after_query()
921
958
 
922
959
  DESCRIPTION
923
960
    This function is used to reset thread data to its default state.
929
966
    slave.
930
967
*/
931
968
 
932
 
void Session::cleanup_after_query()
 
969
void THD::cleanup_after_query()
933
970
{
934
971
  /*
935
972
    Reset rand_used so that detection of calls to rand() will save random 
936
973
    seeds if needed by the slave.
 
974
 
 
975
    Do not reset rand_used if inside a stored function or trigger because 
 
976
    only the call to these operations is logged. Thus only the calling 
 
977
    statement needs to detect rand() calls made by its substatements. These
 
978
    substatements must not set rand_used to 0 because it would remove the
 
979
    detection of rand() by the calling statement. 
937
980
  */
 
981
  if (!in_sub_stmt) /* stored functions and triggers are a special case */
938
982
  {
939
983
    /* Forget those values, for next binlogger: */
940
984
    stmt_depends_on_first_successful_insert_id_in_prev_stmt= 0;
941
985
    auto_inc_intervals_in_cur_stmt_for_binlog.empty();
 
986
    rand_used= 0;
942
987
  }
943
988
  if (first_successful_insert_id_in_cur_stmt > 0)
944
989
  {
952
997
  /* Free Items that were created during this execution */
953
998
  free_items();
954
999
  /* Reset where. */
955
 
  where= Session::DEFAULT_WHERE;
 
1000
  where= THD::DEFAULT_WHERE;
956
1001
}
957
1002
 
958
1003
 
966
1011
                              instead of using lex_str value
967
1012
  @return  NULL on failure, or pointer to the LEX_STRING object
968
1013
*/
969
 
LEX_STRING *Session::make_lex_string(LEX_STRING *lex_str,
970
 
                                 const char* str, uint32_t length,
 
1014
LEX_STRING *THD::make_lex_string(LEX_STRING *lex_str,
 
1015
                                 const char* str, uint length,
971
1016
                                 bool allocate_lex_string)
972
1017
{
973
1018
  if (allocate_lex_string)
1000
1045
        In this case to->str will point to 0 and to->length will be 0.
1001
1046
*/
1002
1047
 
1003
 
bool Session::convert_string(LEX_STRING *to, const CHARSET_INFO * const to_cs,
1004
 
                         const char *from, uint32_t from_length,
1005
 
                         const CHARSET_INFO * const from_cs)
 
1048
bool THD::convert_string(LEX_STRING *to, CHARSET_INFO *to_cs,
 
1049
                         const char *from, uint from_length,
 
1050
                         CHARSET_INFO *from_cs)
1006
1051
{
1007
1052
  size_t new_length= to_cs->mbmaxlen * from_length;
1008
 
  uint32_t dummy_errors;
 
1053
  uint dummy_errors;
1009
1054
  if (!(to->str= (char*) alloc(new_length+1)))
1010
1055
  {
1011
1056
    to->length= 0;                              // Safety fix
1022
1067
  Convert string from source character set to target character set inplace.
1023
1068
 
1024
1069
  SYNOPSIS
1025
 
    Session::convert_string
 
1070
    THD::convert_string
1026
1071
 
1027
1072
  DESCRIPTION
1028
1073
    Convert string using convert_buffer - buffer for character set 
1033
1078
   !0   out of memory
1034
1079
*/
1035
1080
 
1036
 
bool Session::convert_string(String *s, const CHARSET_INFO * const from_cs,
1037
 
                         const CHARSET_INFO * const to_cs)
 
1081
bool THD::convert_string(String *s, CHARSET_INFO *from_cs, CHARSET_INFO *to_cs)
1038
1082
{
1039
 
  uint32_t dummy_errors;
 
1083
  uint dummy_errors;
1040
1084
  if (convert_buffer.copy(s->ptr(), s->length(), from_cs, to_cs, &dummy_errors))
1041
1085
    return true;
1042
1086
  /* If convert_buffer >> s copying is more efficient long term */
1054
1098
  Update some cache variables when character set changes
1055
1099
*/
1056
1100
 
1057
 
void Session::update_charset()
 
1101
void THD::update_charset()
1058
1102
{
1059
1103
  uint32_t not_used;
1060
1104
  charset_is_system_charset= !String::needs_conversion(0,charset(),
1071
1115
 
1072
1116
/* routings to adding tables to list of changed in transaction tables */
1073
1117
 
1074
 
inline static void list_include(CHANGED_TableList** prev,
1075
 
                                CHANGED_TableList* curr,
1076
 
                                CHANGED_TableList* new_table)
 
1118
inline static void list_include(CHANGED_TABLE_LIST** prev,
 
1119
                                CHANGED_TABLE_LIST* curr,
 
1120
                                CHANGED_TABLE_LIST* new_table)
1077
1121
{
1078
1122
  if (new_table)
1079
1123
  {
1084
1128
 
1085
1129
/* add table to list of changed in transaction tables */
1086
1130
 
1087
 
void Session::add_changed_table(Table *table)
 
1131
void THD::add_changed_table(TABLE *table)
1088
1132
{
1089
1133
  assert((options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) &&
1090
1134
              table->file->has_transactions());
1094
1138
}
1095
1139
 
1096
1140
 
1097
 
void Session::add_changed_table(const char *key, long key_length)
 
1141
void THD::add_changed_table(const char *key, long key_length)
1098
1142
{
1099
 
  CHANGED_TableList **prev_changed = &transaction.changed_tables;
1100
 
  CHANGED_TableList *curr = transaction.changed_tables;
 
1143
  CHANGED_TABLE_LIST **prev_changed = &transaction.changed_tables;
 
1144
  CHANGED_TABLE_LIST *curr = transaction.changed_tables;
1101
1145
 
1102
1146
  for (; curr; prev_changed = &(curr->next), curr = curr->next)
1103
1147
  {
1126
1170
}
1127
1171
 
1128
1172
 
1129
 
CHANGED_TableList* Session::changed_table_dup(const char *key, long key_length)
 
1173
CHANGED_TABLE_LIST* THD::changed_table_dup(const char *key, long key_length)
1130
1174
{
1131
 
  CHANGED_TableList* new_table = 
1132
 
    (CHANGED_TableList*) trans_alloc(ALIGN_SIZE(sizeof(CHANGED_TableList))+
 
1175
  CHANGED_TABLE_LIST* new_table = 
 
1176
    (CHANGED_TABLE_LIST*) trans_alloc(ALIGN_SIZE(sizeof(CHANGED_TABLE_LIST))+
1133
1177
                                      key_length + 1);
1134
1178
  if (!new_table)
1135
1179
  {
1136
1180
    my_error(EE_OUTOFMEMORY, MYF(ME_BELL),
1137
 
             ALIGN_SIZE(sizeof(TableList)) + key_length + 1);
 
1181
             ALIGN_SIZE(sizeof(TABLE_LIST)) + key_length + 1);
1138
1182
    killed= KILL_CONNECTION;
1139
1183
    return 0;
1140
1184
  }
1141
1185
 
1142
 
  new_table->key= ((char*)new_table)+ ALIGN_SIZE(sizeof(CHANGED_TableList));
 
1186
  new_table->key= ((char*)new_table)+ ALIGN_SIZE(sizeof(CHANGED_TABLE_LIST));
1143
1187
  new_table->next = 0;
1144
1188
  new_table->key_length = key_length;
1145
1189
  ::memcpy(new_table->key, key, key_length);
1147
1191
}
1148
1192
 
1149
1193
 
1150
 
int Session::send_explain_fields(select_result *result)
 
1194
int THD::send_explain_fields(select_result *result)
1151
1195
{
1152
1196
  List<Item> field_list;
1153
1197
  Item *item;
1154
 
  const CHARSET_INFO * const cs= system_charset_info;
 
1198
  CHARSET_INFO *cs= system_charset_info;
1155
1199
  field_list.push_back(new Item_return_int("id",3, DRIZZLE_TYPE_LONGLONG));
1156
1200
  field_list.push_back(new Item_empty_string("select_type", 19, cs));
1157
1201
  field_list.push_back(item= new Item_empty_string("table", NAME_CHAR_LEN, cs));
1186
1230
                              Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF));
1187
1231
}
1188
1232
 
 
1233
#ifdef SIGNAL_WITH_VIO_CLOSE
 
1234
void THD::close_active_vio()
 
1235
{
 
1236
  safe_mutex_assert_owner(&LOCK_delete); 
 
1237
  if (active_vio)
 
1238
  {
 
1239
    vio_close(active_vio);
 
1240
    active_vio = 0;
 
1241
  }
 
1242
  return;
 
1243
}
 
1244
#endif
 
1245
 
1189
1246
 
1190
1247
struct Item_change_record: public ilink
1191
1248
{
1207
1264
/*
1208
1265
  Register an item tree tree transformation, performed by the query
1209
1266
  optimizer. We need a pointer to runtime_memroot because it may be !=
1210
 
  session->mem_root (this may no longer be a true statement)
 
1267
  thd->mem_root (due to possible set_n_backup_active_arena called for thd).
1211
1268
*/
1212
1269
 
1213
 
void Session::nocheck_register_item_tree_change(Item **place, Item *old_value,
 
1270
void THD::nocheck_register_item_tree_change(Item **place, Item *old_value,
1214
1271
                                            MEM_ROOT *runtime_memroot)
1215
1272
{
1216
1273
  Item_change_record *change;
1223
1280
  if (change_mem == 0)
1224
1281
  {
1225
1282
    /*
1226
 
      OOM, session->fatal_error() is called by the error handler of the
 
1283
      OOM, thd->fatal_error() is called by the error handler of the
1227
1284
      memroot. Just return.
1228
1285
    */
1229
1286
    return;
1235
1292
}
1236
1293
 
1237
1294
 
1238
 
void Session::rollback_item_tree_changes()
 
1295
void THD::rollback_item_tree_changes()
1239
1296
{
1240
1297
  I_List_iterator<Item_change_record> it(change_list);
1241
1298
  Item_change_record *change;
1248
1305
}
1249
1306
 
1250
1307
 
 
1308
/**
 
1309
  Check that the endpoint is still available.
 
1310
*/
 
1311
 
 
1312
bool THD::vio_is_connected()
 
1313
{
 
1314
  uint bytes= 0;
 
1315
 
 
1316
  /* End of input is signaled by poll if the socket is aborted. */
 
1317
  if (vio_poll_read(net.vio, 0))
 
1318
    return true;
 
1319
 
 
1320
  /* Socket is aborted if signaled but no data is available. */
 
1321
  if (vio_peek_read(net.vio, &bytes))
 
1322
    return true;
 
1323
 
 
1324
  return bytes ? true : false;
 
1325
}
 
1326
 
 
1327
 
1251
1328
/*****************************************************************************
1252
1329
** Functions to provide a interface to select results
1253
1330
*****************************************************************************/
1254
1331
 
1255
1332
select_result::select_result()
1256
1333
{
1257
 
  session=current_session;
 
1334
  thd=current_thd;
1258
1335
}
1259
1336
 
1260
 
void select_result::send_error(uint32_t errcode,const char *err)
 
1337
void select_result::send_error(uint errcode,const char *err)
1261
1338
{
1262
1339
  my_message(errcode, err, MYF(0));
1263
1340
}
1278
1355
static String default_line_term("\n",default_charset_info);
1279
1356
static String default_escaped("\\",default_charset_info);
1280
1357
static String default_field_term("\t",default_charset_info);
 
1358
static String default_xml_row_term("<row>", default_charset_info);
1281
1359
 
1282
1360
sql_exchange::sql_exchange(char *name, bool flag,
1283
1361
                           enum enum_filetype filetype_arg)
1286
1364
  filetype= filetype_arg;
1287
1365
  field_term= &default_field_term;
1288
1366
  enclosed=   line_start= &my_empty_string;
1289
 
  line_term=  &default_line_term;
 
1367
  line_term=  filetype == FILETYPE_CSV ?
 
1368
              &default_line_term : &default_xml_row_term;
1290
1369
  escaped=    &default_escaped;
1291
1370
  cs= NULL;
1292
1371
}
1293
1372
 
1294
 
bool select_send::send_fields(List<Item> &list, uint32_t flags)
 
1373
bool select_send::send_fields(List<Item> &list, uint flags)
1295
1374
{
1296
1375
  bool res;
1297
 
  if (!(res= session->protocol->send_fields(&list, flags)))
 
1376
  if (!(res= thd->protocol->send_fields(&list, flags)))
1298
1377
    is_result_set_started= 1;
1299
1378
  return res;
1300
1379
}
1329
1408
  /*
1330
1409
    We may be passing the control from mysqld to the client: release the
1331
1410
    InnoDB adaptive hash S-latch to avoid thread deadlocks if it was reserved
1332
 
    by session
 
1411
    by thd
1333
1412
  */
1334
 
  ha_release_temporary_latches(session);
 
1413
  ha_release_temporary_latches(thd);
1335
1414
 
1336
1415
  List_iterator_fast<Item> li(items);
1337
 
  Protocol *protocol= session->protocol;
 
1416
  Protocol *protocol= thd->protocol;
1338
1417
  char buff[MAX_FIELD_WIDTH];
1339
1418
  String buffer(buff, sizeof(buff), &my_charset_bin);
1340
1419
 
1349
1428
      break;
1350
1429
    }
1351
1430
  }
1352
 
  session->sent_row_count++;
1353
 
  if (session->is_error())
 
1431
  thd->sent_row_count++;
 
1432
  if (thd->is_error())
1354
1433
  {
1355
1434
    protocol->remove_last_row();
1356
1435
    return(1);
1357
1436
  }
1358
 
  if (session->vio_ok())
 
1437
  if (thd->vio_ok())
1359
1438
    return(protocol->write());
1360
1439
  return(0);
1361
1440
}
1365
1444
  /* 
1366
1445
    We may be passing the control from mysqld to the client: release the
1367
1446
    InnoDB adaptive hash S-latch to avoid thread deadlocks if it was reserved
1368
 
    by session 
 
1447
    by thd 
1369
1448
  */
1370
 
  ha_release_temporary_latches(session);
 
1449
  ha_release_temporary_latches(thd);
1371
1450
 
1372
1451
  /* Unlock tables before sending packet to gain some speed */
1373
 
  if (session->lock)
 
1452
  if (thd->lock)
1374
1453
  {
1375
 
    mysql_unlock_tables(session, session->lock);
1376
 
    session->lock=0;
 
1454
    mysql_unlock_tables(thd, thd->lock);
 
1455
    thd->lock=0;
1377
1456
  }
1378
 
  ::my_eof(session);
 
1457
  ::my_eof(thd);
1379
1458
  is_result_set_started= 0;
1380
1459
  return false;
1381
1460
}
1385
1464
  Handling writing to file
1386
1465
************************************************************************/
1387
1466
 
1388
 
void select_to_file::send_error(uint32_t errcode,const char *err)
 
1467
void select_to_file::send_error(uint errcode,const char *err)
1389
1468
{
1390
1469
  my_message(errcode, err, MYF(0));
1391
1470
  if (file > 0)
1410
1489
      function, SELECT INTO has to have an own SQLCOM.
1411
1490
      TODO: split from SQLCOM_SELECT
1412
1491
    */
1413
 
    ::my_ok(session,row_count);
 
1492
    ::my_ok(thd,row_count);
1414
1493
  }
1415
1494
  file= -1;
1416
1495
  return error;
1447
1526
 
1448
1527
select_export::~select_export()
1449
1528
{
1450
 
  session->sent_row_count=row_count;
 
1529
  thd->sent_row_count=row_count;
1451
1530
}
1452
1531
 
1453
1532
 
1456
1535
 
1457
1536
  SYNOPSIS
1458
1537
    create_file()
1459
 
    session                     Thread handle
 
1538
    thd                 Thread handle
1460
1539
    path                File name
1461
1540
    exchange            Excange class
1462
1541
    cache               IO cache
1467
1546
*/
1468
1547
 
1469
1548
 
1470
 
static File create_file(Session *session, char *path, sql_exchange *exchange,
 
1549
static File create_file(THD *thd, char *path, sql_exchange *exchange,
1471
1550
                        IO_CACHE *cache)
1472
1551
{
1473
1552
  File file;
1474
 
  uint32_t option= MY_UNPACK_FILENAME | MY_RELATIVE_PATH;
 
1553
  uint option= MY_UNPACK_FILENAME | MY_RELATIVE_PATH;
1475
1554
 
1476
1555
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
1477
1556
  option|= MY_REPLACE_DIR;                      // Force use of db directory
1479
1558
 
1480
1559
  if (!dirname_length(exchange->file_name))
1481
1560
  {
1482
 
    strcpy(path, drizzle_real_data_home);
1483
 
    if (session->db)
1484
 
      strncat(path, session->db, FN_REFLEN-strlen(drizzle_real_data_home)-1);
 
1561
    strxnmov(path, FN_REFLEN-1, mysql_real_data_home, thd->db ? thd->db : "",
 
1562
             NullS);
1485
1563
    (void) fn_format(path, exchange->file_name, path, "", option);
1486
1564
  }
1487
1565
  else
1488
 
    (void) fn_format(path, exchange->file_name, drizzle_real_data_home, "", option);
 
1566
    (void) fn_format(path, exchange->file_name, mysql_real_data_home, "", option);
1489
1567
 
1490
1568
  if (opt_secure_file_priv &&
1491
1569
      strncmp(opt_secure_file_priv, path, strlen(opt_secure_file_priv)))
1527
1605
  if ((uint) strlen(exchange->file_name) + NAME_LEN >= FN_REFLEN)
1528
1606
    strmake(path,exchange->file_name,FN_REFLEN-1);
1529
1607
 
1530
 
  if ((file= create_file(session, path, exchange, &cache)) < 0)
 
1608
  if ((file= create_file(thd, path, exchange, &cache)) < 0)
1531
1609
    return 1;
1532
1610
  /* Check if there is any blobs in data */
1533
1611
  {
1548
1626
  }
1549
1627
  field_term_length=exchange->field_term->length();
1550
1628
  field_term_char= field_term_length ?
1551
 
                   (int) (unsigned char) (*exchange->field_term)[0] : INT_MAX;
 
1629
                   (int) (uchar) (*exchange->field_term)[0] : INT_MAX;
1552
1630
  if (!exchange->line_term->length())
1553
1631
    exchange->line_term=exchange->field_term;   // Use this if it exists
1554
1632
  field_sep_char= (exchange->enclosed->length() ?
1555
 
                  (int) (unsigned char) (*exchange->enclosed)[0] : field_term_char);
 
1633
                  (int) (uchar) (*exchange->enclosed)[0] : field_term_char);
1556
1634
  escape_char=  (exchange->escaped->length() ?
1557
 
                (int) (unsigned char) (*exchange->escaped)[0] : -1);
 
1635
                (int) (uchar) (*exchange->escaped)[0] : -1);
1558
1636
  is_ambiguous_field_sep= test(strchr(ESCAPE_CHARS, field_sep_char));
1559
1637
  is_unsafe_field_sep= test(strchr(NUMERIC_CHARS, field_sep_char));
1560
1638
  line_sep_char= (exchange->line_term->length() ?
1561
 
                 (int) (unsigned char) (*exchange->line_term)[0] : INT_MAX);
 
1639
                 (int) (uchar) (*exchange->line_term)[0] : INT_MAX);
1562
1640
  if (!field_term_length)
1563
1641
    exchange->opt_enclosed=0;
1564
1642
  if (!exchange->enclosed->length())
1570
1648
      (exchange->opt_enclosed && non_string_results &&
1571
1649
       field_term_length && strchr(NUMERIC_CHARS, field_term_char)))
1572
1650
  {
1573
 
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
1651
    push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
1574
1652
                 ER_AMBIGUOUS_FIELD_TERM, ER(ER_AMBIGUOUS_FIELD_TERM));
1575
1653
    is_ambiguous_field_term= true;
1576
1654
  }
1581
1659
}
1582
1660
 
1583
1661
 
1584
 
#define NEED_ESCAPING(x) ((int) (unsigned char) (x) == escape_char    || \
1585
 
                          (enclosed ? (int) (unsigned char) (x) == field_sep_char      \
1586
 
                                    : (int) (unsigned char) (x) == field_term_char) || \
1587
 
                          (int) (unsigned char) (x) == line_sep_char  || \
 
1662
#define NEED_ESCAPING(x) ((int) (uchar) (x) == escape_char    || \
 
1663
                          (enclosed ? (int) (uchar) (x) == field_sep_char      \
 
1664
                                    : (int) (uchar) (x) == field_term_char) || \
 
1665
                          (int) (uchar) (x) == line_sep_char  || \
1588
1666
                          !(x))
1589
1667
 
1590
1668
bool select_export::send_data(List<Item> &items)
1601
1679
  }
1602
1680
  row_count++;
1603
1681
  Item *item;
1604
 
  uint32_t used_length=0,items_left=items.elements;
 
1682
  uint used_length=0,items_left=items.elements;
1605
1683
  List_iterator_fast<Item> li(items);
1606
1684
 
1607
 
  if (my_b_write(&cache,(unsigned char*) exchange->line_start->ptr(),
 
1685
  if (my_b_write(&cache,(uchar*) exchange->line_start->ptr(),
1608
1686
                 exchange->line_start->length()))
1609
1687
    goto err;
1610
1688
  while ((item=li++))
1615
1693
    res=item->str_result(&tmp);
1616
1694
    if (res && enclosed)
1617
1695
    {
1618
 
      if (my_b_write(&cache,(unsigned char*) exchange->enclosed->ptr(),
 
1696
      if (my_b_write(&cache,(uchar*) exchange->enclosed->ptr(),
1619
1697
                     exchange->enclosed->length()))
1620
1698
        goto err;
1621
1699
    }
1627
1705
        {
1628
1706
          null_buff[0]=escape_char;
1629
1707
          null_buff[1]='N';
1630
 
          if (my_b_write(&cache,(unsigned char*) null_buff,2))
 
1708
          if (my_b_write(&cache,(uchar*) null_buff,2))
1631
1709
            goto err;
1632
1710
        }
1633
 
        else if (my_b_write(&cache,(unsigned char*) "NULL",4))
 
1711
        else if (my_b_write(&cache,(uchar*) "NULL",4))
1634
1712
          goto err;
1635
1713
      }
1636
1714
      else
1641
1719
    else
1642
1720
    {
1643
1721
      if (fixed_row_size)
1644
 
        used_length=cmin(res->length(),item->max_length);
 
1722
        used_length=min(res->length(),item->max_length);
1645
1723
      else
1646
1724
        used_length=res->length();
1647
1725
      if ((result_type == STRING_RESULT || is_unsafe_field_sep) &&
1648
1726
           escape_char != -1)
1649
1727
      {
1650
1728
        char *pos, *start, *end;
1651
 
        const CHARSET_INFO * const res_charset= res->charset();
1652
 
        const CHARSET_INFO * const character_set_client= session->variables.
1653
 
                                                            character_set_client;
 
1729
        CHARSET_INFO *res_charset= res->charset();
 
1730
        CHARSET_INFO *character_set_client= thd->variables.
 
1731
                                            character_set_client;
1654
1732
        bool check_second_byte= (res_charset == &my_charset_bin) &&
1655
1733
                                 character_set_client->
1656
1734
                                 escape_with_backslash_is_dangerous;
1687
1765
            If this file is later loaded using this sequence of commands:
1688
1766
            
1689
1767
            mysql> create table t1 (a varchar(128)) character set big5;
1690
 
            mysql> LOAD DATA INFILE 'dump.txt' INTO Table t1;
 
1768
            mysql> LOAD DATA INFILE 'dump.txt' INTO TABLE t1;
1691
1769
            
1692
1770
            then 0x5C will be misinterpreted as the second byte
1693
1771
            of a multi-byte character "0xEE + 0x5C", instead of
1706
1784
 
1707
1785
          if ((NEED_ESCAPING(*pos) ||
1708
1786
               (check_second_byte &&
1709
 
                my_mbcharlen(character_set_client, (unsigned char) *pos) == 2 &&
 
1787
                my_mbcharlen(character_set_client, (uchar) *pos) == 2 &&
1710
1788
                pos + 1 < end &&
1711
1789
                NEED_ESCAPING(pos[1]))) &&
1712
1790
              /*
1714
1792
               valid for ENCLOSED BY characters:
1715
1793
              */
1716
1794
              (enclosed || !is_ambiguous_field_term ||
1717
 
               (int) (unsigned char) *pos != field_term_char))
 
1795
               (int) (uchar) *pos != field_term_char))
1718
1796
          {
1719
1797
            char tmp_buff[2];
1720
 
            tmp_buff[0]= ((int) (unsigned char) *pos == field_sep_char &&
 
1798
            tmp_buff[0]= ((int) (uchar) *pos == field_sep_char &&
1721
1799
                          is_ambiguous_field_sep) ?
1722
1800
                          field_sep_char : escape_char;
1723
1801
            tmp_buff[1]= *pos ? *pos : '0';
1724
 
            if (my_b_write(&cache,(unsigned char*) start,(uint) (pos-start)) ||
1725
 
                my_b_write(&cache,(unsigned char*) tmp_buff,2))
 
1802
            if (my_b_write(&cache,(uchar*) start,(uint) (pos-start)) ||
 
1803
                my_b_write(&cache,(uchar*) tmp_buff,2))
1726
1804
              goto err;
1727
1805
            start=pos+1;
1728
1806
          }
1729
1807
        }
1730
 
        if (my_b_write(&cache,(unsigned char*) start,(uint) (pos-start)))
 
1808
        if (my_b_write(&cache,(uchar*) start,(uint) (pos-start)))
1731
1809
          goto err;
1732
1810
      }
1733
 
      else if (my_b_write(&cache,(unsigned char*) res->ptr(),used_length))
 
1811
      else if (my_b_write(&cache,(uchar*) res->ptr(),used_length))
1734
1812
        goto err;
1735
1813
    }
1736
1814
    if (fixed_row_size)
1743
1821
          space_inited=1;
1744
1822
          memset(space, ' ', sizeof(space));
1745
1823
        }
1746
 
        uint32_t length=item->max_length-used_length;
 
1824
        uint length=item->max_length-used_length;
1747
1825
        for (; length > sizeof(space) ; length-=sizeof(space))
1748
1826
        {
1749
 
          if (my_b_write(&cache,(unsigned char*) space,sizeof(space)))
 
1827
          if (my_b_write(&cache,(uchar*) space,sizeof(space)))
1750
1828
            goto err;
1751
1829
        }
1752
 
        if (my_b_write(&cache,(unsigned char*) space,length))
 
1830
        if (my_b_write(&cache,(uchar*) space,length))
1753
1831
          goto err;
1754
1832
      }
1755
1833
    }
1756
1834
    if (res && enclosed)
1757
1835
    {
1758
 
      if (my_b_write(&cache, (unsigned char*) exchange->enclosed->ptr(),
 
1836
      if (my_b_write(&cache, (uchar*) exchange->enclosed->ptr(),
1759
1837
                     exchange->enclosed->length()))
1760
1838
        goto err;
1761
1839
    }
1762
1840
    if (--items_left)
1763
1841
    {
1764
 
      if (my_b_write(&cache, (unsigned char*) exchange->field_term->ptr(),
 
1842
      if (my_b_write(&cache, (uchar*) exchange->field_term->ptr(),
1765
1843
                     field_term_length))
1766
1844
        goto err;
1767
1845
    }
1768
1846
  }
1769
 
  if (my_b_write(&cache,(unsigned char*) exchange->line_term->ptr(),
 
1847
  if (my_b_write(&cache,(uchar*) exchange->line_term->ptr(),
1770
1848
                 exchange->line_term->length()))
1771
1849
    goto err;
1772
1850
  return(0);
1785
1863
                     SELECT_LEX_UNIT *u)
1786
1864
{
1787
1865
  unit= u;
1788
 
  return (int) ((file= create_file(session, path, exchange, &cache)) < 0);
 
1866
  return (int) ((file= create_file(thd, path, exchange, &cache)) < 0);
1789
1867
}
1790
1868
 
1791
1869
 
1812
1890
    res=item->str_result(&tmp);
1813
1891
    if (!res)                                   // If NULL
1814
1892
    {
1815
 
      if (my_b_write(&cache,(unsigned char*) "",1))
 
1893
      if (my_b_write(&cache,(uchar*) "",1))
1816
1894
        goto err;
1817
1895
    }
1818
 
    else if (my_b_write(&cache,(unsigned char*) res->ptr(),res->length()))
 
1896
    else if (my_b_write(&cache,(uchar*) res->ptr(),res->length()))
1819
1897
    {
1820
1898
      my_error(ER_ERROR_ON_WRITE, MYF(0), path, my_errno);
1821
1899
      goto err;
1848
1926
  }
1849
1927
  List_iterator_fast<Item> li(items);
1850
1928
  Item *val_item;
1851
 
  for (uint32_t i= 0; (val_item= li++); i++)
 
1929
  for (uint i= 0; (val_item= li++); i++)
1852
1930
    it->store(i, val_item);
1853
1931
  it->assigned(1);
1854
1932
  return(0);
2024
2102
}
2025
2103
 
2026
2104
 
 
2105
void Query_arena::set_query_arena(Query_arena *set)
 
2106
{
 
2107
  mem_root= set->mem_root;
 
2108
  free_list= set->free_list;
 
2109
  state= set->state;
 
2110
}
 
2111
 
 
2112
 
 
2113
void Query_arena::cleanup_stmt()
 
2114
{
 
2115
  assert("not implemented");
 
2116
}
 
2117
 
2027
2118
/*
2028
2119
  Statement functions
2029
2120
*/
2030
2121
 
2031
 
Statement::Statement(LEX *lex_arg, MEM_ROOT *mem_root_arg, ulong id_arg)
2032
 
  :Query_arena(mem_root_arg),
 
2122
Statement::Statement(LEX *lex_arg, MEM_ROOT *mem_root_arg,
 
2123
                     enum enum_state state_arg, ulong id_arg)
 
2124
  :Query_arena(mem_root_arg, state_arg),
2033
2125
  id(id_arg),
2034
2126
  mark_used_columns(MARK_COLUMNS_READ),
2035
2127
  lex(lex_arg),
2038
2130
  db(NULL),
2039
2131
  db_length(0)
2040
2132
{
2041
 
}
2042
 
 
2043
 
 
2044
 
/*
2045
 
  Don't free mem_root, as mem_root is freed in the end of dispatch_command
2046
 
  (once for any command).
2047
 
*/
2048
 
void Session::end_statement()
 
2133
  name.str= NULL;
 
2134
}
 
2135
 
 
2136
 
 
2137
void Statement::set_statement(Statement *stmt)
 
2138
{
 
2139
  id=             stmt->id;
 
2140
  mark_used_columns=   stmt->mark_used_columns;
 
2141
  lex=            stmt->lex;
 
2142
  query=          stmt->query;
 
2143
  query_length=   stmt->query_length;
 
2144
}
 
2145
 
 
2146
 
 
2147
void
 
2148
Statement::set_n_backup_statement(Statement *stmt, Statement *backup)
 
2149
{
 
2150
  backup->set_statement(this);
 
2151
  set_statement(stmt);
 
2152
  return;
 
2153
}
 
2154
 
 
2155
 
 
2156
void Statement::restore_backup_statement(Statement *stmt, Statement *backup)
 
2157
{
 
2158
  stmt->set_statement(this);
 
2159
  set_statement(backup);
 
2160
  return;
 
2161
}
 
2162
 
 
2163
 
 
2164
void THD::end_statement()
2049
2165
{
2050
2166
  /* Cleanup SQL processing state to reuse this statement in next query. */
2051
2167
  lex_end(lex);
2052
 
}
2053
 
 
2054
 
 
2055
 
bool Session::copy_db_to(char **p_db, size_t *p_db_length)
 
2168
  delete lex->result;
 
2169
  lex->result= 0;
 
2170
  /* Note that free_list is freed in cleanup_after_query() */
 
2171
 
 
2172
  /*
 
2173
    Don't free mem_root, as mem_root is freed in the end of dispatch_command
 
2174
    (once for any command).
 
2175
  */
 
2176
}
 
2177
 
 
2178
 
 
2179
void THD::set_n_backup_active_arena(Query_arena *set, Query_arena *backup)
 
2180
{
 
2181
  assert(backup->is_backup_arena == false);
 
2182
 
 
2183
  backup->set_query_arena(this);
 
2184
  set_query_arena(set);
 
2185
  backup->is_backup_arena= true;
 
2186
  return;
 
2187
}
 
2188
 
 
2189
 
 
2190
void THD::restore_active_arena(Query_arena *set, Query_arena *backup)
 
2191
{
 
2192
  assert(backup->is_backup_arena);
 
2193
  set->set_query_arena(this);
 
2194
  set_query_arena(backup);
 
2195
  backup->is_backup_arena= false;
 
2196
  return;
 
2197
}
 
2198
 
 
2199
 
 
2200
bool THD::copy_db_to(char **p_db, size_t *p_db_length)
2056
2201
{
2057
2202
  if (db == NULL)
2058
2203
  {
2087
2232
    if (mv->local == 0)
2088
2233
    {
2089
2234
      Item_func_set_user_var *suv= new Item_func_set_user_var(mv->s, item);
2090
 
      suv->fix_fields(session, 0);
 
2235
      suv->fix_fields(thd, 0);
2091
2236
      suv->check(0);
2092
2237
      suv->update();
2093
2238
    }
2094
2239
  }
2095
 
  return(session->is_error());
 
2240
  return(thd->is_error());
2096
2241
}
2097
2242
 
2098
2243
bool select_dumpvar::send_eof()
2099
2244
{
2100
2245
  if (! row_count)
2101
 
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
2246
    push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
2102
2247
                 ER_SP_FETCH_NO_DATA, ER(ER_SP_FETCH_NO_DATA));
2103
2248
  /*
2104
2249
    In order to remember the value of affected rows for ROW_COUNT()
2105
2250
    function, SELECT INTO has to have an own SQLCOM.
2106
2251
    TODO: split from SQLCOM_SELECT
2107
2252
  */
2108
 
  ::my_ok(session,row_count);
 
2253
  ::my_ok(thd,row_count);
2109
2254
  return 0;
2110
2255
}
2111
2256
 
2124
2269
  return;
2125
2270
}
2126
2271
 
2127
 
void TMP_TABLE_PARAM::cleanup(void)
2128
 
{
2129
 
  /* Fix for Intel compiler */
2130
 
  if (copy_field)
2131
 
  {
2132
 
    delete [] copy_field;
2133
 
    save_copy_field= copy_field= 0;
2134
 
  }
2135
 
}
2136
 
 
2137
 
 
2138
 
void session_increment_bytes_sent(ulong length)
2139
 
{
2140
 
  Session *session=current_session;
2141
 
  if (likely(session != 0))
2142
 
  { /* current_session==0 when close_connection() calls net_send_error() */
2143
 
    session->status_var.bytes_sent+= length;
2144
 
  }
2145
 
}
2146
 
 
2147
 
 
2148
 
void session_increment_bytes_received(ulong length)
2149
 
{
2150
 
  current_session->status_var.bytes_received+= length;
2151
 
}
2152
 
 
2153
 
 
2154
 
void session_increment_net_big_packet_count(ulong length)
2155
 
{
2156
 
  current_session->status_var.net_big_packet_count+= length;
2157
 
}
2158
 
 
2159
 
void Session::send_kill_message() const
 
2272
 
 
2273
void thd_increment_bytes_sent(ulong length)
 
2274
{
 
2275
  THD *thd=current_thd;
 
2276
  if (likely(thd != 0))
 
2277
  { /* current_thd==0 when close_connection() calls net_send_error() */
 
2278
    thd->status_var.bytes_sent+= length;
 
2279
  }
 
2280
}
 
2281
 
 
2282
 
 
2283
void thd_increment_bytes_received(ulong length)
 
2284
{
 
2285
  current_thd->status_var.bytes_received+= length;
 
2286
}
 
2287
 
 
2288
 
 
2289
void thd_increment_net_big_packet_count(ulong length)
 
2290
{
 
2291
  current_thd->status_var.net_big_packet_count+= length;
 
2292
}
 
2293
 
 
2294
void THD::send_kill_message() const
2160
2295
{
2161
2296
  int err= killed_errno();
2162
2297
  if (err)
2163
2298
    my_message(err, ER(err), MYF(0));
2164
2299
}
2165
2300
 
2166
 
void Session::set_status_var_init()
 
2301
void THD::set_status_var_init()
2167
2302
{
2168
 
  memset(&status_var, 0, sizeof(status_var));
 
2303
  memset((char*) &status_var, 0, sizeof(status_var));
2169
2304
}
2170
2305
 
2171
2306
 
2172
2307
void Security_context::init()
2173
2308
{
2174
 
  user= ip= 0;
 
2309
  host= user= priv_user= ip= 0;
 
2310
  host_or_ip= "connecting host";
 
2311
  priv_host[0]= '\0';
2175
2312
}
2176
2313
 
2177
2314
 
2178
2315
void Security_context::destroy()
2179
2316
{
2180
2317
  // If not pointer to constant
2181
 
  if (user)
2182
 
  {
2183
 
    free(user);
2184
 
    user= NULL;
2185
 
  }
2186
 
  if (ip)
2187
 
  {
2188
 
    free(ip);
2189
 
    ip= NULL;
2190
 
  }
 
2318
  if (host != my_localhost)
 
2319
    safeFree(host);
 
2320
  safeFree(user);
 
2321
  safeFree(ip);
2191
2322
}
2192
2323
 
2193
2324
 
2194
2325
void Security_context::skip_grants()
2195
2326
{
2196
2327
  /* privileges for the user are unknown everything is allowed */
 
2328
  host_or_ip= (char *)"";
 
2329
  priv_user= (char *)"";
 
2330
  *priv_host= '\0';
2197
2331
}
2198
2332
 
2199
2333
 
2205
2339
  access to mysql.proc table to find definitions of stored routines.
2206
2340
****************************************************************************/
2207
2341
 
2208
 
void Session::reset_n_backup_open_tables_state(Open_tables_state *backup)
 
2342
void THD::reset_n_backup_open_tables_state(Open_tables_state *backup)
2209
2343
{
2210
2344
  backup->set_open_tables_state(this);
2211
2345
  reset_open_tables_state();
2214
2348
}
2215
2349
 
2216
2350
 
2217
 
void Session::restore_backup_open_tables_state(Open_tables_state *backup)
 
2351
void THD::restore_backup_open_tables_state(Open_tables_state *backup)
2218
2352
{
2219
2353
  /*
2220
2354
    Before we will throw away current open tables state we want
2229
2363
 
2230
2364
/**
2231
2365
  Check the killed state of a user thread
2232
 
  @param session  user thread
 
2366
  @param thd  user thread
2233
2367
  @retval 0 the user thread is active
2234
2368
  @retval 1 the user thread has been killed
2235
2369
*/
2236
 
extern "C" int session_killed(const Session *session)
 
2370
extern "C" int thd_killed(const MYSQL_THD thd)
2237
2371
{
2238
 
  return(session->killed);
 
2372
  return(thd->killed);
2239
2373
}
2240
2374
 
2241
2375
/**
2242
2376
  Return the thread id of a user thread
2243
 
  @param session user thread
 
2377
  @param thd user thread
2244
2378
  @return thread id
2245
2379
*/
2246
 
extern "C" unsigned long session_get_thread_id(const Session *session)
2247
 
{
2248
 
  return((unsigned long)session->thread_id);
2249
 
}
2250
 
 
2251
 
 
2252
 
extern "C"
2253
 
LEX_STRING *session_make_lex_string(Session *session, LEX_STRING *lex_str,
2254
 
                                const char *str, unsigned int size,
2255
 
                                int allocate_lex_string)
2256
 
{
2257
 
  return session->make_lex_string(lex_str, str, size,
2258
 
                              (bool) allocate_lex_string);
2259
 
}
2260
 
 
2261
 
extern "C" const struct charset_info_st *session_charset(Session *session)
2262
 
{
2263
 
  return(session->charset());
2264
 
}
2265
 
 
2266
 
extern "C" char **session_query(Session *session)
2267
 
{
2268
 
  return(&session->query);
2269
 
}
2270
 
 
2271
 
extern "C" int session_slave_thread(const Session *session)
2272
 
{
2273
 
  return(session->slave_thread);
2274
 
}
2275
 
 
2276
 
extern "C" int session_non_transactional_update(const Session *session)
2277
 
{
2278
 
  return(session->transaction.all.modified_non_trans_table);
2279
 
}
2280
 
 
2281
 
extern "C" void session_mark_transaction_to_rollback(Session *session, bool all)
2282
 
{
2283
 
  mark_transaction_to_rollback(session, all);
2284
 
}
 
2380
extern "C" unsigned long thd_get_thread_id(const MYSQL_THD thd)
 
2381
{
 
2382
  return((unsigned long)thd->thread_id);
 
2383
}
 
2384
 
 
2385
 
 
2386
#ifdef INNODB_COMPATIBILITY_HOOKS
 
2387
extern "C" struct charset_info_st *thd_charset(MYSQL_THD thd)
 
2388
{
 
2389
  return(thd->charset());
 
2390
}
 
2391
 
 
2392
extern "C" char **thd_query(MYSQL_THD thd)
 
2393
{
 
2394
  return(&thd->query);
 
2395
}
 
2396
 
 
2397
extern "C" int thd_slave_thread(const MYSQL_THD thd)
 
2398
{
 
2399
  return(thd->slave_thread);
 
2400
}
 
2401
 
 
2402
extern "C" int thd_non_transactional_update(const MYSQL_THD thd)
 
2403
{
 
2404
  return(thd->transaction.all.modified_non_trans_table);
 
2405
}
 
2406
 
 
2407
extern "C" int thd_binlog_format(const MYSQL_THD thd)
 
2408
{
 
2409
  return (int) thd->variables.binlog_format;
 
2410
}
 
2411
 
 
2412
extern "C" void thd_mark_transaction_to_rollback(MYSQL_THD thd, bool all)
 
2413
{
 
2414
  mark_transaction_to_rollback(thd, all);
 
2415
}
 
2416
#endif // INNODB_COMPATIBILITY_HOOKS */
2285
2417
 
2286
2418
 
2287
2419
/**
2288
2420
  Mark transaction to rollback and mark error as fatal to a sub-statement.
2289
2421
 
2290
 
  @param  session   Thread handle
 
2422
  @param  thd   Thread handle
2291
2423
  @param  all   true <=> rollback main transaction.
2292
2424
*/
2293
2425
 
2294
 
void mark_transaction_to_rollback(Session *session, bool all)
 
2426
void mark_transaction_to_rollback(THD *thd, bool all)
2295
2427
{
2296
 
  if (session)
 
2428
  if (thd)
2297
2429
  {
2298
 
    session->is_fatal_sub_stmt_error= true;
2299
 
    session->transaction_rollback_request= all;
 
2430
    thd->is_fatal_sub_stmt_error= true;
 
2431
    thd->transaction_rollback_request= all;
2300
2432
  }
2301
2433
}
2302
2434
/***************************************************************************
2306
2438
pthread_mutex_t LOCK_xid_cache;
2307
2439
HASH xid_cache;
2308
2440
 
2309
 
extern "C" unsigned char *xid_get_hash_key(const unsigned char *, size_t *, bool);
 
2441
extern "C" uchar *xid_get_hash_key(const uchar *, size_t *, bool);
2310
2442
extern "C" void xid_free_hash(void *);
2311
2443
 
2312
 
unsigned char *xid_get_hash_key(const unsigned char *ptr, size_t *length,
 
2444
uchar *xid_get_hash_key(const uchar *ptr, size_t *length,
2313
2445
                        bool not_used __attribute__((unused)))
2314
2446
{
2315
2447
  *length=((XID_STATE*)ptr)->xid.key_length();
2318
2450
 
2319
2451
void xid_free_hash(void *ptr)
2320
2452
{
2321
 
  if (!((XID_STATE*)ptr)->in_session)
2322
 
    free((unsigned char*)ptr);
 
2453
  if (!((XID_STATE*)ptr)->in_thd)
 
2454
    my_free((uchar*)ptr, MYF(0));
2323
2455
}
2324
2456
 
2325
2457
bool xid_cache_init()
2360
2492
  {
2361
2493
    xs->xa_state=xa_state;
2362
2494
    xs->xid.set(xid);
2363
 
    xs->in_session=0;
2364
 
    res=my_hash_insert(&xid_cache, (unsigned char*)xs);
 
2495
    xs->in_thd=0;
 
2496
    res=my_hash_insert(&xid_cache, (uchar*)xs);
2365
2497
  }
2366
2498
  pthread_mutex_unlock(&LOCK_xid_cache);
2367
2499
  return res;
2373
2505
  pthread_mutex_lock(&LOCK_xid_cache);
2374
2506
  assert(hash_search(&xid_cache, xid_state->xid.key(),
2375
2507
                          xid_state->xid.key_length())==0);
2376
 
  bool res=my_hash_insert(&xid_cache, (unsigned char*)xid_state);
 
2508
  bool res=my_hash_insert(&xid_cache, (uchar*)xid_state);
2377
2509
  pthread_mutex_unlock(&LOCK_xid_cache);
2378
2510
  return res;
2379
2511
}
2382
2514
void xid_cache_delete(XID_STATE *xid_state)
2383
2515
{
2384
2516
  pthread_mutex_lock(&LOCK_xid_cache);
2385
 
  hash_delete(&xid_cache, (unsigned char *)xid_state);
 
2517
  hash_delete(&xid_cache, (uchar *)xid_state);
2386
2518
  pthread_mutex_unlock(&LOCK_xid_cache);
2387
2519
}
2388
2520
 
2392
2524
  inserted/updated/deleted.
2393
2525
*/
2394
2526
 
 
2527
#ifndef MYSQL_CLIENT
2395
2528
 
2396
2529
/*
2397
2530
  Template member function for ensuring that there is an rows log
2401
2534
    - Events of type 'RowEventT' have the type code 'type_code'.
2402
2535
    
2403
2536
  POST CONDITION:
2404
 
    If a non-NULL pointer is returned, the pending event for thread 'session' will
 
2537
    If a non-NULL pointer is returned, the pending event for thread 'thd' will
2405
2538
    be an event of type 'RowEventT' (which have the type code 'type_code')
2406
2539
    will either empty or have enough space to hold 'needed' bytes.  In
2407
2540
    addition, the columns bitmap will be correct for the row, meaning that
2415
2548
 */
2416
2549
 
2417
2550
template <class RowsEventT> Rows_log_event* 
2418
 
Session::binlog_prepare_pending_rows_event(Table* table, uint32_t serv_id,
 
2551
THD::binlog_prepare_pending_rows_event(TABLE* table, uint32_t serv_id,
2419
2552
                                       size_t needed,
2420
2553
                                       bool is_transactional,
2421
2554
                                       RowsEventT *hint __attribute__((unused)))
2422
2555
{
2423
2556
  /* Pre-conditions */
2424
 
  assert(table->s->table_map_id != UINT32_MAX);
 
2557
  assert(table->s->table_map_id != ~0UL);
2425
2558
 
2426
2559
  /* Fetch the type code for the RowsEventT template parameter */
2427
2560
  int const type_code= RowsEventT::TYPE_CODE;
2474
2607
      flush the pending event and replace it with the newly created
2475
2608
      event...
2476
2609
    */
2477
 
    if (unlikely(drizzle_bin_log.flush_and_set_pending_rows_event(this, ev)))
 
2610
    if (unlikely(mysql_bin_log.flush_and_set_pending_rows_event(this, ev)))
2478
2611
    {
2479
2612
      delete ev;
2480
2613
      return(NULL);
2491
2624
  compiling option.
2492
2625
*/
2493
2626
template Rows_log_event*
2494
 
Session::binlog_prepare_pending_rows_event(Table*, uint32_t, size_t, bool,
 
2627
THD::binlog_prepare_pending_rows_event(TABLE*, uint32_t, size_t, bool,
2495
2628
                                       Write_rows_log_event*);
2496
2629
 
2497
2630
template Rows_log_event*
2498
 
Session::binlog_prepare_pending_rows_event(Table*, uint32_t, size_t, bool,
 
2631
THD::binlog_prepare_pending_rows_event(TABLE*, uint32_t, size_t, bool,
2499
2632
                                       Delete_rows_log_event *);
2500
2633
 
2501
2634
template Rows_log_event* 
2502
 
Session::binlog_prepare_pending_rows_event(Table*, uint32_t, size_t, bool,
 
2635
THD::binlog_prepare_pending_rows_event(TABLE*, uint32_t, size_t, bool,
2503
2636
                                       Update_rows_log_event *);
2504
2637
#endif
2505
2638
 
2531
2664
      @param length
2532
2665
      Length of data that is needed, if the record contain blobs.
2533
2666
     */
2534
 
    Row_data_memory(Table *table, size_t const len1)
 
2667
    Row_data_memory(TABLE *table, size_t const len1)
2535
2668
      : m_memory(0)
2536
2669
    {
2537
2670
      m_alloc_checked= false;
2540
2673
      m_ptr[1]= 0;
2541
2674
    }
2542
2675
 
2543
 
    Row_data_memory(Table *table, size_t const len1, size_t const len2)
 
2676
    Row_data_memory(TABLE *table, size_t const len1, size_t const len2)
2544
2677
      : m_memory(0)
2545
2678
    {
2546
2679
      m_alloc_checked= false;
2552
2685
    ~Row_data_memory()
2553
2686
    {
2554
2687
      if (m_memory != 0 && m_release_memory_on_destruction)
2555
 
        free((unsigned char*) m_memory);
 
2688
        my_free((uchar*) m_memory, MYF(MY_WME));
2556
2689
    }
2557
2690
 
2558
2691
    /**
2566
2699
      return m_memory != 0;
2567
2700
    }
2568
2701
 
2569
 
    unsigned char *slot(uint32_t s)
 
2702
    uchar *slot(uint s)
2570
2703
    {
2571
2704
      assert(s < sizeof(m_ptr)/sizeof(*m_ptr));
2572
2705
      assert(m_ptr[s] != 0);
2575
2708
    }
2576
2709
 
2577
2710
  private:
2578
 
    void allocate_memory(Table *const table, size_t const total_length)
 
2711
    void allocate_memory(TABLE *const table, size_t const total_length)
2579
2712
    {
2580
2713
      if (table->s->blob_fields == 0)
2581
2714
      {
2598
2731
        */
2599
2732
        if (table->write_row_record == 0)
2600
2733
          table->write_row_record=
2601
 
            (unsigned char *) alloc_root(&table->mem_root, 2 * maxlen);
 
2734
            (uchar *) alloc_root(&table->mem_root, 2 * maxlen);
2602
2735
        m_memory= table->write_row_record;
2603
2736
        m_release_memory_on_destruction= false;
2604
2737
      }
2605
2738
      else
2606
2739
      {
2607
 
        m_memory= (unsigned char *) my_malloc(total_length, MYF(MY_WME));
 
2740
        m_memory= (uchar *) my_malloc(total_length, MYF(MY_WME));
2608
2741
        m_release_memory_on_destruction= true;
2609
2742
      }
2610
2743
    }
2611
2744
 
2612
2745
    mutable bool m_alloc_checked;
2613
2746
    bool m_release_memory_on_destruction;
2614
 
    unsigned char *m_memory;
2615
 
    unsigned char *m_ptr[2];
 
2747
    uchar *m_memory;
 
2748
    uchar *m_ptr[2];
2616
2749
  };
2617
2750
}
2618
2751
 
2619
2752
 
2620
 
int Session::binlog_write_row(Table* table, bool is_trans, 
2621
 
                          unsigned char const *record) 
 
2753
int THD::binlog_write_row(TABLE* table, bool is_trans, 
 
2754
                          uchar const *record) 
2622
2755
2623
 
  assert(drizzle_bin_log.is_open());
 
2756
  assert(current_stmt_binlog_row_based && mysql_bin_log.is_open());
2624
2757
 
2625
2758
  /*
2626
2759
    Pack records into format for transfer. We are allocating more
2627
2760
    memory than needed, but that doesn't matter.
2628
2761
  */
2629
 
  Row_data_memory memory(table, table->max_row_length(record));
 
2762
  Row_data_memory memory(table, max_row_length(table, record));
2630
2763
  if (!memory.has_memory())
2631
2764
    return HA_ERR_OUT_OF_MEM;
2632
2765
 
2633
 
  unsigned char *row_data= memory.slot(0);
 
2766
  uchar *row_data= memory.slot(0);
2634
2767
 
2635
2768
  size_t const len= pack_row(table, table->write_set, row_data, record);
2636
2769
 
2644
2777
  return ev->add_row_data(row_data, len);
2645
2778
}
2646
2779
 
2647
 
int Session::binlog_update_row(Table* table, bool is_trans,
2648
 
                           const unsigned char *before_record,
2649
 
                           const unsigned char *after_record)
 
2780
int THD::binlog_update_row(TABLE* table, bool is_trans,
 
2781
                           const uchar *before_record,
 
2782
                           const uchar *after_record)
2650
2783
2651
 
  assert(drizzle_bin_log.is_open());
 
2784
  assert(current_stmt_binlog_row_based && mysql_bin_log.is_open());
2652
2785
 
2653
 
  size_t const before_maxlen = table->max_row_length(before_record);
2654
 
  size_t const after_maxlen  = table->max_row_length(after_record);
 
2786
  size_t const before_maxlen = max_row_length(table, before_record);
 
2787
  size_t const after_maxlen  = max_row_length(table, after_record);
2655
2788
 
2656
2789
  Row_data_memory row_data(table, before_maxlen, after_maxlen);
2657
2790
  if (!row_data.has_memory())
2658
2791
    return HA_ERR_OUT_OF_MEM;
2659
2792
 
2660
 
  unsigned char *before_row= row_data.slot(0);
2661
 
  unsigned char *after_row= row_data.slot(1);
 
2793
  uchar *before_row= row_data.slot(0);
 
2794
  uchar *after_row= row_data.slot(1);
2662
2795
 
2663
2796
  size_t const before_size= pack_row(table, table->read_set, before_row,
2664
2797
                                        before_record);
2678
2811
    ev->add_row_data(after_row, after_size);
2679
2812
}
2680
2813
 
2681
 
int Session::binlog_delete_row(Table* table, bool is_trans, 
2682
 
                           unsigned char const *record)
 
2814
int THD::binlog_delete_row(TABLE* table, bool is_trans, 
 
2815
                           uchar const *record)
2683
2816
2684
 
  assert(drizzle_bin_log.is_open());
 
2817
  assert(current_stmt_binlog_row_based && mysql_bin_log.is_open());
2685
2818
 
2686
2819
  /* 
2687
2820
     Pack records into format for transfer. We are allocating more
2688
2821
     memory than needed, but that doesn't matter.
2689
2822
  */
2690
 
  Row_data_memory memory(table, table->max_row_length(record));
 
2823
  Row_data_memory memory(table, max_row_length(table, record));
2691
2824
  if (unlikely(!memory.has_memory()))
2692
2825
    return HA_ERR_OUT_OF_MEM;
2693
2826
 
2694
 
  unsigned char *row_data= memory.slot(0);
 
2827
  uchar *row_data= memory.slot(0);
2695
2828
 
2696
2829
  size_t const len= pack_row(table, table->read_set, row_data, record);
2697
2830
 
2706
2839
}
2707
2840
 
2708
2841
 
2709
 
int Session::binlog_flush_pending_rows_event(bool stmt_end)
 
2842
int THD::binlog_flush_pending_rows_event(bool stmt_end)
2710
2843
{
2711
2844
  /*
2712
2845
    We shall flush the pending event even if we are not in row-based
2713
2846
    mode: it might be the case that we left row-based mode before
2714
2847
    flushing anything (e.g., if we have explicitly locked tables).
2715
2848
   */
2716
 
  if (!drizzle_bin_log.is_open())
 
2849
  if (!mysql_bin_log.is_open())
2717
2850
    return(0);
2718
2851
 
2719
2852
  /*
2730
2863
      binlog_table_maps= 0;
2731
2864
    }
2732
2865
 
2733
 
    error= drizzle_bin_log.flush_and_set_pending_rows_event(this, 0);
 
2866
    error= mysql_bin_log.flush_and_set_pending_rows_event(this, 0);
2734
2867
  }
2735
2868
 
2736
2869
  return(error);
2760
2893
  RETURN VALUE
2761
2894
    Error code, or 0 if no error.
2762
2895
*/
2763
 
int Session::binlog_query(Session::enum_binlog_query_type qtype, char const *query_arg,
 
2896
int THD::binlog_query(THD::enum_binlog_query_type qtype, char const *query_arg,
2764
2897
                      ulong query_len, bool is_trans, bool suppress_use,
2765
 
                      Session::killed_state killed_status_arg)
 
2898
                      THD::killed_state killed_status_arg)
2766
2899
{
2767
 
  assert(query_arg && drizzle_bin_log.is_open());
 
2900
  assert(query_arg && mysql_bin_log.is_open());
2768
2901
 
2769
2902
  if (int error= binlog_flush_pending_rows_event(true))
2770
2903
    return(error);
2771
2904
 
 
2905
  /*
 
2906
    If we are in statement mode and trying to log an unsafe statement,
 
2907
    we should print a warning.
 
2908
  */
 
2909
  if (lex->is_stmt_unsafe() &&
 
2910
      variables.binlog_format == BINLOG_FORMAT_STMT)
 
2911
  {
 
2912
    assert(this->query != NULL);
 
2913
    push_warning(this, MYSQL_ERROR::WARN_LEVEL_WARN,
 
2914
                 ER_BINLOG_UNSAFE_STATEMENT,
 
2915
                 ER(ER_BINLOG_UNSAFE_STATEMENT));
 
2916
    if (!(binlog_flags & BINLOG_FLAG_UNSAFE_STMT_PRINTED))
 
2917
    {
 
2918
      char warn_buf[MYSQL_ERRMSG_SIZE];
 
2919
      snprintf(warn_buf, MYSQL_ERRMSG_SIZE, "%s Statement: %s",
 
2920
               ER(ER_BINLOG_UNSAFE_STATEMENT), this->query);
 
2921
      sql_print_warning(warn_buf);
 
2922
      binlog_flags|= BINLOG_FLAG_UNSAFE_STMT_PRINTED;
 
2923
    }
 
2924
  }
 
2925
 
2772
2926
  switch (qtype) {
2773
 
  case Session::ROW_QUERY_TYPE:
2774
 
    return(0);
2775
 
  case Session::DRIZZLE_QUERY_TYPE:
 
2927
  case THD::ROW_QUERY_TYPE:
 
2928
    if (current_stmt_binlog_row_based)
 
2929
      return(0);
 
2930
    /* Otherwise, we fall through */
 
2931
  case THD::MYSQL_QUERY_TYPE:
2776
2932
    /*
2777
2933
      Using this query type is a conveniece hack, since we have been
2778
2934
      moving back and forth between using RBR for replication of
2781
2937
      Make sure to change in check_table_binlog_row_based() according
2782
2938
      to how you treat this.
2783
2939
    */
2784
 
  case Session::STMT_QUERY_TYPE:
 
2940
  case THD::STMT_QUERY_TYPE:
2785
2941
    /*
2786
 
      The DRIZZLE_LOG::write() function will set the STMT_END_F flag and
 
2942
      The MYSQL_LOG::write() function will set the STMT_END_F flag and
2787
2943
      flush the pending rows event if necessary.
2788
2944
     */
2789
2945
    {
2796
2952
        log event is written to the binary log, we pretend that no
2797
2953
        table maps were written.
2798
2954
       */
2799
 
      int error= drizzle_bin_log.write(&qinfo);
 
2955
      int error= mysql_bin_log.write(&qinfo);
2800
2956
      binlog_table_maps= 0;
2801
2957
      return(error);
2802
2958
    }
2803
2959
    break;
2804
2960
 
2805
 
  case Session::QUERY_TYPE_COUNT:
 
2961
  case THD::QUERY_TYPE_COUNT:
2806
2962
  default:
2807
2963
    assert(0 <= qtype && qtype < QUERY_TYPE_COUNT);
2808
2964
  }
2835
2991
  return(0);
2836
2992
}
2837
2993
 
2838
 
/**
2839
 
  Close a connection.
2840
 
 
2841
 
  @param session                Thread handle
2842
 
  @param errcode        Error code to print to console
2843
 
  @param lock           1 if we have have to lock LOCK_thread_count
2844
 
 
2845
 
  @note
2846
 
    For the connection that is doing shutdown, this is called twice
2847
 
*/
2848
 
void close_connection(Session *session, uint32_t errcode, bool lock)
2849
 
{
2850
 
  st_vio *vio;
2851
 
  if (lock)
2852
 
    (void) pthread_mutex_lock(&LOCK_thread_count);
2853
 
  session->killed= Session::KILL_CONNECTION;
2854
 
  if ((vio= session->net.vio) != 0)
2855
 
  {
2856
 
    if (errcode)
2857
 
      net_send_error(session, errcode, ER(errcode)); /* purecov: inspected */
2858
 
    net_close(&(session->net));         /* vio is freed in delete session */
2859
 
  }
2860
 
  if (lock)
2861
 
    (void) pthread_mutex_unlock(&LOCK_thread_count);
2862
 
  return;;
2863
 
}
 
2994
#endif /* !defined(MYSQL_CLIENT) */