~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/session.cc

  • Committer: jay
  • Date: 2008-12-23 00:18:10 UTC
  • Revision ID: jay@piggy.tangent.org-20081223001810-026ibij22q2842k1
Had a --regex-replace by accident. Should have been --replace_column call.  Only showed up in make test, not running single test, because InnoDB key numbers were different with multiple test running.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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 */
 
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
 */
15
19
 
16
20
 
17
21
/*****************************************************************************
18
22
**
19
 
** This file implements classes defined in sql_class.h
 
23
** This file implements classes defined in session.h
20
24
** Especially the classes to handle a result from a select
21
25
**
22
26
*****************************************************************************/
23
27
#include <drizzled/server_includes.h>
24
 
#include "rpl_rli.h"
25
 
#include "rpl_record.h"
26
 
#include "log_event.h"
 
28
#include <drizzled/session.h>
 
29
#include <drizzled/replication/rli.h>
 
30
#include <drizzled/replication/record.h>
 
31
#include <drizzled/log_event.h>
27
32
#include <sys/stat.h>
28
33
#include <mysys/thr_alarm.h>
29
34
#include <mysys/mysys_err.h>
30
 
#include <drizzled/drizzled_error_messages.h>
 
35
#include <drizzled/error.h>
 
36
#include <drizzled/query_id.h>
 
37
#include <drizzled/data_home.h>
 
38
#include <drizzled/sql_base.h>
 
39
#include <drizzled/lock.h>
 
40
#include <drizzled/item/cache.h>
 
41
#include <drizzled/item/float.h>
 
42
#include <drizzled/item/return_int.h>
 
43
#include <drizzled/item/empty_string.h>
31
44
 
 
45
extern scheduler_functions thread_scheduler;
32
46
/*
33
47
  The following is used to initialise Table_ident with a internal
34
48
  table name
36
50
char internal_table_name[2]= "*";
37
51
char empty_c_string[1]= {0};    /* used for not defined db */
38
52
 
39
 
const char * const THD::DEFAULT_WHERE= "field list";
 
53
const char * const Session::DEFAULT_WHERE= "field list";
 
54
extern pthread_key_t THR_Session;
 
55
extern pthread_key_t THR_Mem_root;
40
56
 
41
57
 
42
58
/*****************************************************************************
55
71
template class List_iterator<Alter_column>;
56
72
#endif
57
73
 
 
74
 
58
75
/****************************************************************************
59
76
** User variables
60
77
****************************************************************************/
85
102
  Construct an (almost) deep copy of this key. Only those
86
103
  elements that are known to never change are not copied.
87
104
  If out of memory, a partial copy is returned and an error is set
88
 
  in THD.
 
105
  in Session.
89
106
*/
90
107
 
91
108
Key::Key(const Key &rhs, MEM_ROOT *mem_root)
102
119
  Construct an (almost) deep copy of this foreign key. Only those
103
120
  elements that are known to never change are not copied.
104
121
  If out of memory, a partial copy is returned and an error is set
105
 
  in THD.
 
122
  in Session.
106
123
*/
107
124
 
108
125
Foreign_key::Foreign_key(const Foreign_key &rhs, MEM_ROOT *mem_root)
183
200
}
184
201
 
185
202
 
 
203
/*
 
204
  Check if the foreign key options are compatible with columns
 
205
  on which the FK is created.
 
206
 
 
207
  RETURN
 
208
    0   Key valid
 
209
    1   Key invalid
 
210
*/
 
211
bool Foreign_key::validate(List<Create_field> &table_fields)
 
212
{
 
213
  Create_field  *sql_field;
 
214
  Key_part_spec *column;
 
215
  List_iterator<Key_part_spec> cols(columns);
 
216
  List_iterator<Create_field> it(table_fields);
 
217
  while ((column= cols++))
 
218
  {
 
219
    it.rewind();
 
220
    while ((sql_field= it++) &&
 
221
           my_strcasecmp(system_charset_info,
 
222
                         column->field_name.str,
 
223
                         sql_field->field_name)) {}
 
224
    if (!sql_field)
 
225
    {
 
226
      my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name.str);
 
227
      return true;
 
228
    }
 
229
    if (type == Key::FOREIGN_KEY && sql_field->vcol_info)
 
230
    {
 
231
      if (delete_opt == FK_OPTION_SET_NULL)
 
232
      {
 
233
        my_error(ER_WRONG_FK_OPTION_FOR_VIRTUAL_COLUMN, MYF(0),
 
234
                 "ON DELETE SET NULL");
 
235
        return true;
 
236
      }
 
237
      if (update_opt == FK_OPTION_SET_NULL)
 
238
      {
 
239
        my_error(ER_WRONG_FK_OPTION_FOR_VIRTUAL_COLUMN, MYF(0),
 
240
                 "ON UPDATE SET NULL");
 
241
        return true;
 
242
      }
 
243
      if (update_opt == FK_OPTION_CASCADE)
 
244
      {
 
245
        my_error(ER_WRONG_FK_OPTION_FOR_VIRTUAL_COLUMN, MYF(0),
 
246
                 "ON UPDATE CASCADE");
 
247
        return true;
 
248
      }
 
249
    }
 
250
  }
 
251
  return false;
 
252
}
 
253
 
 
254
 
186
255
/****************************************************************************
187
256
** Thread specific functions
188
257
****************************************************************************/
200
269
extern "C" int mysql_tmpfile(const char *prefix)
201
270
{
202
271
  char filename[FN_REFLEN];
203
 
  File fd = create_temp_file(filename, mysql_tmpdir, prefix,
204
 
                             O_CREAT | O_EXCL | O_RDWR | O_TEMPORARY,
 
272
  File fd = create_temp_file(filename, drizzle_tmpdir, prefix,
 
273
                             O_CREAT | O_EXCL | O_RDWR,
205
274
                             MYF(MY_WME));
206
275
  if (fd >= 0) {
207
 
    /*
208
 
      This can be removed once the following bug is fixed:
209
 
      Bug #28903  create_temp_file() doesn't honor O_TEMPORARY option
210
 
                  (file not removed) (Unix)
211
 
    */
212
276
    unlink(filename);
213
277
  }
214
278
 
217
281
 
218
282
 
219
283
extern "C"
220
 
int thd_in_lock_tables(const THD *thd)
221
 
{
222
 
  return test(thd->in_lock_tables);
223
 
}
224
 
 
225
 
 
226
 
extern "C"
227
 
int thd_tablespace_op(const THD *thd)
228
 
{
229
 
  return test(thd->tablespace_op);
230
 
}
231
 
 
232
 
 
233
 
extern "C"
234
 
const char *set_thd_proc_info(THD *thd, const char *info,
235
 
                              const char *calling_function __attribute__((unused)),
236
 
                              const char *calling_file __attribute__((unused)),
237
 
                              const unsigned int calling_line __attribute__((unused)))
238
 
{
239
 
  const char *old_info= thd->get_proc_info();
240
 
  thd->set_proc_info(info);
241
 
  return old_info;
242
 
}
243
 
 
244
 
extern "C"
245
 
void **thd_ha_data(const THD *thd, const struct handlerton *hton)
246
 
{
247
 
  return (void **) &thd->ha_data[hton->slot].ha_ptr;
248
 
}
249
 
 
250
 
extern "C"
251
 
int64_t thd_test_options(const THD *thd, int64_t test_options)
252
 
{
253
 
  return thd->options & test_options;
254
 
}
255
 
 
256
 
extern "C"
257
 
int thd_sql_command(const THD *thd)
258
 
{
259
 
  return (int) thd->lex->sql_command;
260
 
}
261
 
 
262
 
extern "C"
263
 
int thd_tx_isolation(const THD *thd)
264
 
{
265
 
  return (int) thd->variables.tx_isolation;
266
 
}
267
 
 
268
 
extern "C"
269
 
void thd_inc_row_count(THD *thd)
270
 
{
271
 
  thd->row_count++;
272
 
}
273
 
 
274
 
/**
275
 
  Clear this diagnostics area. 
 
284
int session_in_lock_tables(const Session *session)
 
285
{
 
286
  return test(session->in_lock_tables);
 
287
}
 
288
 
 
289
 
 
290
extern "C"
 
291
int session_tablespace_op(const Session *session)
 
292
{
 
293
  return test(session->tablespace_op);
 
294
}
 
295
 
 
296
 
 
297
/**
 
298
   Set the process info field of the Session structure.
 
299
 
 
300
   This function is used by plug-ins. Internally, the
 
301
   Session::set_proc_info() function should be used.
 
302
 
 
303
   @see Session::set_proc_info
 
304
 */
 
305
extern "C" void
 
306
set_session_proc_info(Session *session, const char *info)
 
307
{
 
308
  session->set_proc_info(info);
 
309
}
 
310
 
 
311
extern "C"
 
312
const char *get_session_proc_info(Session *session)
 
313
{
 
314
  return session->get_proc_info();
 
315
}
 
316
 
 
317
extern "C"
 
318
void **session_ha_data(const Session *session, const struct handlerton *hton)
 
319
{
 
320
  return (void **) &session->ha_data[hton->slot].ha_ptr;
 
321
}
 
322
 
 
323
extern "C"
 
324
int64_t session_test_options(const Session *session, int64_t test_options)
 
325
{
 
326
  return session->options & test_options;
 
327
}
 
328
 
 
329
extern "C"
 
330
int session_sql_command(const Session *session)
 
331
{
 
332
  return (int) session->lex->sql_command;
 
333
}
 
334
 
 
335
extern "C"
 
336
int session_tx_isolation(const Session *session)
 
337
{
 
338
  return (int) session->variables.tx_isolation;
 
339
}
 
340
 
 
341
extern "C"
 
342
void session_inc_row_count(Session *session)
 
343
{
 
344
  session->row_count++;
 
345
}
 
346
 
 
347
/**
 
348
  Clear this diagnostics area.
276
349
 
277
350
  Normally called at the end of a statement.
278
351
*/
300
373
*/
301
374
 
302
375
void
303
 
Diagnostics_area::set_ok_status(THD *thd, ha_rows affected_rows_arg,
 
376
Diagnostics_area::set_ok_status(Session *session, ha_rows affected_rows_arg,
304
377
                                uint64_t last_insert_id_arg,
305
378
                                const char *message_arg)
306
379
{
313
386
    return;
314
387
  /** Only allowed to report success if has not yet reported an error */
315
388
 
316
 
  m_server_status= thd->server_status;
317
 
  m_total_warn_count= thd->total_warn_count;
 
389
  m_server_status= session->server_status;
 
390
  m_total_warn_count= session->total_warn_count;
318
391
  m_affected_rows= affected_rows_arg;
319
392
  m_last_insert_id= last_insert_id_arg;
320
393
  if (message_arg)
321
 
    strmake(m_message, message_arg, sizeof(m_message) - 1);
 
394
    strncpy(m_message, message_arg, sizeof(m_message) - 1);
322
395
  else
323
396
    m_message[0]= '\0';
324
397
  m_status= DA_OK;
330
403
*/
331
404
 
332
405
void
333
 
Diagnostics_area::set_eof_status(THD *thd)
 
406
Diagnostics_area::set_eof_status(Session *session)
334
407
{
335
408
  /** Only allowed to report eof if has not yet reported an error */
336
409
 
342
415
  if (is_error() || is_disabled())
343
416
    return;
344
417
 
345
 
  m_server_status= thd->server_status;
 
418
  m_server_status= session->server_status;
346
419
  /*
347
420
    If inside a stored procedure, do not return the total
348
421
    number of warnings, since they are not available to the client
349
422
    anyway.
350
423
  */
351
 
  m_total_warn_count= thd->total_warn_count;
 
424
  m_total_warn_count= session->total_warn_count;
352
425
 
353
426
  m_status= DA_EOF;
354
427
}
358
431
*/
359
432
 
360
433
void
361
 
Diagnostics_area::set_error_status(THD *thd __attribute__((unused)),
 
434
Diagnostics_area::set_error_status(Session *session __attribute__((unused)),
362
435
                                   uint32_t sql_errno_arg,
363
436
                                   const char *message_arg)
364
437
{
376
449
    return;
377
450
 
378
451
  m_sql_errno= sql_errno_arg;
379
 
  strmake(m_message, message_arg, sizeof(m_message) - 1);
 
452
  strncpy(m_message, message_arg, sizeof(m_message) - 1);
380
453
 
381
454
  m_status= DA_ERROR;
382
455
}
398
471
}
399
472
 
400
473
 
401
 
THD::THD()
 
474
Session::Session()
402
475
   :Statement(&main_lex, &main_mem_root,
403
476
              /* statement id */ 0),
404
477
   Open_tables_state(refresh_version), rli_fake(0),
405
478
   lock_id(&main_lock_id),
406
 
   user_time(0), in_sub_stmt(0),
 
479
   user_time(0),
407
480
   binlog_table_maps(0), binlog_flags(0UL),
408
481
   arg_of_last_insert_id_function(false),
409
482
   first_successful_insert_id_in_prev_stmt(0),
410
 
   first_successful_insert_id_in_prev_stmt_for_binlog(0),
411
483
   first_successful_insert_id_in_cur_stmt(0),
412
 
   stmt_depends_on_first_successful_insert_id_in_prev_stmt(false),
413
484
   global_read_lock(0),
414
485
   is_fatal_error(0),
415
486
   transaction_rollback_request(0),
416
487
   is_fatal_sub_stmt_error(0),
417
 
   rand_used(0),
418
 
   time_zone_used(0),
419
488
   in_lock_tables(0),
420
 
   bootstrap(0),
421
489
   derived_tables_processing(false),
422
490
   m_lip(NULL)
423
491
{
431
499
  init_sql_alloc(&main_mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
432
500
  thread_stack= 0;
433
501
  catalog= (char*)"std"; // the only catalog we have for now
434
 
  main_security_ctx.init();
435
 
  security_ctx= &main_security_ctx;
436
502
  some_tables_deleted=no_errors=password= 0;
437
503
  query_start_used= 0;
438
504
  count_cuted_fields= CHECK_FIELD_IGNORE;
446
512
  limit_found_rows= 0;
447
513
  row_count_func= -1;
448
514
  statement_id_counter= 0UL;
449
 
  // Must be reset to handle error with THD's created for init of mysqld
 
515
  // Must be reset to handle error with Session's created for init of mysqld
450
516
  lex->current_select= 0;
451
517
  start_time=(time_t) 0;
452
518
  start_utime= 0L;
455
521
  slave_thread = 0;
456
522
  memset(&variables, 0, sizeof(variables));
457
523
  thread_id= 0;
458
 
  one_shot_set= 0;
459
524
  file_id = 0;
460
525
  query_id= 0;
461
526
  warn_id= 0;
462
527
  db_charset= global_system_variables.collation_database;
463
528
  memset(ha_data, 0, sizeof(ha_data));
 
529
  replication_data= 0;
464
530
  mysys_var=0;
465
531
  binlog_evt_union.do_union= false;
466
 
  dbug_sentry=THD_SENTRY_MAGIC;
467
 
  net.vio=0;
 
532
  dbug_sentry=Session_SENTRY_MAGIC;
 
533
  net.vio= 0;
468
534
  client_capabilities= 0;                       // minimalistic client
469
535
  system_thread= NON_SYSTEM_THREAD;
470
536
  cleanup_done= abort_on_warning= no_warnings_for_error= 0;
475
541
 
476
542
  /* Variables with default values */
477
543
  proc_info="login";
478
 
  where= THD::DEFAULT_WHERE;
 
544
  where= Session::DEFAULT_WHERE;
479
545
  server_id = ::server_id;
480
 
  slave_net = 0;
 
546
  slave_net= NULL;
481
547
  command=COM_CONNECT;
482
548
  *scramble= '\0';
483
549
 
500
566
  protocol= &protocol_text;                     // Default protocol
501
567
  protocol_text.init(this);
502
568
 
 
569
  const Query_id& query_id= Query_id::get_query_id();
503
570
  tablespace_op= false;
504
571
  tmp= sql_rnd();
505
 
  randominit(&rand, tmp + (ulong) &rand, tmp + (ulong) ::global_query_id);
 
572
  randominit(&rand, tmp + (ulong) &rand, tmp + query_id.value());
506
573
  substitute_null_with_insert_id = false;
507
574
  thr_lock_info_init(&lock_info); /* safety: will be reset after start */
508
575
  thr_lock_owner_init(&main_lock_id, &lock_info);
511
578
}
512
579
 
513
580
 
514
 
void THD::push_internal_handler(Internal_error_handler *handler)
 
581
void Session::push_internal_handler(Internal_error_handler *handler)
515
582
{
516
583
  /*
517
584
    TODO: The current implementation is limited to 1 handler at a time only.
518
 
    THD and sp_rcontext need to be modified to use a common handler stack.
 
585
    Session and sp_rcontext need to be modified to use a common handler stack.
519
586
  */
520
587
  assert(m_internal_handler == NULL);
521
588
  m_internal_handler= handler;
522
589
}
523
590
 
524
591
 
525
 
bool THD::handle_error(uint32_t sql_errno, const char *message,
 
592
bool Session::handle_error(uint32_t sql_errno, const char *message,
526
593
                       DRIZZLE_ERROR::enum_warning_level level)
527
594
{
528
595
  if (m_internal_handler)
534
601
}
535
602
 
536
603
 
537
 
void THD::pop_internal_handler()
 
604
void Session::pop_internal_handler()
538
605
{
539
606
  assert(m_internal_handler != NULL);
540
607
  m_internal_handler= NULL;
541
608
}
542
609
 
543
 
extern "C"
544
 
void *thd_alloc(DRIZZLE_THD thd, unsigned int size)
545
 
{
546
 
  return thd->alloc(size);
547
 
}
548
 
 
549
 
extern "C"
550
 
void *thd_calloc(DRIZZLE_THD thd, unsigned int size)
551
 
{
552
 
  return thd->calloc(size);
553
 
}
554
 
 
555
 
extern "C"
556
 
char *thd_strdup(DRIZZLE_THD thd, const char *str)
557
 
{
558
 
  return thd->strdup(str);
559
 
}
560
 
 
561
 
extern "C"
562
 
char *thd_strmake(DRIZZLE_THD thd, const char *str, unsigned int size)
563
 
{
564
 
  return thd->strmake(str, size);
565
 
}
566
 
 
567
 
extern "C"
568
 
LEX_STRING *thd_make_lex_string(THD *thd, LEX_STRING *lex_str,
569
 
                                const char *str, unsigned int size,
570
 
                                int allocate_lex_string)
571
 
{
572
 
  return thd->make_lex_string(lex_str, str, size,
573
 
                              (bool) allocate_lex_string);
574
 
}
575
 
 
576
 
extern "C"
577
 
void *thd_memdup(DRIZZLE_THD thd, const void* str, unsigned int size)
578
 
{
579
 
  return thd->memdup(str, size);
580
 
}
581
 
 
582
 
extern "C"
583
 
void thd_get_xid(const DRIZZLE_THD thd, DRIZZLE_XID *xid)
584
 
{
585
 
  *xid = *(DRIZZLE_XID *) &thd->transaction.xid_state.xid;
586
 
}
 
610
#if defined(__cplusplus)
 
611
extern "C" {
 
612
#endif
 
613
 
 
614
void *session_alloc(Session *session, unsigned int size)
 
615
{
 
616
  return session->alloc(size);
 
617
}
 
618
 
 
619
void *session_calloc(Session *session, unsigned int size)
 
620
{
 
621
  return session->calloc(size);
 
622
}
 
623
 
 
624
char *session_strdup(Session *session, const char *str)
 
625
{
 
626
  return session->strdup(str);
 
627
}
 
628
 
 
629
char *session_strmake(Session *session, const char *str, unsigned int size)
 
630
{
 
631
  return session->strmake(str, size);
 
632
}
 
633
 
 
634
void *session_memdup(Session *session, const void* str, unsigned int size)
 
635
{
 
636
  return session->memdup(str, size);
 
637
}
 
638
 
 
639
void session_get_xid(const Session *session, DRIZZLE_XID *xid)
 
640
{
 
641
  *xid = *(DRIZZLE_XID *) &session->transaction.xid_state.xid;
 
642
}
 
643
 
 
644
#if defined(__cplusplus)
 
645
}
 
646
#endif
587
647
 
588
648
/*
589
649
  Init common variables that has to be reset on start and on change_user
590
650
*/
591
651
 
592
 
void THD::init(void)
 
652
void Session::init(void)
593
653
{
594
654
  pthread_mutex_lock(&LOCK_global_system_variables);
595
 
  plugin_thdvar_init(this);
596
 
  variables.time_format= date_time_format_copy((THD*) 0,
 
655
  plugin_sessionvar_init(this);
 
656
  variables.time_format= date_time_format_copy((Session*) 0,
597
657
                                               variables.time_format);
598
 
  variables.date_format= date_time_format_copy((THD*) 0,
 
658
  variables.date_format= date_time_format_copy((Session*) 0,
599
659
                                               variables.date_format);
600
 
  variables.datetime_format= date_time_format_copy((THD*) 0,
 
660
  variables.datetime_format= date_time_format_copy((Session*) 0,
601
661
                                                   variables.datetime_format);
602
662
  /*
603
663
    variables= global_system_variables above has reset
607
667
  variables.pseudo_thread_id= thread_id;
608
668
  pthread_mutex_unlock(&LOCK_global_system_variables);
609
669
  server_status= SERVER_STATUS_AUTOCOMMIT;
610
 
  options= thd_startup_options;
 
670
  options= session_startup_options;
611
671
 
612
672
  if (variables.max_join_size == HA_POS_ERROR)
613
673
    options |= OPTION_BIG_SELECTS;
616
676
 
617
677
  transaction.all.modified_non_trans_table= transaction.stmt.modified_non_trans_table= false;
618
678
  open_options=ha_open_options;
619
 
  update_lock_default= (variables.low_priority_updates ?
620
 
                        TL_WRITE_LOW_PRIORITY :
621
 
                        TL_WRITE);
 
679
  update_lock_default= TL_WRITE;
622
680
  session_tx_isolation= (enum_tx_isolation) variables.tx_isolation;
623
681
  warn_list.empty();
624
682
  memset(warn_count, 0, sizeof(warn_count));
625
683
  total_warn_count= 0;
626
684
  update_charset();
627
 
  reset_current_stmt_binlog_row_based();
628
685
  memset(&status_var, 0, sizeof(status_var));
629
686
}
630
687
 
631
688
 
632
689
/*
633
 
  Init THD for query processing.
 
690
  Init Session for query processing.
634
691
  This has to be called once before we call mysql_parse.
635
 
  See also comments in sql_class.h.
 
692
  See also comments in session.h.
636
693
*/
637
694
 
638
 
void THD::init_for_queries()
 
695
void Session::init_for_queries()
639
696
{
640
 
  set_time(); 
 
697
  set_time();
641
698
  ha_enable_transaction(this,true);
642
699
 
643
700
  reset_root_defaults(mem_root, variables.query_alloc_block_size,
646
703
                      variables.trans_alloc_block_size,
647
704
                      variables.trans_prealloc_size);
648
705
  transaction.xid_state.xid.null();
649
 
  transaction.xid_state.in_thd=1;
 
706
  transaction.xid_state.in_session=1;
650
707
}
651
708
 
652
709
 
653
710
/* Do operations that may take a long time */
654
711
 
655
 
void THD::cleanup(void)
 
712
void Session::cleanup(void)
656
713
{
657
714
  assert(cleanup_done == 0);
658
715
 
679
736
  free((char*) variables.time_format);
680
737
  free((char*) variables.date_format);
681
738
  free((char*) variables.datetime_format);
682
 
  
 
739
 
683
740
  if (global_read_lock)
684
741
    unlock_global_read_lock(this);
685
742
 
687
744
  return;
688
745
}
689
746
 
690
 
THD::~THD()
 
747
Session::~Session()
691
748
{
692
 
  THD_CHECK_SENTRY(this);
693
 
  /* Ensure that no one is using THD */
 
749
  Session_CHECK_SENTRY(this);
 
750
  /* Ensure that no one is using Session */
694
751
  pthread_mutex_lock(&LOCK_delete);
695
752
  pthread_mutex_unlock(&LOCK_delete);
696
753
  add_to_status(&global_status_var, &status_var);
705
762
    cleanup();
706
763
 
707
764
  ha_close_connection(this);
708
 
  plugin_thdvar_cleanup(this);
 
765
  plugin_sessionvar_cleanup(this);
709
766
 
710
 
  main_security_ctx.destroy();
711
767
  if (db)
712
768
  {
713
769
    free(db);
717
773
  free_root(&transaction.mem_root,MYF(0));
718
774
  mysys_var=0;                                  // Safety (shouldn't be needed)
719
775
  pthread_mutex_destroy(&LOCK_delete);
720
 
  dbug_sentry= THD_SENTRY_GONE;
 
776
  dbug_sentry= Session_SENTRY_GONE;
721
777
  if (rli_fake)
722
778
  {
723
779
    delete rli_fake;
724
780
    rli_fake= NULL;
725
781
  }
726
 
  
 
782
 
727
783
  free_root(&main_mem_root, MYF(0));
 
784
  pthread_setspecific(THR_Session,  0);
728
785
  return;
729
786
}
730
787
 
762
819
    to_var       add to this array
763
820
    from_var     from this array
764
821
    dec_var      minus this array
765
 
  
 
822
 
766
823
  NOTE
767
824
    This function assumes that all variables are long/ulong.
768
825
*/
780
837
}
781
838
 
782
839
 
783
 
void THD::awake(THD::killed_state state_to_set)
 
840
void Session::awake(Session::killed_state state_to_set)
784
841
{
785
 
  THD_CHECK_SENTRY(this);
786
 
  safe_mutex_assert_owner(&LOCK_delete); 
 
842
  Session_CHECK_SENTRY(this);
 
843
  safe_mutex_assert_owner(&LOCK_delete);
787
844
 
788
845
  killed= state_to_set;
789
 
  if (state_to_set != THD::KILL_QUERY)
 
846
  if (state_to_set != Session::KILL_QUERY)
790
847
  {
791
848
    thr_alarm_kill(thread_id);
792
849
    if (!slave_thread)
813
870
      current_cond and current_mutex are 0), then the victim will not get
814
871
      a signal and it may wait "forever" on the cond (until
815
872
      we issue a second KILL or the status it's waiting for happens).
816
 
      It's true that we have set its thd->killed but it may not
 
873
      It's true that we have set its session->killed but it may not
817
874
      see it immediately and so may have time to reach the cond_wait().
818
875
    */
819
876
    if (mysys_var->current_cond && mysys_var->current_mutex)
832
889
  sql_alloc() and the structure for the net buffer
833
890
*/
834
891
 
835
 
bool THD::store_globals()
 
892
bool Session::store_globals()
836
893
{
837
894
  /*
838
895
    Assert that thread_stack is initialized: it's necessary to be able
840
897
  */
841
898
  assert(thread_stack);
842
899
 
843
 
  if (my_pthread_setspecific_ptr(THR_THD,  this) ||
844
 
      my_pthread_setspecific_ptr(THR_MALLOC, &mem_root))
 
900
  if (pthread_setspecific(THR_Session,  this) ||
 
901
      pthread_setspecific(THR_Mem_root, &mem_root))
845
902
    return 1;
846
903
  mysys_var=my_thread_var;
847
904
  /*
848
905
    Let mysqld define the thread id (not mysys)
849
 
    This allows us to move THD to different threads if needed.
 
906
    This allows us to move Session to different threads if needed.
850
907
  */
851
908
  mysys_var->id= thread_id;
852
909
  real_id= pthread_self();                      // For debugging
853
910
 
854
911
  /*
855
 
    We have to call thr_lock_info_init() again here as THD may have been
 
912
    We have to call thr_lock_info_init() again here as Session may have been
856
913
    created in another thread
857
914
  */
858
915
  thr_lock_info_init(&lock_info);
864
921
  Cleanup after query.
865
922
 
866
923
  SYNOPSIS
867
 
    THD::cleanup_after_query()
 
924
    Session::cleanup_after_query()
868
925
 
869
926
  DESCRIPTION
870
927
    This function is used to reset thread data to its default state.
876
933
    slave.
877
934
*/
878
935
 
879
 
void THD::cleanup_after_query()
 
936
void Session::cleanup_after_query()
880
937
{
881
938
  /*
882
 
    Reset rand_used so that detection of calls to rand() will save random 
 
939
    Reset rand_used so that detection of calls to rand() will save random
883
940
    seeds if needed by the slave.
884
 
 
885
 
    Do not reset rand_used if inside a stored function or trigger because 
886
 
    only the call to these operations is logged. Thus only the calling 
887
 
    statement needs to detect rand() calls made by its substatements. These
888
 
    substatements must not set rand_used to 0 because it would remove the
889
 
    detection of rand() by the calling statement. 
890
941
  */
891
 
  if (!in_sub_stmt) /* stored functions and triggers are a special case */
892
942
  {
893
943
    /* Forget those values, for next binlogger: */
894
 
    stmt_depends_on_first_successful_insert_id_in_prev_stmt= 0;
895
944
    auto_inc_intervals_in_cur_stmt_for_binlog.empty();
896
 
    rand_used= 0;
897
945
  }
898
946
  if (first_successful_insert_id_in_cur_stmt > 0)
899
947
  {
900
948
    /* set what LAST_INSERT_ID() will return */
901
 
    first_successful_insert_id_in_prev_stmt= 
 
949
    first_successful_insert_id_in_prev_stmt=
902
950
      first_successful_insert_id_in_cur_stmt;
903
951
    first_successful_insert_id_in_cur_stmt= 0;
904
952
    substitute_null_with_insert_id= true;
907
955
  /* Free Items that were created during this execution */
908
956
  free_items();
909
957
  /* Reset where. */
910
 
  where= THD::DEFAULT_WHERE;
 
958
  where= Session::DEFAULT_WHERE;
911
959
}
912
960
 
913
961
 
921
969
                              instead of using lex_str value
922
970
  @return  NULL on failure, or pointer to the LEX_STRING object
923
971
*/
924
 
LEX_STRING *THD::make_lex_string(LEX_STRING *lex_str,
 
972
LEX_STRING *Session::make_lex_string(LEX_STRING *lex_str,
925
973
                                 const char* str, uint32_t length,
926
974
                                 bool allocate_lex_string)
927
975
{
955
1003
        In this case to->str will point to 0 and to->length will be 0.
956
1004
*/
957
1005
 
958
 
bool THD::convert_string(LEX_STRING *to, const CHARSET_INFO * const to_cs,
 
1006
bool Session::convert_string(LEX_STRING *to, const CHARSET_INFO * const to_cs,
959
1007
                         const char *from, uint32_t from_length,
960
1008
                         const CHARSET_INFO * const from_cs)
961
1009
{
977
1025
  Convert string from source character set to target character set inplace.
978
1026
 
979
1027
  SYNOPSIS
980
 
    THD::convert_string
 
1028
    Session::convert_string
981
1029
 
982
1030
  DESCRIPTION
983
 
    Convert string using convert_buffer - buffer for character set 
 
1031
    Convert string using convert_buffer - buffer for character set
984
1032
    conversion shared between all protocols.
985
1033
 
986
1034
  RETURN
988
1036
   !0   out of memory
989
1037
*/
990
1038
 
991
 
bool THD::convert_string(String *s, const CHARSET_INFO * const from_cs,
 
1039
bool Session::convert_string(String *s, const CHARSET_INFO * const from_cs,
992
1040
                         const CHARSET_INFO * const to_cs)
993
1041
{
994
1042
  uint32_t dummy_errors;
1009
1057
  Update some cache variables when character set changes
1010
1058
*/
1011
1059
 
1012
 
void THD::update_charset()
 
1060
void Session::update_charset()
1013
1061
{
1014
1062
  uint32_t not_used;
1015
1063
  charset_is_system_charset= !String::needs_conversion(0,charset(),
1016
1064
                                                       system_charset_info,
1017
1065
                                                       &not_used);
1018
 
  charset_is_collation_connection= 
 
1066
  charset_is_collation_connection=
1019
1067
    !String::needs_conversion(0,charset(),variables.collation_connection,
1020
1068
                              &not_used);
1021
 
  charset_is_character_set_filesystem= 
 
1069
  charset_is_character_set_filesystem=
1022
1070
    !String::needs_conversion(0, charset(),
1023
1071
                              variables.character_set_filesystem, &not_used);
1024
1072
}
1039
1087
 
1040
1088
/* add table to list of changed in transaction tables */
1041
1089
 
1042
 
void THD::add_changed_table(Table *table)
 
1090
void Session::add_changed_table(Table *table)
1043
1091
{
1044
1092
  assert((options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) &&
1045
1093
              table->file->has_transactions());
1049
1097
}
1050
1098
 
1051
1099
 
1052
 
void THD::add_changed_table(const char *key, long key_length)
 
1100
void Session::add_changed_table(const char *key, long key_length)
1053
1101
{
1054
1102
  CHANGED_TableList **prev_changed = &transaction.changed_tables;
1055
1103
  CHANGED_TableList *curr = transaction.changed_tables;
1081
1129
}
1082
1130
 
1083
1131
 
1084
 
CHANGED_TableList* THD::changed_table_dup(const char *key, long key_length)
 
1132
CHANGED_TableList* Session::changed_table_dup(const char *key, long key_length)
1085
1133
{
1086
 
  CHANGED_TableList* new_table = 
 
1134
  CHANGED_TableList* new_table =
1087
1135
    (CHANGED_TableList*) trans_alloc(ALIGN_SIZE(sizeof(CHANGED_TableList))+
1088
1136
                                      key_length + 1);
1089
1137
  if (!new_table)
1102
1150
}
1103
1151
 
1104
1152
 
1105
 
int THD::send_explain_fields(select_result *result)
 
1153
int Session::send_explain_fields(select_result *result)
1106
1154
{
1107
1155
  List<Item> field_list;
1108
1156
  Item *item;
1162
1210
/*
1163
1211
  Register an item tree tree transformation, performed by the query
1164
1212
  optimizer. We need a pointer to runtime_memroot because it may be !=
1165
 
  thd->mem_root (this may no longer be a true statement)
 
1213
  session->mem_root (this may no longer be a true statement)
1166
1214
*/
1167
1215
 
1168
 
void THD::nocheck_register_item_tree_change(Item **place, Item *old_value,
 
1216
void Session::nocheck_register_item_tree_change(Item **place, Item *old_value,
1169
1217
                                            MEM_ROOT *runtime_memroot)
1170
1218
{
1171
1219
  Item_change_record *change;
1178
1226
  if (change_mem == 0)
1179
1227
  {
1180
1228
    /*
1181
 
      OOM, thd->fatal_error() is called by the error handler of the
 
1229
      OOM, session->fatal_error() is called by the error handler of the
1182
1230
      memroot. Just return.
1183
1231
    */
1184
1232
    return;
1190
1238
}
1191
1239
 
1192
1240
 
1193
 
void THD::rollback_item_tree_changes()
 
1241
void Session::rollback_item_tree_changes()
1194
1242
{
1195
1243
  I_List_iterator<Item_change_record> it(change_list);
1196
1244
  Item_change_record *change;
1209
1257
 
1210
1258
select_result::select_result()
1211
1259
{
1212
 
  thd=current_thd;
 
1260
  session=current_session;
1213
1261
}
1214
1262
 
1215
1263
void select_result::send_error(uint32_t errcode,const char *err)
1249
1297
bool select_send::send_fields(List<Item> &list, uint32_t flags)
1250
1298
{
1251
1299
  bool res;
1252
 
  if (!(res= thd->protocol->send_fields(&list, flags)))
 
1300
  if (!(res= session->protocol->send_fields(&list, flags)))
1253
1301
    is_result_set_started= 1;
1254
1302
  return res;
1255
1303
}
1260
1308
}
1261
1309
 
1262
1310
 
1263
 
/** 
 
1311
/**
1264
1312
  Cleanup an instance of this class for re-use
1265
1313
  at next execution of a prepared statement/
1266
1314
  stored procedure statement.
1284
1332
  /*
1285
1333
    We may be passing the control from mysqld to the client: release the
1286
1334
    InnoDB adaptive hash S-latch to avoid thread deadlocks if it was reserved
1287
 
    by thd
 
1335
    by session
1288
1336
  */
1289
 
  ha_release_temporary_latches(thd);
 
1337
  ha_release_temporary_latches(session);
1290
1338
 
1291
1339
  List_iterator_fast<Item> li(items);
1292
 
  Protocol *protocol= thd->protocol;
 
1340
  Protocol *protocol= session->protocol;
1293
1341
  char buff[MAX_FIELD_WIDTH];
1294
1342
  String buffer(buff, sizeof(buff), &my_charset_bin);
1295
1343
 
1304
1352
      break;
1305
1353
    }
1306
1354
  }
1307
 
  thd->sent_row_count++;
1308
 
  if (thd->is_error())
 
1355
  session->sent_row_count++;
 
1356
  if (session->is_error())
1309
1357
  {
1310
1358
    protocol->remove_last_row();
1311
1359
    return(1);
1312
1360
  }
1313
 
  if (thd->vio_ok())
 
1361
  if (session->vio_ok())
1314
1362
    return(protocol->write());
1315
1363
  return(0);
1316
1364
}
1317
1365
 
1318
1366
bool select_send::send_eof()
1319
1367
{
1320
 
  /* 
 
1368
  /*
1321
1369
    We may be passing the control from mysqld to the client: release the
1322
1370
    InnoDB adaptive hash S-latch to avoid thread deadlocks if it was reserved
1323
 
    by thd 
 
1371
    by session
1324
1372
  */
1325
 
  ha_release_temporary_latches(thd);
 
1373
  ha_release_temporary_latches(session);
1326
1374
 
1327
1375
  /* Unlock tables before sending packet to gain some speed */
1328
 
  if (thd->lock)
 
1376
  if (session->lock)
1329
1377
  {
1330
 
    mysql_unlock_tables(thd, thd->lock);
1331
 
    thd->lock=0;
 
1378
    mysql_unlock_tables(session, session->lock);
 
1379
    session->lock=0;
1332
1380
  }
1333
 
  ::my_eof(thd);
 
1381
  ::my_eof(session);
1334
1382
  is_result_set_started= 0;
1335
1383
  return false;
1336
1384
}
1365
1413
      function, SELECT INTO has to have an own SQLCOM.
1366
1414
      TODO: split from SQLCOM_SELECT
1367
1415
    */
1368
 
    ::my_ok(thd,row_count);
 
1416
    ::my_ok(session,row_count);
1369
1417
  }
1370
1418
  file= -1;
1371
1419
  return error;
1402
1450
 
1403
1451
select_export::~select_export()
1404
1452
{
1405
 
  thd->sent_row_count=row_count;
 
1453
  session->sent_row_count=row_count;
1406
1454
}
1407
1455
 
1408
1456
 
1411
1459
 
1412
1460
  SYNOPSIS
1413
1461
    create_file()
1414
 
    thd                 Thread handle
 
1462
    session                     Thread handle
1415
1463
    path                File name
1416
1464
    exchange            Excange class
1417
1465
    cache               IO cache
1422
1470
*/
1423
1471
 
1424
1472
 
1425
 
static File create_file(THD *thd, char *path, sql_exchange *exchange,
 
1473
static File create_file(Session *session, char *path, sql_exchange *exchange,
1426
1474
                        IO_CACHE *cache)
1427
1475
{
1428
1476
  File file;
1434
1482
 
1435
1483
  if (!dirname_length(exchange->file_name))
1436
1484
  {
1437
 
    strxnmov(path, FN_REFLEN-1, mysql_real_data_home, thd->db ? thd->db : "",
1438
 
             NULL);
 
1485
    strcpy(path, drizzle_real_data_home);
 
1486
    if (session->db)
 
1487
      strncat(path, session->db, FN_REFLEN-strlen(drizzle_real_data_home)-1);
1439
1488
    (void) fn_format(path, exchange->file_name, path, "", option);
1440
1489
  }
1441
1490
  else
1442
 
    (void) fn_format(path, exchange->file_name, mysql_real_data_home, "", option);
 
1491
    (void) fn_format(path, exchange->file_name, drizzle_real_data_home, "", option);
1443
1492
 
1444
1493
  if (opt_secure_file_priv &&
1445
1494
      strncmp(opt_secure_file_priv, path, strlen(opt_secure_file_priv)))
1465
1514
  if (init_io_cache(cache, file, 0L, WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1466
1515
  {
1467
1516
    my_close(file, MYF(0));
1468
 
    my_delete(path, MYF(0));  // Delete file on error, it was just created 
 
1517
    my_delete(path, MYF(0));  // Delete file on error, it was just created
1469
1518
    return -1;
1470
1519
  }
1471
1520
  return file;
1479
1528
  bool string_results= false, non_string_results= false;
1480
1529
  unit= u;
1481
1530
  if ((uint) strlen(exchange->file_name) + NAME_LEN >= FN_REFLEN)
1482
 
    strmake(path,exchange->file_name,FN_REFLEN-1);
 
1531
    strncpy(path,exchange->file_name,FN_REFLEN-1);
1483
1532
 
1484
 
  if ((file= create_file(thd, path, exchange, &cache)) < 0)
1485
 
    return 1;
1486
1533
  /* Check if there is any blobs in data */
1487
1534
  {
1488
1535
    List_iterator_fast<Item> li(list);
1524
1571
      (exchange->opt_enclosed && non_string_results &&
1525
1572
       field_term_length && strchr(NUMERIC_CHARS, field_term_char)))
1526
1573
  {
1527
 
    push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1528
 
                 ER_AMBIGUOUS_FIELD_TERM, ER(ER_AMBIGUOUS_FIELD_TERM));
1529
 
    is_ambiguous_field_term= true;
 
1574
    my_error(ER_AMBIGUOUS_FIELD_TERM, MYF(0));
 
1575
    return 1;
1530
1576
  }
1531
 
  else
1532
 
    is_ambiguous_field_term= false;
 
1577
 
 
1578
  if ((file= create_file(session, path, exchange, &cache)) < 0)
 
1579
    return 1;
1533
1580
 
1534
1581
  return 0;
1535
1582
}
1603
1650
      {
1604
1651
        char *pos, *start, *end;
1605
1652
        const CHARSET_INFO * const res_charset= res->charset();
1606
 
        const CHARSET_INFO * const character_set_client= thd->variables.
 
1653
        const CHARSET_INFO * const character_set_client= session->variables.
1607
1654
                                                            character_set_client;
1608
1655
        bool check_second_byte= (res_charset == &my_charset_bin) &&
1609
1656
                                 character_set_client->
1631
1678
            for the clients with character sets big5, cp932, gbk and sjis,
1632
1679
            which can have the escape character (0x5C "\" by default)
1633
1680
            as the second byte of a multi-byte sequence.
1634
 
            
 
1681
 
1635
1682
            If
1636
1683
            - pos[0] is a valid multi-byte head (e.g 0xEE) and
1637
1684
            - pos[1] is 0x00, which will be escaped as "\0",
1638
 
            
 
1685
 
1639
1686
            then we'll get "0xEE + 0x5C + 0x30" in the output file.
1640
 
            
 
1687
 
1641
1688
            If this file is later loaded using this sequence of commands:
1642
 
            
 
1689
 
1643
1690
            mysql> create table t1 (a varchar(128)) character set big5;
1644
1691
            mysql> LOAD DATA INFILE 'dump.txt' INTO Table t1;
1645
 
            
 
1692
 
1646
1693
            then 0x5C will be misinterpreted as the second byte
1647
1694
            of a multi-byte character "0xEE + 0x5C", instead of
1648
1695
            escape character for 0x00.
1649
 
            
 
1696
 
1650
1697
            To avoid this confusion, we'll escape the multi-byte
1651
1698
            head character too, so the sequence "0xEE + 0x00" will be
1652
1699
            dumped as "0x5C + 0xEE + 0x5C + 0x30".
1653
 
            
 
1700
 
1654
1701
            Note, in the condition below we only check if
1655
1702
            mbcharlen is equal to 2, because there are no
1656
1703
            character sets with mbmaxlen longer than 2
1739
1786
                     SELECT_LEX_UNIT *u)
1740
1787
{
1741
1788
  unit= u;
1742
 
  return (int) ((file= create_file(thd, path, exchange, &cache)) < 0);
 
1789
  return (int) ((file= create_file(session, path, exchange, &cache)) < 0);
1743
1790
}
1744
1791
 
1745
1792
 
1756
1803
    unit->offset_limit_cnt--;
1757
1804
    return(0);
1758
1805
  }
1759
 
  if (row_count++ > 1) 
 
1806
  if (row_count++ > 1)
1760
1807
  {
1761
1808
    my_message(ER_TOO_MANY_ROWS, ER(ER_TOO_MANY_ROWS), MYF(0));
1762
1809
    goto err;
1940
1987
int select_dumpvar::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
1941
1988
{
1942
1989
  unit= u;
1943
 
  
 
1990
 
1944
1991
  if (var_list.elements != list.elements)
1945
1992
  {
1946
1993
    my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT,
1947
1994
               ER(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT), MYF(0));
1948
1995
    return 1;
1949
 
  }               
 
1996
  }
1950
1997
  return 0;
1951
1998
}
1952
1999
 
1999
2046
  Don't free mem_root, as mem_root is freed in the end of dispatch_command
2000
2047
  (once for any command).
2001
2048
*/
2002
 
void THD::end_statement()
 
2049
void Session::end_statement()
2003
2050
{
2004
2051
  /* Cleanup SQL processing state to reuse this statement in next query. */
2005
2052
  lex_end(lex);
2006
2053
}
2007
2054
 
2008
2055
 
2009
 
bool THD::copy_db_to(char **p_db, size_t *p_db_length)
 
2056
bool Session::copy_db_to(char **p_db, size_t *p_db_length)
2010
2057
{
2011
2058
  if (db == NULL)
2012
2059
  {
2031
2078
    unit->offset_limit_cnt--;
2032
2079
    return(0);
2033
2080
  }
2034
 
  if (row_count++) 
 
2081
  if (row_count++)
2035
2082
  {
2036
2083
    my_message(ER_TOO_MANY_ROWS, ER(ER_TOO_MANY_ROWS), MYF(0));
2037
2084
    return(1);
2041
2088
    if (mv->local == 0)
2042
2089
    {
2043
2090
      Item_func_set_user_var *suv= new Item_func_set_user_var(mv->s, item);
2044
 
      suv->fix_fields(thd, 0);
 
2091
      suv->fix_fields(session, 0);
2045
2092
      suv->check(0);
2046
2093
      suv->update();
2047
2094
    }
2048
2095
  }
2049
 
  return(thd->is_error());
 
2096
  return(session->is_error());
2050
2097
}
2051
2098
 
2052
2099
bool select_dumpvar::send_eof()
2053
2100
{
2054
2101
  if (! row_count)
2055
 
    push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
2102
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
2056
2103
                 ER_SP_FETCH_NO_DATA, ER(ER_SP_FETCH_NO_DATA));
2057
2104
  /*
2058
2105
    In order to remember the value of affected rows for ROW_COUNT()
2059
2106
    function, SELECT INTO has to have an own SQLCOM.
2060
2107
    TODO: split from SQLCOM_SELECT
2061
2108
  */
2062
 
  ::my_ok(thd,row_count);
 
2109
  ::my_ok(session,row_count);
2063
2110
  return 0;
2064
2111
}
2065
2112
 
2078
2125
  return;
2079
2126
}
2080
2127
 
2081
 
 
2082
 
void thd_increment_bytes_sent(ulong length)
2083
 
{
2084
 
  THD *thd=current_thd;
2085
 
  if (likely(thd != 0))
2086
 
  { /* current_thd==0 when close_connection() calls net_send_error() */
2087
 
    thd->status_var.bytes_sent+= length;
2088
 
  }
2089
 
}
2090
 
 
2091
 
 
2092
 
void thd_increment_bytes_received(ulong length)
2093
 
{
2094
 
  current_thd->status_var.bytes_received+= length;
2095
 
}
2096
 
 
2097
 
 
2098
 
void thd_increment_net_big_packet_count(ulong length)
2099
 
{
2100
 
  current_thd->status_var.net_big_packet_count+= length;
2101
 
}
2102
 
 
2103
 
void THD::send_kill_message() const
 
2128
void TMP_TABLE_PARAM::cleanup(void)
 
2129
{
 
2130
  /* Fix for Intel compiler */
 
2131
  if (copy_field)
 
2132
  {
 
2133
    delete [] copy_field;
 
2134
    save_copy_field= copy_field= 0;
 
2135
  }
 
2136
}
 
2137
 
 
2138
 
 
2139
void session_increment_bytes_sent(ulong length)
 
2140
{
 
2141
  Session *session=current_session;
 
2142
  if (likely(session != 0))
 
2143
  { /* current_session==0 when close_connection() calls net_send_error() */
 
2144
    session->status_var.bytes_sent+= length;
 
2145
  }
 
2146
}
 
2147
 
 
2148
 
 
2149
void session_increment_bytes_received(ulong length)
 
2150
{
 
2151
  current_session->status_var.bytes_received+= length;
 
2152
}
 
2153
 
 
2154
 
 
2155
void session_increment_net_big_packet_count(ulong length)
 
2156
{
 
2157
  current_session->status_var.net_big_packet_count+= length;
 
2158
}
 
2159
 
 
2160
void Session::send_kill_message() const
2104
2161
{
2105
2162
  int err= killed_errno();
2106
2163
  if (err)
2107
2164
    my_message(err, ER(err), MYF(0));
2108
2165
}
2109
2166
 
2110
 
void THD::set_status_var_init()
 
2167
void Session::set_status_var_init()
2111
2168
{
2112
2169
  memset(&status_var, 0, sizeof(status_var));
2113
2170
}
2114
2171
 
2115
 
 
2116
 
void Security_context::init()
2117
 
{
2118
 
  user= ip= 0;
2119
 
}
2120
 
 
2121
 
 
2122
 
void Security_context::destroy()
2123
 
{
2124
 
  // If not pointer to constant
2125
 
  if (user)
2126
 
  {
2127
 
    free(user);
2128
 
    user= NULL;
2129
 
  }
2130
 
  if (ip)
2131
 
  {
2132
 
    free(ip);
2133
 
    ip= NULL;
2134
 
  }
2135
 
}
2136
 
 
2137
 
 
2138
2172
void Security_context::skip_grants()
2139
2173
{
2140
2174
  /* privileges for the user are unknown everything is allowed */
2149
2183
  access to mysql.proc table to find definitions of stored routines.
2150
2184
****************************************************************************/
2151
2185
 
2152
 
void THD::reset_n_backup_open_tables_state(Open_tables_state *backup)
 
2186
void Session::reset_n_backup_open_tables_state(Open_tables_state *backup)
2153
2187
{
2154
2188
  backup->set_open_tables_state(this);
2155
2189
  reset_open_tables_state();
2158
2192
}
2159
2193
 
2160
2194
 
2161
 
void THD::restore_backup_open_tables_state(Open_tables_state *backup)
 
2195
void Session::restore_backup_open_tables_state(Open_tables_state *backup)
2162
2196
{
2163
2197
  /*
2164
2198
    Before we will throw away current open tables state we want
2171
2205
  return;
2172
2206
}
2173
2207
 
 
2208
 
 
2209
bool Session::set_db(const char *new_db, size_t new_db_len)
 
2210
{
 
2211
  /* Do not reallocate memory if current chunk is big enough. */
 
2212
  if (db && new_db && db_length >= new_db_len)
 
2213
    memcpy(db, new_db, new_db_len+1);
 
2214
  else
 
2215
  {
 
2216
    if (db)
 
2217
      free(db);
 
2218
    if (new_db)
 
2219
    {
 
2220
      db= (char *)malloc(new_db_len + 1);
 
2221
      if (db != NULL)
 
2222
      {
 
2223
        memcpy(db, new_db, new_db_len);
 
2224
        db[new_db_len]= 0;
 
2225
      }
 
2226
    }
 
2227
    else
 
2228
      db= NULL;
 
2229
  }
 
2230
  db_length= db ? new_db_len : 0;
 
2231
  return new_db && !db;
 
2232
}
 
2233
 
 
2234
 
2174
2235
/**
2175
2236
  Check the killed state of a user thread
2176
 
  @param thd  user thread
 
2237
  @param session  user thread
2177
2238
  @retval 0 the user thread is active
2178
2239
  @retval 1 the user thread has been killed
2179
2240
*/
2180
 
extern "C" int thd_killed(const DRIZZLE_THD thd)
 
2241
extern "C" int session_killed(const Session *session)
2181
2242
{
2182
 
  return(thd->killed);
 
2243
  return(session->killed);
2183
2244
}
2184
2245
 
2185
2246
/**
2186
2247
  Return the thread id of a user thread
2187
 
  @param thd user thread
 
2248
  @param session user thread
2188
2249
  @return thread id
2189
2250
*/
2190
 
extern "C" unsigned long thd_get_thread_id(const DRIZZLE_THD thd)
2191
 
{
2192
 
  return((unsigned long)thd->thread_id);
2193
 
}
2194
 
 
2195
 
 
2196
 
#ifdef INNODB_COMPATIBILITY_HOOKS
2197
 
extern "C" const struct charset_info_st *thd_charset(DRIZZLE_THD thd)
2198
 
{
2199
 
  return(thd->charset());
2200
 
}
2201
 
 
2202
 
extern "C" char **thd_query(DRIZZLE_THD thd)
2203
 
{
2204
 
  return(&thd->query);
2205
 
}
2206
 
 
2207
 
extern "C" int thd_slave_thread(const DRIZZLE_THD thd)
2208
 
{
2209
 
  return(thd->slave_thread);
2210
 
}
2211
 
 
2212
 
extern "C" int thd_non_transactional_update(const DRIZZLE_THD thd)
2213
 
{
2214
 
  return(thd->transaction.all.modified_non_trans_table);
2215
 
}
2216
 
 
2217
 
extern "C" int thd_binlog_format(const DRIZZLE_THD thd)
2218
 
{
2219
 
  return (int) thd->variables.binlog_format;
2220
 
}
2221
 
 
2222
 
extern "C" void thd_mark_transaction_to_rollback(DRIZZLE_THD thd, bool all)
2223
 
{
2224
 
  mark_transaction_to_rollback(thd, all);
2225
 
}
2226
 
#endif // INNODB_COMPATIBILITY_HOOKS */
 
2251
extern "C" unsigned long session_get_thread_id(const Session *session)
 
2252
{
 
2253
  return((unsigned long)session->thread_id);
 
2254
}
 
2255
 
 
2256
 
 
2257
extern "C"
 
2258
LEX_STRING *session_make_lex_string(Session *session, LEX_STRING *lex_str,
 
2259
                                const char *str, unsigned int size,
 
2260
                                int allocate_lex_string)
 
2261
{
 
2262
  return session->make_lex_string(lex_str, str, size,
 
2263
                              (bool) allocate_lex_string);
 
2264
}
 
2265
 
 
2266
extern "C" const struct charset_info_st *session_charset(Session *session)
 
2267
{
 
2268
  return(session->charset());
 
2269
}
 
2270
 
 
2271
extern "C" char **session_query(Session *session)
 
2272
{
 
2273
  return(&session->query);
 
2274
}
 
2275
 
 
2276
extern "C" int session_slave_thread(const Session *session)
 
2277
{
 
2278
  return(session->slave_thread);
 
2279
}
 
2280
 
 
2281
extern "C" int session_non_transactional_update(const Session *session)
 
2282
{
 
2283
  return(session->transaction.all.modified_non_trans_table);
 
2284
}
 
2285
 
 
2286
extern "C" void session_mark_transaction_to_rollback(Session *session, bool all)
 
2287
{
 
2288
  mark_transaction_to_rollback(session, all);
 
2289
}
2227
2290
 
2228
2291
 
2229
2292
/**
2230
2293
  Mark transaction to rollback and mark error as fatal to a sub-statement.
2231
2294
 
2232
 
  @param  thd   Thread handle
 
2295
  @param  session   Thread handle
2233
2296
  @param  all   true <=> rollback main transaction.
2234
2297
*/
2235
2298
 
2236
 
void mark_transaction_to_rollback(THD *thd, bool all)
 
2299
void mark_transaction_to_rollback(Session *session, bool all)
2237
2300
{
2238
 
  if (thd)
 
2301
  if (session)
2239
2302
  {
2240
 
    thd->is_fatal_sub_stmt_error= true;
2241
 
    thd->transaction_rollback_request= all;
 
2303
    session->is_fatal_sub_stmt_error= true;
 
2304
    session->transaction_rollback_request= all;
2242
2305
  }
2243
2306
}
2244
2307
/***************************************************************************
2260
2323
 
2261
2324
void xid_free_hash(void *ptr)
2262
2325
{
2263
 
  if (!((XID_STATE*)ptr)->in_thd)
 
2326
  if (!((XID_STATE*)ptr)->in_session)
2264
2327
    free((unsigned char*)ptr);
2265
2328
}
2266
2329
 
2296
2359
  pthread_mutex_lock(&LOCK_xid_cache);
2297
2360
  if (hash_search(&xid_cache, xid->key(), xid->key_length()))
2298
2361
    res=0;
2299
 
  else if (!(xs=(XID_STATE *)my_malloc(sizeof(*xs), MYF(MY_WME))))
 
2362
  else if (!(xs=(XID_STATE *)malloc(sizeof(*xs))))
2300
2363
    res=1;
2301
2364
  else
2302
2365
  {
2303
2366
    xs->xa_state=xa_state;
2304
2367
    xs->xid.set(xid);
2305
 
    xs->in_thd=0;
 
2368
    xs->in_session=0;
2306
2369
    res=my_hash_insert(&xid_cache, (unsigned char*)xs);
2307
2370
  }
2308
2371
  pthread_mutex_unlock(&LOCK_xid_cache);
2328
2391
  pthread_mutex_unlock(&LOCK_xid_cache);
2329
2392
}
2330
2393
 
2331
 
/*
2332
 
  Implementation of interface to write rows to the binary log through the
2333
 
  thread.  The thread is responsible for writing the rows it has
2334
 
  inserted/updated/deleted.
2335
 
*/
2336
 
 
2337
 
 
2338
 
/*
2339
 
  Template member function for ensuring that there is an rows log
2340
 
  event of the apropriate type before proceeding.
2341
 
 
2342
 
  PRE CONDITION:
2343
 
    - Events of type 'RowEventT' have the type code 'type_code'.
2344
 
    
2345
 
  POST CONDITION:
2346
 
    If a non-NULL pointer is returned, the pending event for thread 'thd' will
2347
 
    be an event of type 'RowEventT' (which have the type code 'type_code')
2348
 
    will either empty or have enough space to hold 'needed' bytes.  In
2349
 
    addition, the columns bitmap will be correct for the row, meaning that
2350
 
    the pending event will be flushed if the columns in the event differ from
2351
 
    the columns suppled to the function.
2352
 
 
2353
 
  RETURNS
2354
 
    If no error, a non-NULL pending event (either one which already existed or
2355
 
    the newly created one).
2356
 
    If error, NULL.
2357
 
 */
2358
 
 
2359
 
template <class RowsEventT> Rows_log_event* 
2360
 
THD::binlog_prepare_pending_rows_event(Table* table, uint32_t serv_id,
2361
 
                                       size_t needed,
2362
 
                                       bool is_transactional,
2363
 
                                       RowsEventT *hint __attribute__((unused)))
2364
 
{
2365
 
  /* Pre-conditions */
2366
 
  assert(table->s->table_map_id != UINT32_MAX);
2367
 
 
2368
 
  /* Fetch the type code for the RowsEventT template parameter */
2369
 
  int const type_code= RowsEventT::TYPE_CODE;
2370
 
 
2371
 
  /*
2372
 
    There is no good place to set up the transactional data, so we
2373
 
    have to do it here.
2374
 
  */
2375
 
  if (binlog_setup_trx_data())
2376
 
    return(NULL);
2377
 
 
2378
 
  Rows_log_event* pending= binlog_get_pending_rows_event();
2379
 
 
2380
 
  if (unlikely(pending && !pending->is_valid()))
2381
 
    return(NULL);
2382
 
 
2383
 
  /*
2384
 
    Check if the current event is non-NULL and a write-rows
2385
 
    event. Also check if the table provided is mapped: if it is not,
2386
 
    then we have switched to writing to a new table.
2387
 
    If there is no pending event, we need to create one. If there is a pending
2388
 
    event, but it's not about the same table id, or not of the same type
2389
 
    (between Write, Update and Delete), or not the same affected columns, or
2390
 
    going to be too big, flush this event to disk and create a new pending
2391
 
    event.
2392
 
 
2393
 
    The last test is necessary for the Cluster injector to work
2394
 
    correctly. The reason is that the Cluster can inject two write
2395
 
    rows with different column bitmaps if there is an insert followed
2396
 
    by an update in the same transaction, and these are grouped into a
2397
 
    single epoch/transaction when fed to the injector.
2398
 
 
2399
 
    TODO: Fix the code so that the last test can be removed.
2400
 
  */
2401
 
  if (!pending ||
2402
 
      pending->server_id != serv_id || 
2403
 
      pending->get_table_id() != table->s->table_map_id ||
2404
 
      pending->get_type_code() != type_code || 
2405
 
      pending->get_data_size() + needed > opt_binlog_rows_event_max_size ||
2406
 
      !bitmap_cmp(pending->get_cols(), table->write_set))
2407
 
    {
2408
 
    /* Create a new RowsEventT... */
2409
 
    Rows_log_event* const
2410
 
        ev= new RowsEventT(this, table, table->s->table_map_id,
2411
 
                           is_transactional);
2412
 
    if (unlikely(!ev))
2413
 
      return(NULL);
2414
 
    ev->server_id= serv_id; // I don't like this, it's too easy to forget.
2415
 
    /*
2416
 
      flush the pending event and replace it with the newly created
2417
 
      event...
2418
 
    */
2419
 
    if (unlikely(mysql_bin_log.flush_and_set_pending_rows_event(this, ev)))
2420
 
    {
2421
 
      delete ev;
2422
 
      return(NULL);
2423
 
    }
2424
 
 
2425
 
    return(ev);               /* This is the new pending event */
2426
 
  }
2427
 
  return(pending);        /* This is the current pending event */
2428
 
}
2429
 
 
2430
 
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
2431
 
/*
2432
 
  Instantiate the versions we need, we have -fno-implicit-template as
2433
 
  compiling option.
2434
 
*/
2435
 
template Rows_log_event*
2436
 
THD::binlog_prepare_pending_rows_event(Table*, uint32_t, size_t, bool,
2437
 
                                       Write_rows_log_event*);
2438
 
 
2439
 
template Rows_log_event*
2440
 
THD::binlog_prepare_pending_rows_event(Table*, uint32_t, size_t, bool,
2441
 
                                       Delete_rows_log_event *);
2442
 
 
2443
 
template Rows_log_event* 
2444
 
THD::binlog_prepare_pending_rows_event(Table*, uint32_t, size_t, bool,
2445
 
                                       Update_rows_log_event *);
2446
 
#endif
2447
 
 
2448
2394
namespace {
2449
2395
  /**
2450
2396
     Class to handle temporary allocation of memory for row data.
2546
2492
      }
2547
2493
      else
2548
2494
      {
2549
 
        m_memory= (unsigned char *) my_malloc(total_length, MYF(MY_WME));
 
2495
        m_memory= (unsigned char *) malloc(total_length);
2550
2496
        m_release_memory_on_destruction= true;
2551
2497
      }
2552
2498
    }
2558
2504
  };
2559
2505
}
2560
2506
 
2561
 
 
2562
 
int THD::binlog_write_row(Table* table, bool is_trans, 
2563
 
                          unsigned char const *record) 
2564
 
2565
 
  assert(current_stmt_binlog_row_based && mysql_bin_log.is_open());
2566
 
 
2567
 
  /*
2568
 
    Pack records into format for transfer. We are allocating more
2569
 
    memory than needed, but that doesn't matter.
2570
 
  */
2571
 
  Row_data_memory memory(table, table->max_row_length(record));
2572
 
  if (!memory.has_memory())
2573
 
    return HA_ERR_OUT_OF_MEM;
2574
 
 
2575
 
  unsigned char *row_data= memory.slot(0);
2576
 
 
2577
 
  size_t const len= pack_row(table, table->write_set, row_data, record);
2578
 
 
2579
 
  Rows_log_event* const ev=
2580
 
    binlog_prepare_pending_rows_event(table, server_id, len, is_trans,
2581
 
                                      static_cast<Write_rows_log_event*>(0));
2582
 
 
2583
 
  if (unlikely(ev == 0))
2584
 
    return HA_ERR_OUT_OF_MEM;
2585
 
 
2586
 
  return ev->add_row_data(row_data, len);
2587
 
}
2588
 
 
2589
 
int THD::binlog_update_row(Table* table, bool is_trans,
2590
 
                           const unsigned char *before_record,
2591
 
                           const unsigned char *after_record)
2592
 
2593
 
  assert(current_stmt_binlog_row_based && mysql_bin_log.is_open());
2594
 
 
2595
 
  size_t const before_maxlen = table->max_row_length(before_record);
2596
 
  size_t const after_maxlen  = table->max_row_length(after_record);
2597
 
 
2598
 
  Row_data_memory row_data(table, before_maxlen, after_maxlen);
2599
 
  if (!row_data.has_memory())
2600
 
    return HA_ERR_OUT_OF_MEM;
2601
 
 
2602
 
  unsigned char *before_row= row_data.slot(0);
2603
 
  unsigned char *after_row= row_data.slot(1);
2604
 
 
2605
 
  size_t const before_size= pack_row(table, table->read_set, before_row,
2606
 
                                        before_record);
2607
 
  size_t const after_size= pack_row(table, table->write_set, after_row,
2608
 
                                       after_record);
2609
 
 
2610
 
  Rows_log_event* const ev=
2611
 
    binlog_prepare_pending_rows_event(table, server_id,
2612
 
                                      before_size + after_size, is_trans,
2613
 
                                      static_cast<Update_rows_log_event*>(0));
2614
 
 
2615
 
  if (unlikely(ev == 0))
2616
 
    return HA_ERR_OUT_OF_MEM;
2617
 
 
2618
 
  return
2619
 
    ev->add_row_data(before_row, before_size) ||
2620
 
    ev->add_row_data(after_row, after_size);
2621
 
}
2622
 
 
2623
 
int THD::binlog_delete_row(Table* table, bool is_trans, 
2624
 
                           unsigned char const *record)
2625
 
2626
 
  assert(current_stmt_binlog_row_based && mysql_bin_log.is_open());
2627
 
 
2628
 
  /* 
2629
 
     Pack records into format for transfer. We are allocating more
2630
 
     memory than needed, but that doesn't matter.
2631
 
  */
2632
 
  Row_data_memory memory(table, table->max_row_length(record));
2633
 
  if (unlikely(!memory.has_memory()))
2634
 
    return HA_ERR_OUT_OF_MEM;
2635
 
 
2636
 
  unsigned char *row_data= memory.slot(0);
2637
 
 
2638
 
  size_t const len= pack_row(table, table->read_set, row_data, record);
2639
 
 
2640
 
  Rows_log_event* const ev=
2641
 
    binlog_prepare_pending_rows_event(table, server_id, len, is_trans,
2642
 
                                      static_cast<Delete_rows_log_event*>(0));
2643
 
 
2644
 
  if (unlikely(ev == 0))
2645
 
    return HA_ERR_OUT_OF_MEM;
2646
 
 
2647
 
  return ev->add_row_data(row_data, len);
2648
 
}
2649
 
 
2650
 
 
2651
 
int THD::binlog_flush_pending_rows_event(bool stmt_end)
2652
 
{
2653
 
  /*
2654
 
    We shall flush the pending event even if we are not in row-based
2655
 
    mode: it might be the case that we left row-based mode before
2656
 
    flushing anything (e.g., if we have explicitly locked tables).
2657
 
   */
2658
 
  if (!mysql_bin_log.is_open())
2659
 
    return(0);
2660
 
 
2661
 
  /*
2662
 
    Mark the event as the last event of a statement if the stmt_end
2663
 
    flag is set.
2664
 
  */
2665
 
  int error= 0;
2666
 
  if (Rows_log_event *pending= binlog_get_pending_rows_event())
2667
 
  {
2668
 
    if (stmt_end)
2669
 
    {
2670
 
      pending->set_flags(Rows_log_event::STMT_END_F);
2671
 
      pending->flags|= LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F;
2672
 
      binlog_table_maps= 0;
2673
 
    }
2674
 
 
2675
 
    error= mysql_bin_log.flush_and_set_pending_rows_event(this, 0);
2676
 
  }
2677
 
 
2678
 
  return(error);
2679
 
}
2680
 
 
2681
 
 
2682
 
/*
2683
 
  Member function that will log query, either row-based or
2684
 
  statement-based depending on the value of the 'current_stmt_binlog_row_based'
2685
 
  the value of the 'qtype' flag.
2686
 
 
2687
 
  This function should be called after the all calls to ha_*_row()
2688
 
  functions have been issued, but before tables are unlocked and
2689
 
  closed.
2690
 
 
2691
 
  OBSERVE
2692
 
    There shall be no writes to any system table after calling
2693
 
    binlog_query(), so these writes has to be moved to before the call
2694
 
    of binlog_query() for correct functioning.
2695
 
 
2696
 
    This is necessesary not only for RBR, but the master might crash
2697
 
    after binlogging the query but before changing the system tables.
2698
 
    This means that the slave and the master are not in the same state
2699
 
    (after the master has restarted), so therefore we have to
2700
 
    eliminate this problem.
2701
 
 
2702
 
  RETURN VALUE
2703
 
    Error code, or 0 if no error.
2704
 
*/
2705
 
int THD::binlog_query(THD::enum_binlog_query_type qtype, char const *query_arg,
2706
 
                      ulong query_len, bool is_trans, bool suppress_use,
2707
 
                      THD::killed_state killed_status_arg)
2708
 
{
2709
 
  assert(query_arg && mysql_bin_log.is_open());
2710
 
 
2711
 
  if (int error= binlog_flush_pending_rows_event(true))
2712
 
    return(error);
2713
 
 
2714
 
  /*
2715
 
    If we are in statement mode and trying to log an unsafe statement,
2716
 
    we should print a warning.
2717
 
  */
2718
 
  if (lex->is_stmt_unsafe() &&
2719
 
      variables.binlog_format == BINLOG_FORMAT_STMT)
2720
 
  {
2721
 
    assert(this->query != NULL);
2722
 
    push_warning(this, DRIZZLE_ERROR::WARN_LEVEL_WARN,
2723
 
                 ER_BINLOG_UNSAFE_STATEMENT,
2724
 
                 ER(ER_BINLOG_UNSAFE_STATEMENT));
2725
 
    if (!(binlog_flags & BINLOG_FLAG_UNSAFE_STMT_PRINTED))
2726
 
    {
2727
 
      char warn_buf[DRIZZLE_ERRMSG_SIZE];
2728
 
      snprintf(warn_buf, DRIZZLE_ERRMSG_SIZE, "%s Statement: %s",
2729
 
               ER(ER_BINLOG_UNSAFE_STATEMENT), this->query);
2730
 
      sql_print_warning(warn_buf);
2731
 
      binlog_flags|= BINLOG_FLAG_UNSAFE_STMT_PRINTED;
2732
 
    }
2733
 
  }
2734
 
 
2735
 
  switch (qtype) {
2736
 
  case THD::ROW_QUERY_TYPE:
2737
 
    if (current_stmt_binlog_row_based)
2738
 
      return(0);
2739
 
    /* Otherwise, we fall through */
2740
 
  case THD::DRIZZLE_QUERY_TYPE:
2741
 
    /*
2742
 
      Using this query type is a conveniece hack, since we have been
2743
 
      moving back and forth between using RBR for replication of
2744
 
      system tables and not using it.
2745
 
 
2746
 
      Make sure to change in check_table_binlog_row_based() according
2747
 
      to how you treat this.
2748
 
    */
2749
 
  case THD::STMT_QUERY_TYPE:
2750
 
    /*
2751
 
      The DRIZZLE_LOG::write() function will set the STMT_END_F flag and
2752
 
      flush the pending rows event if necessary.
2753
 
     */
2754
 
    {
2755
 
      Query_log_event qinfo(this, query_arg, query_len, is_trans, suppress_use,
2756
 
                            killed_status_arg);
2757
 
      qinfo.flags|= LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F;
2758
 
      /*
2759
 
        Binlog table maps will be irrelevant after a Query_log_event
2760
 
        (they are just removed on the slave side) so after the query
2761
 
        log event is written to the binary log, we pretend that no
2762
 
        table maps were written.
2763
 
       */
2764
 
      int error= mysql_bin_log.write(&qinfo);
2765
 
      binlog_table_maps= 0;
2766
 
      return(error);
2767
 
    }
2768
 
    break;
2769
 
 
2770
 
  case THD::QUERY_TYPE_COUNT:
2771
 
  default:
2772
 
    assert(0 <= qtype && qtype < QUERY_TYPE_COUNT);
2773
 
  }
2774
 
  return(0);
2775
 
}
2776
 
 
2777
2507
bool Discrete_intervals_list::append(uint64_t start, uint64_t val,
2778
2508
                                 uint64_t incr)
2779
2509
{
2799
2529
  elements++;
2800
2530
  return(0);
2801
2531
}
 
2532
 
 
2533
/**
 
2534
  Close a connection.
 
2535
 
 
2536
  @param session                Thread handle
 
2537
  @param errcode        Error code to print to console
 
2538
  @param lock           1 if we have have to lock LOCK_thread_count
 
2539
 
 
2540
  @note
 
2541
    For the connection that is doing shutdown, this is called twice
 
2542
*/
 
2543
void Session::close_connection(uint32_t errcode, bool lock)
 
2544
{
 
2545
  st_vio *vio;
 
2546
  if (lock)
 
2547
    (void) pthread_mutex_lock(&LOCK_thread_count);
 
2548
  killed= Session::KILL_CONNECTION;
 
2549
  if ((vio= net.vio) != 0)
 
2550
  {
 
2551
    if (errcode)
 
2552
      net_send_error(this, errcode, ER(errcode)); /* purecov: inspected */
 
2553
    net_close(&net);            /* vio is freed in delete session */
 
2554
  }
 
2555
  if (lock)
 
2556
    (void) pthread_mutex_unlock(&LOCK_thread_count);
 
2557
}