~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/session.cc

  • Committer: Padraig O'Sullivan
  • Date: 2009-09-13 01:03:01 UTC
  • mto: (1126.9.2 captain-20090915-01)
  • mto: This revision was merged to the branch mainline in revision 1133.
  • Revision ID: osullivan.padraig@gmail.com-20090913010301-tcvvezipx1124acy
Added calls to the dtrace delete begin/end probes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
 * @file Implementation of the Session class and API
22
22
 */
23
23
 
24
 
#include "config.h"
 
24
#include <drizzled/server_includes.h>
25
25
#include <drizzled/session.h>
26
 
#include "drizzled/session_list.h"
27
26
#include <sys/stat.h>
 
27
#include <mysys/mysys_err.h>
28
28
#include <drizzled/error.h>
29
29
#include <drizzled/gettext.h>
30
30
#include <drizzled/query_id.h>
36
36
#include <drizzled/item/return_int.h>
37
37
#include <drizzled/item/empty_string.h>
38
38
#include <drizzled/show.h>
39
 
#include <drizzled/plugin/client.h>
40
 
#include "drizzled/plugin/scheduler.h"
41
 
#include "drizzled/plugin/authentication.h"
42
 
#include "drizzled/plugin/logging.h"
43
 
#include "drizzled/plugin/transactional_storage_engine.h"
44
 
#include "drizzled/probes.h"
45
 
#include "drizzled/table_proto.h"
46
 
#include "drizzled/db.h"
47
 
#include "drizzled/pthread_globals.h"
48
 
#include "drizzled/transaction_services.h"
49
 
 
50
 
#include "plugin/myisam/myisam.h"
51
 
#include "drizzled/internal/iocache.h"
52
 
 
53
 
#include <fcntl.h>
 
39
#include <drizzled/scheduling.h>
 
40
 
54
41
#include <algorithm>
55
 
#include <climits>
56
42
 
57
43
using namespace std;
58
 
namespace drizzled
59
 
{
 
44
using namespace drizzled;
60
45
 
61
46
extern "C"
62
47
{
75
60
extern pthread_key_t THR_Session;
76
61
extern pthread_key_t THR_Mem_root;
77
62
extern uint32_t max_used_connections;
78
 
extern atomic<uint32_t> connection_count;
 
63
extern drizzled::atomic<uint32_t> connection_count;
79
64
 
 
65
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
 
66
/* Used templates */
 
67
template class List<Key>;
 
68
template class List_iterator<Key>;
 
69
template class List<Key_part_spec>;
 
70
template class List_iterator<Key_part_spec>;
 
71
template class List<Alter_drop>;
 
72
template class List_iterator<Alter_drop>;
 
73
template class List<Alter_column>;
 
74
template class List_iterator<Alter_column>;
 
75
#endif
80
76
 
81
77
/****************************************************************************
82
78
** User variables
99
95
         !strcmp(field_name.str, other.field_name.str);
100
96
}
101
97
 
102
 
Open_tables_state::Open_tables_state(uint64_t version_arg)
 
98
Open_tables_state::Open_tables_state(ulong version_arg)
103
99
  :version(version_arg), backups_available(false)
104
100
{
105
101
  reset_open_tables_state();
111
107
extern "C" int mysql_tmpfile(const char *prefix)
112
108
{
113
109
  char filename[FN_REFLEN];
114
 
  int fd = internal::create_temp_file(filename, drizzle_tmpdir, prefix, MYF(MY_WME));
 
110
  File fd = create_temp_file(filename, drizzle_tmpdir, prefix, MYF(MY_WME));
115
111
  if (fd >= 0) {
116
112
    unlink(filename);
117
113
  }
145
141
  return session->get_proc_info();
146
142
}
147
143
 
148
 
void **Session::getEngineData(const plugin::MonitoredInTransaction *monitored)
149
 
{
150
 
  return static_cast<void **>(&ha_data[monitored->getId()].ha_ptr);
151
 
}
152
 
 
153
 
ResourceContext *Session::getResourceContext(const plugin::MonitoredInTransaction *monitored,
154
 
                                             size_t index)
155
 
{
156
 
  return &ha_data[monitored->getId()].resource_context[index];
 
144
extern "C"
 
145
void **session_ha_data(const Session *session, const struct StorageEngine *engine)
 
146
{
 
147
  return (void **) &session->ha_data[engine->slot].ha_ptr;
157
148
}
158
149
 
159
150
extern "C"
174
165
  return (int) session->variables.tx_isolation;
175
166
}
176
167
 
177
 
Session::Session(plugin::Client *client_arg)
 
168
extern "C"
 
169
void session_inc_row_count(Session *session)
 
170
{
 
171
  session->row_count++;
 
172
}
 
173
 
 
174
Session::Session(plugin::Protocol *protocol_arg)
178
175
  :
179
176
  Open_tables_state(refresh_version),
180
177
  mem_root(&main_mem_root),
181
178
  lex(&main_lex),
182
 
  query(),
183
 
  client(client_arg),
 
179
  db(NULL),
184
180
  scheduler(NULL),
185
181
  scheduler_arg(NULL),
186
182
  lock_id(&main_lock_id),
187
183
  user_time(0),
188
 
  ha_data(plugin::num_trx_monitored_objects),
189
184
  arg_of_last_insert_id_function(false),
190
185
  first_successful_insert_id_in_prev_stmt(0),
191
186
  first_successful_insert_id_in_cur_stmt(0),
200
195
  derived_tables_processing(false),
201
196
  tablespace_op(false),
202
197
  m_lip(NULL),
203
 
  cached_table(0),
204
 
  transaction_message(NULL),
205
 
  statement_message(NULL)
 
198
  cached_table(0)
206
199
{
207
200
  memset(process_list_info, 0, PROCESS_LIST_WIDTH);
208
 
  client->setSession(this);
209
201
 
210
202
  /*
211
203
    Pass nominal parameters to init_alloc_root only to ensure that
212
204
    the destructor works OK in case of an error. The main_mem_root
213
205
    will be re-initialized in init_for_queries().
214
206
  */
215
 
  memory::init_sql_alloc(&main_mem_root, memory::ROOT_MIN_BLOCK_SIZE, 0);
 
207
  init_sql_alloc(&main_mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
216
208
  thread_stack= NULL;
217
209
  count_cuted_fields= CHECK_FIELD_IGNORE;
218
210
  killed= NOT_KILLED;
231
223
  thread_id= 0;
232
224
  file_id = 0;
233
225
  query_id= 0;
234
 
  warn_query_id= 0;
 
226
  warn_id= 0;
 
227
  memset(ha_data, 0, sizeof(ha_data));
 
228
  replication_data= 0;
235
229
  mysys_var= 0;
236
230
  dbug_sentry=Session_SENTRY_MAGIC;
237
231
  cleanup_done= abort_on_warning= no_warnings_for_error= false;
 
232
  peer_port= 0;                                 // For SHOW PROCESSLIST
 
233
  transaction.on= 1;
238
234
  pthread_mutex_init(&LOCK_delete, MY_MUTEX_INIT_FAST);
239
235
 
240
236
  /* Variables with default values */
257
253
  else
258
254
    options &= ~OPTION_BIG_SELECTS;
259
255
 
 
256
  transaction.all.modified_non_trans_table= transaction.stmt.modified_non_trans_table= false;
260
257
  open_options=ha_open_options;
261
258
  update_lock_default= TL_WRITE;
262
259
  session_tx_isolation= (enum_tx_isolation) variables.tx_isolation;
266
263
  memset(&status_var, 0, sizeof(status_var));
267
264
 
268
265
  /* Initialize sub structures */
269
 
  memory::init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
 
266
  init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
270
267
  hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
271
268
            (hash_get_key) get_var_key,
272
269
            (hash_free_key) free_user_var, 0);
273
270
 
 
271
  protocol= protocol_arg;
 
272
  protocol->setSession(this);
 
273
 
274
274
  substitute_null_with_insert_id = false;
275
275
  thr_lock_info_init(&lock_info); /* safety: will be reset after start */
276
276
  thr_lock_owner_init(&main_lock_id, &lock_info);
281
281
void Session::free_items()
282
282
{
283
283
  Item *next;
284
 
  /* This works because items are allocated with memory::sql_alloc() */
 
284
  /* This works because items are allocated with sql_alloc() */
285
285
  for (; free_list; free_list= next)
286
286
  {
287
287
    next= free_list->next;
368
368
  }
369
369
#endif
370
370
  {
371
 
    TransactionServices &transaction_services= TransactionServices::singleton();
372
 
    transaction_services.ha_rollback_trans(this, true);
 
371
    ha_rollback(this);
373
372
    xid_cache_delete(&transaction.xid_state);
374
373
  }
375
374
  hash_free(&user_vars);
383
382
 
384
383
Session::~Session()
385
384
{
386
 
  this->checkSentry();
 
385
  Session_CHECK_SENTRY(this);
387
386
  add_to_status(&global_status_var, &status_var);
388
387
 
389
 
  if (client->isConnected())
 
388
  if (protocol->isConnected())
390
389
  {
391
390
    if (global_system_variables.log_warnings)
392
 
        errmsg_printf(ERRMSG_LVL_WARN, ER(ER_FORCING_CLOSE),internal::my_progname,
 
391
        errmsg_printf(ERRMSG_LVL_WARN, ER(ER_FORCING_CLOSE),my_progname,
393
392
                      thread_id,
394
 
                      (getSecurityContext().getUser().c_str() ?
395
 
                       getSecurityContext().getUser().c_str() : ""));
 
393
                      (security_ctx.user.c_str() ?
 
394
                       security_ctx.user.c_str() : ""));
396
395
    disconnect(0, false);
397
396
  }
398
397
 
399
398
  /* Close connection */
400
 
  client->close();
401
 
  delete client;
 
399
  protocol->close();
 
400
  delete protocol;
402
401
 
403
402
  if (cleanup_done == false)
404
403
    cleanup();
405
404
 
406
 
  plugin::StorageEngine::closeConnection(this);
 
405
  ha_close_connection(this);
407
406
  plugin_sessionvar_cleanup(this);
408
407
 
 
408
  if (db)
 
409
  {
 
410
    free(db);
 
411
    db= NULL;
 
412
  }
409
413
  free_root(&warn_root,MYF(0));
 
414
  free_root(&transaction.mem_root,MYF(0));
410
415
  mysys_var=0;                                  // Safety (shouldn't be needed)
411
416
  dbug_sentry= Session_SENTRY_GONE;
412
417
 
413
418
  free_root(&main_mem_root, MYF(0));
414
419
  pthread_setspecific(THR_Session,  0);
415
420
 
416
 
  plugin::Logging::postEndDo(this);
417
421
 
418
422
  /* Ensure that no one is using Session */
419
423
  pthread_mutex_unlock(&LOCK_delete);
433
437
    If this assumption will change, then we have to explictely add
434
438
    the other variables after the while loop
435
439
*/
436
 
void add_to_status(system_status_var *to_var, system_status_var *from_var)
 
440
void add_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var)
437
441
{
438
442
  ulong *end= (ulong*) ((unsigned char*) to_var +
439
 
                        offsetof(system_status_var, last_system_status_var) +
 
443
                        offsetof(STATUS_VAR, last_system_status_var) +
440
444
                        sizeof(ulong));
441
445
  ulong *to= (ulong*) to_var, *from= (ulong*) from_var;
442
446
 
456
460
  NOTE
457
461
    This function assumes that all variables are long/ulong.
458
462
*/
459
 
void add_diff_to_status(system_status_var *to_var, system_status_var *from_var,
460
 
                        system_status_var *dec_var)
 
463
void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var,
 
464
                        STATUS_VAR *dec_var)
461
465
{
462
 
  ulong *end= (ulong*) ((unsigned char*) to_var + offsetof(system_status_var,
 
466
  ulong *end= (ulong*) ((unsigned char*) to_var + offsetof(STATUS_VAR,
463
467
                                                  last_system_status_var) +
464
468
                        sizeof(ulong));
465
469
  ulong *to= (ulong*) to_var, *from= (ulong*) from_var, *dec= (ulong*) dec_var;
470
474
 
471
475
void Session::awake(Session::killed_state state_to_set)
472
476
{
473
 
  this->checkSentry();
 
477
  Session_CHECK_SENTRY(this);
474
478
  safe_mutex_assert_owner(&LOCK_delete);
475
479
 
476
480
  killed= state_to_set;
477
481
  if (state_to_set != Session::KILL_QUERY)
478
482
  {
479
483
    scheduler->killSession(this);
480
 
    DRIZZLE_CONNECTION_DONE(thread_id);
 
484
    DRIZZLE_CONNECTION_DONE(session->thread_id);
481
485
  }
482
486
  if (mysys_var)
483
487
  {
513
517
 
514
518
/*
515
519
  Remember the location of thread info, the structure needed for
516
 
  memory::sql_alloc() and the structure for the net buffer
 
520
  sql_alloc() and the structure for the net buffer
517
521
*/
518
522
bool Session::storeGlobals()
519
523
{
559
563
  set_proc_info(NULL);
560
564
  command= COM_SLEEP;
561
565
  set_time();
 
566
  ha_enable_transaction(this,true);
562
567
 
563
568
  reset_root_defaults(mem_root, variables.query_alloc_block_size,
564
569
                      variables.query_prealloc_size);
 
570
  reset_root_defaults(&transaction.mem_root,
 
571
                      variables.trans_alloc_block_size,
 
572
                      variables.trans_prealloc_size);
565
573
  transaction.xid_state.xid.null();
566
574
  transaction.xid_state.in_session=1;
567
575
}
587
595
 
588
596
  prepareForQueries();
589
597
 
590
 
  while (! client->haveError() && killed != KILL_CONNECTION)
 
598
  while (! protocol->haveError() && killed != KILL_CONNECTION)
591
599
  {
592
600
    if (! executeStatement())
593
601
      break;
598
606
 
599
607
bool Session::schedule()
600
608
{
601
 
  scheduler= plugin::Scheduler::getScheduler();
602
 
  assert(scheduler);
 
609
  scheduler= get_thread_scheduler();
603
610
 
604
 
  connection_count.increment();
 
611
  ++connection_count;
605
612
 
606
613
  if (connection_count > max_used_connections)
607
614
    max_used_connections= connection_count;
609
616
  thread_id= variables.pseudo_thread_id= global_thread_id++;
610
617
 
611
618
  pthread_mutex_lock(&LOCK_thread_count);
612
 
  getSessionList().push_back(this);
 
619
  session_list.push_back(this);
613
620
  pthread_mutex_unlock(&LOCK_thread_count);
614
621
 
615
622
  if (scheduler->addSession(this))
616
623
  {
617
 
    DRIZZLE_CONNECTION_START(thread_id);
 
624
    DRIZZLE_CONNECTION_START(session->thread_id);
618
625
    char error_message_buff[DRIZZLE_ERRMSG_SIZE];
619
626
 
620
627
    killed= Session::KILL_CONNECTION;
625
632
    /* TODO replace will better error message */
626
633
    snprintf(error_message_buff, sizeof(error_message_buff),
627
634
             ER(ER_CANT_CREATE_THREAD), 1);
628
 
    client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
 
635
    protocol->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
629
636
    return true;
630
637
  }
631
638
 
632
639
  return false;
633
640
}
634
641
 
635
 
 
636
 
const char* Session::enter_cond(pthread_cond_t *cond,
637
 
                                pthread_mutex_t* mutex,
638
 
                                const char* msg)
639
 
{
640
 
  const char* old_msg = get_proc_info();
641
 
  safe_mutex_assert_owner(mutex);
642
 
  mysys_var->current_mutex = mutex;
643
 
  mysys_var->current_cond = cond;
644
 
  this->set_proc_info(msg);
645
 
  return old_msg;
646
 
}
647
 
 
648
 
void Session::exit_cond(const char* old_msg)
649
 
{
650
 
  /*
651
 
    Putting the mutex unlock in exit_cond() ensures that
652
 
    mysys_var->current_mutex is always unlocked _before_ mysys_var->mutex is
653
 
    locked (if that would not be the case, you'll get a deadlock if someone
654
 
    does a Session::awake() on you).
655
 
  */
656
 
  pthread_mutex_unlock(mysys_var->current_mutex);
657
 
  pthread_mutex_lock(&mysys_var->mutex);
658
 
  mysys_var->current_mutex = 0;
659
 
  mysys_var->current_cond = 0;
660
 
  this->set_proc_info(old_msg);
661
 
  pthread_mutex_unlock(&mysys_var->mutex);
662
 
}
663
 
 
664
642
bool Session::authenticate()
665
643
{
666
644
  lex_start(this);
667
 
  if (client->authenticate())
 
645
  if (protocol->authenticate())
668
646
    return false;
669
647
 
670
648
  statistic_increment(aborted_connects, &LOCK_status);
673
651
 
674
652
bool Session::checkUser(const char *passwd, uint32_t passwd_len, const char *in_db)
675
653
{
676
 
  const string passwd_str(passwd, passwd_len);
677
 
  bool is_authenticated=
678
 
    plugin::Authentication::isAuthenticated(getSecurityContext(),
679
 
                                            passwd_str);
 
654
  LEX_STRING db_str= { (char *) in_db, in_db ? strlen(in_db) : 0 };
 
655
  bool is_authenticated;
 
656
 
 
657
  /*
 
658
    Clear session->db as it points to something, that will be freed when
 
659
    connection is closed. We don't want to accidentally free a wrong
 
660
    pointer if connect failed. Also in case of 'CHANGE USER' failure,
 
661
    current database will be switched to 'no database selected'.
 
662
  */
 
663
  reset_db(NULL, 0);
 
664
 
 
665
  if (passwd_len != 0 && passwd_len != SCRAMBLE_LENGTH)
 
666
  {
 
667
    my_error(ER_HANDSHAKE_ERROR, MYF(0), security_ctx.ip.c_str());
 
668
    return false;
 
669
  }
 
670
 
 
671
  is_authenticated= authenticate_user(this, passwd);
680
672
 
681
673
  if (is_authenticated != true)
682
674
  {
683
 
    /* isAuthenticated has pushed the error message */
 
675
    my_error(ER_ACCESS_DENIED_ERROR, MYF(0),
 
676
             security_ctx.user.c_str(),
 
677
             security_ctx.ip.c_str(),
 
678
             passwd_len ? ER(ER_YES) : ER(ER_NO));
 
679
 
684
680
    return false;
685
681
  }
686
682
 
 
683
  security_ctx.skip_grants();
 
684
 
687
685
  /* Change database if necessary */
688
686
  if (in_db && in_db[0])
689
687
  {
690
 
    SchemaIdentifier identifier(in_db);
691
 
    if (mysql_change_db(this, identifier))
 
688
    if (mysql_change_db(this, &db_str, false))
692
689
    {
693
690
      /* mysql_change_db() has pushed the error message. */
694
691
      return false;
713
710
    (see my_message_sql)
714
711
  */
715
712
  lex->current_select= 0;
716
 
  clear_error();
717
 
  main_da.reset_diagnostics_area();
718
713
 
719
 
  if (client->readCommand(&l_packet, &packet_length) == false)
 
714
  if (protocol->readCommand(&l_packet, &packet_length) == false)
720
715
    return false;
721
716
 
722
717
  if (packet_length == 0)
747
742
    in_packet_length--;
748
743
  }
749
744
 
750
 
  query.assign(in_packet, in_packet + in_packet_length);
 
745
  /* We must allocate some extra memory for the cached query string */
 
746
  query_length= 0; /* Extra safety: Avoid races */
 
747
  query= (char*) memdup_w_gap((unsigned char*) in_packet, in_packet_length, db_length + 1);
 
748
  if (! query)
 
749
    return false;
 
750
 
 
751
  query[in_packet_length]=0;
 
752
  query_length= in_packet_length;
 
753
 
 
754
  /* Reclaim some memory */
 
755
  packet.shrink(variables.net_buffer_length);
 
756
  convert_buffer.shrink(variables.net_buffer_length);
751
757
 
752
758
  return true;
753
759
}
756
762
{
757
763
  bool do_release= 0;
758
764
  bool result= true;
759
 
  TransactionServices &transaction_services= TransactionServices::singleton();
760
765
 
761
766
  if (transaction.xid_state.xa_state != XA_NOTR)
762
767
  {
772
777
       * (Which of course should never happen...)
773
778
       */
774
779
      server_status&= ~SERVER_STATUS_IN_TRANS;
775
 
      if (transaction_services.ha_commit_trans(this, true))
 
780
      if (ha_commit(this))
776
781
        result= false;
777
 
      options&= ~(OPTION_BEGIN);
 
782
      options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
 
783
      transaction.all.modified_non_trans_table= false;
778
784
      break;
779
785
    case COMMIT_RELEASE:
780
786
      do_release= 1; /* fall through */
789
795
    case ROLLBACK_AND_CHAIN:
790
796
    {
791
797
      server_status&= ~SERVER_STATUS_IN_TRANS;
792
 
      if (transaction_services.ha_rollback_trans(this, true))
 
798
      if (ha_rollback(this))
793
799
        result= false;
794
 
      options&= ~(OPTION_BEGIN);
 
800
      options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
 
801
      transaction.all.modified_non_trans_table= false;
795
802
      if (result == true && (completion == ROLLBACK_AND_CHAIN))
796
803
        result= startTransaction();
797
804
      break;
812
819
bool Session::endActiveTransaction()
813
820
{
814
821
  bool result= true;
815
 
  TransactionServices &transaction_services= TransactionServices::singleton();
816
822
 
817
823
  if (transaction.xid_state.xa_state != XA_NOTR)
818
824
  {
822
828
  if (options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
823
829
  {
824
830
    server_status&= ~SERVER_STATUS_IN_TRANS;
825
 
    if (transaction_services.ha_commit_trans(this, true))
 
831
    if (ha_commit(this))
826
832
      result= false;
827
833
  }
828
 
  options&= ~(OPTION_BEGIN);
 
834
  options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
 
835
  transaction.all.modified_non_trans_table= false;
829
836
  return result;
830
837
}
831
838
 
832
 
bool Session::startTransaction(start_transaction_option_t opt)
 
839
bool Session::startTransaction()
833
840
{
834
841
  bool result= true;
835
842
 
836
843
  if (! endActiveTransaction())
837
 
  {
838
844
    result= false;
839
 
  }
840
845
  else
841
846
  {
842
847
    options|= OPTION_BEGIN;
843
848
    server_status|= SERVER_STATUS_IN_TRANS;
844
 
 
845
 
    if (plugin::TransactionalStorageEngine::notifyStartTransaction(this, opt))
846
 
    {
847
 
      result= false;
848
 
    }
 
849
    if (lex->start_transaction_opt & DRIZZLE_START_TRANS_OPT_WITH_CONS_SNAPSHOT)
 
850
      if (ha_start_consistent_snapshot(this))
 
851
        result= false;
849
852
  }
850
 
 
851
853
  return result;
852
854
}
853
855
 
886
888
  @return  NULL on failure, or pointer to the LEX_STRING object
887
889
*/
888
890
LEX_STRING *Session::make_lex_string(LEX_STRING *lex_str,
889
 
                                     const std::string &str,
890
 
                                     bool allocate_lex_string)
891
 
{
892
 
  return make_lex_string(lex_str, str.c_str(), str.length(), allocate_lex_string);
893
 
}
894
 
 
895
 
LEX_STRING *Session::make_lex_string(LEX_STRING *lex_str,
896
 
                                     const char* str, uint32_t length,
897
 
                                     bool allocate_lex_string)
 
891
                                 const char* str, uint32_t length,
 
892
                                 bool allocate_lex_string)
898
893
{
899
894
  if (allocate_lex_string)
900
895
    if (!(lex_str= (LEX_STRING *)alloc(sizeof(LEX_STRING))))
905
900
  return lex_str;
906
901
}
907
902
 
 
903
/* routings to adding tables to list of changed in transaction tables */
 
904
inline static void list_include(CHANGED_TableList** prev,
 
905
                                CHANGED_TableList* curr,
 
906
                                CHANGED_TableList* new_table)
 
907
{
 
908
  if (new_table)
 
909
  {
 
910
    *prev = new_table;
 
911
    (*prev)->next = curr;
 
912
  }
 
913
}
 
914
 
 
915
/* add table to list of changed in transaction tables */
 
916
 
 
917
void Session::add_changed_table(Table *table)
 
918
{
 
919
  assert((options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) &&
 
920
              table->file->has_transactions());
 
921
  add_changed_table(table->s->table_cache_key.str,
 
922
                    (long) table->s->table_cache_key.length);
 
923
}
 
924
 
 
925
 
 
926
void Session::add_changed_table(const char *key, long key_length)
 
927
{
 
928
  CHANGED_TableList **prev_changed = &transaction.changed_tables;
 
929
  CHANGED_TableList *curr = transaction.changed_tables;
 
930
 
 
931
  for (; curr; prev_changed = &(curr->next), curr = curr->next)
 
932
  {
 
933
    int cmp =  (long)curr->key_length - (long)key_length;
 
934
    if (cmp < 0)
 
935
    {
 
936
      list_include(prev_changed, curr, changed_table_dup(key, key_length));
 
937
      return;
 
938
    }
 
939
    else if (cmp == 0)
 
940
    {
 
941
      cmp = memcmp(curr->key, key, curr->key_length);
 
942
      if (cmp < 0)
 
943
      {
 
944
        list_include(prev_changed, curr, changed_table_dup(key, key_length));
 
945
        return;
 
946
      }
 
947
      else if (cmp == 0)
 
948
      {
 
949
        return;
 
950
      }
 
951
    }
 
952
  }
 
953
  *prev_changed = changed_table_dup(key, key_length);
 
954
}
 
955
 
 
956
 
 
957
CHANGED_TableList* Session::changed_table_dup(const char *key, long key_length)
 
958
{
 
959
  CHANGED_TableList* new_table =
 
960
    (CHANGED_TableList*) trans_alloc(ALIGN_SIZE(sizeof(CHANGED_TableList))+
 
961
                                      key_length + 1);
 
962
  if (!new_table)
 
963
  {
 
964
    my_error(EE_OUTOFMEMORY, MYF(ME_BELL),
 
965
             ALIGN_SIZE(sizeof(TableList)) + key_length + 1);
 
966
    killed= KILL_CONNECTION;
 
967
    return 0;
 
968
  }
 
969
 
 
970
  new_table->key= ((char*)new_table)+ ALIGN_SIZE(sizeof(CHANGED_TableList));
 
971
  new_table->next = 0;
 
972
  new_table->key_length = key_length;
 
973
  ::memcpy(new_table->key, key, key_length);
 
974
  return new_table;
 
975
}
 
976
 
 
977
 
908
978
int Session::send_explain_fields(select_result *result)
909
979
{
910
980
  List<Item> field_list;
943
1013
  return (result->send_fields(field_list));
944
1014
}
945
1015
 
946
 
void select_result::send_error(uint32_t errcode, const char *err)
947
 
{
948
 
  my_message(errcode, err, MYF(0));
949
 
}
950
 
 
951
1016
/************************************************************************
952
1017
  Handling writing to file
953
1018
************************************************************************/
957
1022
  my_message(errcode, err, MYF(0));
958
1023
  if (file > 0)
959
1024
  {
960
 
    (void) end_io_cache(cache);
961
 
    (void) internal::my_close(file, MYF(0));
962
 
    (void) internal::my_delete(path, MYF(0));           // Delete file on error
 
1025
    (void) end_io_cache(&cache);
 
1026
    (void) my_close(file,MYF(0));
 
1027
    (void) my_delete(path,MYF(0));              // Delete file on error
963
1028
    file= -1;
964
1029
  }
965
1030
}
967
1032
 
968
1033
bool select_to_file::send_eof()
969
1034
{
970
 
  int error= test(end_io_cache(cache));
971
 
  if (internal::my_close(file, MYF(MY_WME)))
 
1035
  int error= test(end_io_cache(&cache));
 
1036
  if (my_close(file,MYF(MY_WME)))
972
1037
    error= 1;
973
1038
  if (!error)
974
1039
  {
989
1054
  /* In case of error send_eof() may be not called: close the file here. */
990
1055
  if (file >= 0)
991
1056
  {
992
 
    (void) end_io_cache(cache);
993
 
    (void) internal::my_close(file, MYF(0));
 
1057
    (void) end_io_cache(&cache);
 
1058
    (void) my_close(file,MYF(0));
994
1059
    file= -1;
995
1060
  }
996
1061
  path[0]= '\0';
997
1062
  row_count= 0;
998
1063
}
999
1064
 
1000
 
select_to_file::select_to_file(file_exchange *ex)
1001
 
  : exchange(ex),
1002
 
    file(-1),
1003
 
    cache(static_cast<internal::IO_CACHE *>(memory::sql_calloc(sizeof(internal::IO_CACHE)))),
1004
 
    row_count(0L)
1005
 
{
1006
 
  path[0]=0;
1007
 
}
1008
1065
 
1009
1066
select_to_file::~select_to_file()
1010
1067
{
1011
 
  cleanup();
 
1068
  if (file >= 0)
 
1069
  {                                     // This only happens in case of error
 
1070
    (void) end_io_cache(&cache);
 
1071
    (void) my_close(file,MYF(0));
 
1072
    file= -1;
 
1073
  }
1012
1074
}
1013
1075
 
1014
1076
/***************************************************************************
1037
1099
*/
1038
1100
 
1039
1101
 
1040
 
static int create_file(Session *session, char *path, file_exchange *exchange, internal::IO_CACHE *cache)
 
1102
static File create_file(Session *session, char *path, file_exchange *exchange, IO_CACHE *cache)
1041
1103
{
1042
 
  int file;
 
1104
  File file;
1043
1105
  uint32_t option= MY_UNPACK_FILENAME | MY_RELATIVE_PATH;
1044
1106
 
1045
1107
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
1046
1108
  option|= MY_REPLACE_DIR;                      // Force use of db directory
1047
1109
#endif
1048
1110
 
1049
 
  if (!internal::dirname_length(exchange->file_name))
 
1111
  if (!dirname_length(exchange->file_name))
1050
1112
  {
1051
1113
    strcpy(path, drizzle_real_data_home);
1052
 
    if (! session->db.empty())
1053
 
      strncat(path, session->db.c_str(), FN_REFLEN-strlen(drizzle_real_data_home)-1);
1054
 
    (void) internal::fn_format(path, exchange->file_name, path, "", option);
 
1114
    if (session->db)
 
1115
      strncat(path, session->db, FN_REFLEN-strlen(drizzle_real_data_home)-1);
 
1116
    (void) fn_format(path, exchange->file_name, path, "", option);
1055
1117
  }
1056
1118
  else
1057
 
    (void) internal::fn_format(path, exchange->file_name, drizzle_real_data_home, "", option);
 
1119
    (void) fn_format(path, exchange->file_name, drizzle_real_data_home, "", option);
1058
1120
 
1059
1121
  if (opt_secure_file_priv &&
1060
1122
      strncmp(opt_secure_file_priv, path, strlen(opt_secure_file_priv)))
1070
1132
    return -1;
1071
1133
  }
1072
1134
  /* Create the file world readable */
1073
 
  if ((file= internal::my_create(path, 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
 
1135
  if ((file= my_create(path, 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
1074
1136
    return file;
 
1137
#ifdef HAVE_FCHMOD
1075
1138
  (void) fchmod(file, 0666);                    // Because of umask()
1076
 
  if (init_io_cache(cache, file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
 
1139
#else
 
1140
  (void) chmod(path, 0666);
 
1141
#endif
 
1142
  if (init_io_cache(cache, file, 0L, WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1077
1143
  {
1078
 
    internal::my_close(file, MYF(0));
1079
 
    internal::my_delete(path, MYF(0));  // Delete file on error, it was just created
 
1144
    my_close(file, MYF(0));
 
1145
    my_delete(path, MYF(0));  // Delete file on error, it was just created
1080
1146
    return -1;
1081
1147
  }
1082
1148
  return file;
1137
1203
    return 1;
1138
1204
  }
1139
1205
 
1140
 
  if ((file= create_file(session, path, exchange, cache)) < 0)
 
1206
  if ((file= create_file(session, path, exchange, &cache)) < 0)
1141
1207
    return 1;
1142
1208
 
1143
1209
  return 0;
1144
1210
}
1145
1211
 
 
1212
 
 
1213
#define NEED_ESCAPING(x) ((int) (unsigned char) (x) == escape_char    || \
 
1214
                          (enclosed ? (int) (unsigned char) (x) == field_sep_char      \
 
1215
                                    : (int) (unsigned char) (x) == field_term_char) || \
 
1216
                          (int) (unsigned char) (x) == line_sep_char  || \
 
1217
                          !(x))
 
1218
 
1146
1219
bool select_export::send_data(List<Item> &items)
1147
1220
{
1148
1221
  char buff[MAX_FIELD_WIDTH],null_buff[2],space[MAX_FIELD_WIDTH];
1160
1233
  uint32_t used_length=0,items_left=items.elements;
1161
1234
  List_iterator_fast<Item> li(items);
1162
1235
 
1163
 
  if (my_b_write(cache,(unsigned char*) exchange->line_start->ptr(),
1164
 
                 exchange->line_start->length()))
 
1236
  if (my_b_write(&cache,(unsigned char*) exchange->line_start->ptr(),
 
1237
                 exchange->line_start->length()))
1165
1238
    goto err;
1166
1239
  while ((item=li++))
1167
1240
  {
1171
1244
    res=item->str_result(&tmp);
1172
1245
    if (res && enclosed)
1173
1246
    {
1174
 
      if (my_b_write(cache,(unsigned char*) exchange->enclosed->ptr(),
1175
 
                     exchange->enclosed->length()))
1176
 
        goto err;
 
1247
      if (my_b_write(&cache,(unsigned char*) exchange->enclosed->ptr(),
 
1248
                     exchange->enclosed->length()))
 
1249
        goto err;
1177
1250
    }
1178
1251
    if (!res)
1179
1252
    {                                           // NULL
1180
1253
      if (!fixed_row_size)
1181
1254
      {
1182
 
        if (escape_char != -1)                  // Use \N syntax
1183
 
        {
1184
 
          null_buff[0]=escape_char;
1185
 
          null_buff[1]='N';
1186
 
          if (my_b_write(cache,(unsigned char*) null_buff,2))
1187
 
            goto err;
1188
 
        }
1189
 
        else if (my_b_write(cache,(unsigned char*) "NULL",4))
1190
 
          goto err;
 
1255
        if (escape_char != -1)                  // Use \N syntax
 
1256
        {
 
1257
          null_buff[0]=escape_char;
 
1258
          null_buff[1]='N';
 
1259
          if (my_b_write(&cache,(unsigned char*) null_buff,2))
 
1260
            goto err;
 
1261
        }
 
1262
        else if (my_b_write(&cache,(unsigned char*) "NULL",4))
 
1263
          goto err;
1191
1264
      }
1192
1265
      else
1193
1266
      {
1194
 
        used_length=0;                          // Fill with space
 
1267
        used_length=0;                          // Fill with space
1195
1268
      }
1196
1269
    }
1197
1270
    else
1202
1275
        used_length= res->length();
1203
1276
 
1204
1277
      if ((result_type == STRING_RESULT || is_unsafe_field_sep) &&
1205
 
          escape_char != -1)
 
1278
           escape_char != -1)
1206
1279
      {
1207
1280
        char *pos, *start, *end;
1208
1281
        const CHARSET_INFO * const res_charset= res->charset();
1209
1282
        const CHARSET_INFO * const character_set_client= default_charset_info;
1210
1283
 
1211
1284
        bool check_second_byte= (res_charset == &my_charset_bin) &&
1212
 
          character_set_client->
1213
 
          escape_with_backslash_is_dangerous;
 
1285
                                 character_set_client->
 
1286
                                 escape_with_backslash_is_dangerous;
1214
1287
        assert(character_set_client->mbmaxlen == 2 ||
1215
1288
               !character_set_client->escape_with_backslash_is_dangerous);
1216
 
        for (start=pos=(char*) res->ptr(),end=pos+used_length ;
1217
 
             pos != end ;
1218
 
             pos++)
1219
 
        {
1220
 
          if (use_mb(res_charset))
1221
 
          {
1222
 
            int l;
1223
 
            if ((l=my_ismbchar(res_charset, pos, end)))
1224
 
            {
1225
 
              pos += l-1;
1226
 
              continue;
1227
 
            }
1228
 
          }
 
1289
        for (start=pos=(char*) res->ptr(),end=pos+used_length ;
 
1290
             pos != end ;
 
1291
             pos++)
 
1292
        {
 
1293
          if (use_mb(res_charset))
 
1294
          {
 
1295
            int l;
 
1296
            if ((l=my_ismbchar(res_charset, pos, end)))
 
1297
            {
 
1298
              pos += l-1;
 
1299
              continue;
 
1300
            }
 
1301
          }
1229
1302
 
1230
1303
          /*
1231
1304
            Special case when dumping BINARY/VARBINARY/BLOB values
1259
1332
            assert before the loop makes that sure.
1260
1333
          */
1261
1334
 
1262
 
          if ((needs_escaping(*pos, enclosed) ||
 
1335
          if ((NEED_ESCAPING(*pos) ||
1263
1336
               (check_second_byte &&
1264
1337
                my_mbcharlen(character_set_client, (unsigned char) *pos) == 2 &&
1265
1338
                pos + 1 < end &&
1266
 
                needs_escaping(pos[1], enclosed))) &&
 
1339
                NEED_ESCAPING(pos[1]))) &&
1267
1340
              /*
1268
 
                Don't escape field_term_char by doubling - doubling is only
1269
 
                valid for ENCLOSED BY characters:
 
1341
               Don't escape field_term_char by doubling - doubling is only
 
1342
               valid for ENCLOSED BY characters:
1270
1343
              */
1271
1344
              (enclosed || !is_ambiguous_field_term ||
1272
1345
               (int) (unsigned char) *pos != field_term_char))
1273
1346
          {
1274
 
            char tmp_buff[2];
 
1347
            char tmp_buff[2];
1275
1348
            tmp_buff[0]= ((int) (unsigned char) *pos == field_sep_char &&
1276
1349
                          is_ambiguous_field_sep) ?
1277
 
              field_sep_char : escape_char;
1278
 
            tmp_buff[1]= *pos ? *pos : '0';
1279
 
            if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)) ||
1280
 
                my_b_write(cache,(unsigned char*) tmp_buff,2))
1281
 
              goto err;
1282
 
            start=pos+1;
1283
 
          }
1284
 
        }
1285
 
        if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)))
1286
 
          goto err;
 
1350
                          field_sep_char : escape_char;
 
1351
            tmp_buff[1]= *pos ? *pos : '0';
 
1352
            if (my_b_write(&cache,(unsigned char*) start,(uint32_t) (pos-start)) ||
 
1353
                my_b_write(&cache,(unsigned char*) tmp_buff,2))
 
1354
              goto err;
 
1355
            start=pos+1;
 
1356
          }
 
1357
        }
 
1358
        if (my_b_write(&cache,(unsigned char*) start,(uint32_t) (pos-start)))
 
1359
          goto err;
1287
1360
      }
1288
 
      else if (my_b_write(cache,(unsigned char*) res->ptr(),used_length))
1289
 
        goto err;
 
1361
      else if (my_b_write(&cache,(unsigned char*) res->ptr(),used_length))
 
1362
        goto err;
1290
1363
    }
1291
1364
    if (fixed_row_size)
1292
1365
    {                                           // Fill with space
1293
1366
      if (item->max_length > used_length)
1294
1367
      {
1295
 
        /* QQ:  Fix by adding a my_b_fill() function */
1296
 
        if (!space_inited)
1297
 
        {
1298
 
          space_inited=1;
1299
 
          memset(space, ' ', sizeof(space));
1300
 
        }
1301
 
        uint32_t length=item->max_length-used_length;
1302
 
        for (; length > sizeof(space) ; length-=sizeof(space))
1303
 
        {
1304
 
          if (my_b_write(cache,(unsigned char*) space,sizeof(space)))
1305
 
            goto err;
1306
 
        }
1307
 
        if (my_b_write(cache,(unsigned char*) space,length))
1308
 
          goto err;
 
1368
        /* QQ:  Fix by adding a my_b_fill() function */
 
1369
        if (!space_inited)
 
1370
        {
 
1371
          space_inited=1;
 
1372
          memset(space, ' ', sizeof(space));
 
1373
        }
 
1374
        uint32_t length=item->max_length-used_length;
 
1375
        for (; length > sizeof(space) ; length-=sizeof(space))
 
1376
        {
 
1377
          if (my_b_write(&cache,(unsigned char*) space,sizeof(space)))
 
1378
            goto err;
 
1379
        }
 
1380
        if (my_b_write(&cache,(unsigned char*) space,length))
 
1381
          goto err;
1309
1382
      }
1310
1383
    }
1311
1384
    if (res && enclosed)
1312
1385
    {
1313
 
      if (my_b_write(cache, (unsigned char*) exchange->enclosed->ptr(),
 
1386
      if (my_b_write(&cache, (unsigned char*) exchange->enclosed->ptr(),
1314
1387
                     exchange->enclosed->length()))
1315
1388
        goto err;
1316
1389
    }
1317
1390
    if (--items_left)
1318
1391
    {
1319
 
      if (my_b_write(cache, (unsigned char*) exchange->field_term->ptr(),
 
1392
      if (my_b_write(&cache, (unsigned char*) exchange->field_term->ptr(),
1320
1393
                     field_term_length))
1321
1394
        goto err;
1322
1395
    }
1323
1396
  }
1324
 
  if (my_b_write(cache,(unsigned char*) exchange->line_term->ptr(),
1325
 
                 exchange->line_term->length()))
 
1397
  if (my_b_write(&cache,(unsigned char*) exchange->line_term->ptr(),
 
1398
                 exchange->line_term->length()))
1326
1399
    goto err;
1327
1400
  return(0);
1328
1401
err:
1339
1412
select_dump::prepare(List<Item> &, Select_Lex_Unit *u)
1340
1413
{
1341
1414
  unit= u;
1342
 
  return (int) ((file= create_file(session, path, exchange, cache)) < 0);
 
1415
  return (int) ((file= create_file(session, path, exchange, &cache)) < 0);
1343
1416
}
1344
1417
 
1345
1418
 
1366
1439
    res=item->str_result(&tmp);
1367
1440
    if (!res)                                   // If NULL
1368
1441
    {
1369
 
      if (my_b_write(cache,(unsigned char*) "",1))
 
1442
      if (my_b_write(&cache,(unsigned char*) "",1))
1370
1443
        goto err;
1371
1444
    }
1372
 
    else if (my_b_write(cache,(unsigned char*) res->ptr(),res->length()))
 
1445
    else if (my_b_write(&cache,(unsigned char*) res->ptr(),res->length()))
1373
1446
    {
1374
 
      my_error(ER_ERROR_ON_WRITE, MYF(0), path, errno);
 
1447
      my_error(ER_ERROR_ON_WRITE, MYF(0), path, my_errno);
1375
1448
      goto err;
1376
1449
    }
1377
1450
  }
1543
1616
 
1544
1617
bool Session::copy_db_to(char **p_db, size_t *p_db_length)
1545
1618
{
1546
 
  if (db.empty())
 
1619
  if (db == NULL)
1547
1620
  {
1548
1621
    my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
1549
1622
    return true;
1550
1623
  }
1551
 
  *p_db= strmake(db.c_str(), db.length());
1552
 
  *p_db_length= db.length();
 
1624
  *p_db= strmake(db, db_length);
 
1625
  *p_db_length= db_length;
1553
1626
  return false;
1554
1627
}
1555
1628
 
1564
1637
  quick_group= 1;
1565
1638
  table_charset= 0;
1566
1639
  precomputed_group_by= 0;
 
1640
  bit_fields_as_long= 0;
1567
1641
}
1568
1642
 
1569
1643
void Tmp_Table_Param::cleanup(void)
1588
1662
  memset(&status_var, 0, sizeof(status_var));
1589
1663
}
1590
1664
 
 
1665
void Security_context::skip_grants()
 
1666
{
 
1667
  /* privileges for the user are unknown everything is allowed */
 
1668
}
 
1669
 
1591
1670
 
1592
1671
/****************************************************************************
1593
1672
  Handling of open and locked tables states.
1617
1696
  set_open_tables_state(backup);
1618
1697
}
1619
1698
 
1620
 
bool Session::set_db(const std::string &new_db)
 
1699
 
 
1700
bool Session::set_db(const char *new_db, size_t new_db_len)
1621
1701
{
1622
1702
  /* Do not reallocate memory if current chunk is big enough. */
1623
 
  if (new_db.length())
1624
 
    db= new_db;
 
1703
  if (db && new_db && db_length >= new_db_len)
 
1704
    memcpy(db, new_db, new_db_len+1);
1625
1705
  else
1626
 
    db.clear();
1627
 
 
1628
 
  return false;
 
1706
  {
 
1707
    if (db)
 
1708
      free(db);
 
1709
    if (new_db)
 
1710
    {
 
1711
      db= (char *)malloc(new_db_len + 1);
 
1712
      if (db != NULL)
 
1713
      {
 
1714
        memcpy(db, new_db, new_db_len);
 
1715
        db[new_db_len]= 0;
 
1716
      }
 
1717
    }
 
1718
    else
 
1719
      db= NULL;
 
1720
  }
 
1721
  db_length= db ? new_db_len : 0;
 
1722
  return new_db && !db;
1629
1723
}
1630
1724
 
1631
1725
 
1632
 
 
1633
 
 
1634
1726
/**
1635
1727
  Check the killed state of a user thread
1636
1728
  @param session  user thread
1643
1735
}
1644
1736
 
1645
1737
/**
1646
 
  Return the session id of a user session
1647
 
  @param pointer to Session object
1648
 
  @return session's id
 
1738
  Return the thread id of a user thread
 
1739
  @param session user thread
 
1740
  @return thread id
1649
1741
*/
1650
1742
extern "C" unsigned long session_get_thread_id(const Session *session)
1651
1743
{
1652
 
  return (unsigned long) session->getSessionId();
1653
 
}
1654
 
 
 
1744
  return((unsigned long)session->thread_id);
 
1745
}
 
1746
 
 
1747
 
 
1748
extern "C"
 
1749
LEX_STRING *session_make_lex_string(Session *session, LEX_STRING *lex_str,
 
1750
                                const char *str, unsigned int size,
 
1751
                                int allocate_lex_string)
 
1752
{
 
1753
  return session->make_lex_string(lex_str, str, size,
 
1754
                              (bool) allocate_lex_string);
 
1755
}
1655
1756
 
1656
1757
const struct charset_info_st *session_charset(Session *session)
1657
1758
{
1658
1759
  return(session->charset());
1659
1760
}
1660
1761
 
 
1762
char **session_query(Session *session)
 
1763
{
 
1764
  return(&session->query);
 
1765
}
 
1766
 
1661
1767
int session_non_transactional_update(const Session *session)
1662
1768
{
1663
 
  return(session->transaction.all.hasModifiedNonTransData());
 
1769
  return(session->transaction.all.modified_non_trans_table);
1664
1770
}
1665
1771
 
1666
1772
void session_mark_transaction_to_rollback(Session *session, bool all)
1689
1795
  plugin_sessionvar_cleanup(this);
1690
1796
 
1691
1797
  /* If necessary, log any aborted or unauthorized connections */
1692
 
  if (killed || client->wasAborted())
 
1798
  if (killed || protocol->wasAborted())
1693
1799
    statistic_increment(aborted_threads, &LOCK_status);
1694
1800
 
1695
 
  if (client->wasAborted())
 
1801
  if (protocol->wasAborted())
1696
1802
  {
1697
1803
    if (! killed && variables.log_warnings > 1)
1698
1804
    {
1699
 
      SecurityContext *sctx= &security_ctx;
 
1805
      Security_context *sctx= &security_ctx;
1700
1806
 
1701
1807
      errmsg_printf(ERRMSG_LVL_WARN, ER(ER_NEW_ABORTING_CONNECTION)
1702
1808
                  , thread_id
1703
 
                  , (db.empty() ? "unconnected" : db.c_str())
1704
 
                  , sctx->getUser().empty() == false ? sctx->getUser().c_str() : "unauthenticated"
1705
 
                  , sctx->getIp().c_str()
 
1809
                  , (db ? db : "unconnected")
 
1810
                  , sctx->user.empty() == false ? sctx->user.c_str() : "unauthenticated"
 
1811
                  , sctx->ip.c_str()
1706
1812
                  , (main_da.is_error() ? main_da.message() : ER(ER_UNKNOWN_ERROR)));
1707
1813
    }
1708
1814
  }
1711
1817
  if (should_lock)
1712
1818
    (void) pthread_mutex_lock(&LOCK_thread_count);
1713
1819
  killed= Session::KILL_CONNECTION;
1714
 
  if (client->isConnected())
 
1820
  if (protocol->isConnected())
1715
1821
  {
1716
1822
    if (errcode)
1717
1823
    {
1718
1824
      /*my_error(errcode, ER(errcode));*/
1719
 
      client->sendError(errcode, ER(errcode));
 
1825
      protocol->sendError(errcode, ER(errcode)); /* purecov: inspected */
1720
1826
    }
1721
 
    client->close();
 
1827
    protocol->close();
1722
1828
  }
1723
1829
  if (should_lock)
1724
1830
    (void) pthread_mutex_unlock(&LOCK_thread_count);
1738
1844
  server_status&= ~ (SERVER_MORE_RESULTS_EXISTS |
1739
1845
                          SERVER_QUERY_NO_INDEX_USED |
1740
1846
                          SERVER_QUERY_NO_GOOD_INDEX_USED);
 
1847
  /*
 
1848
    If in autocommit mode and not in a transaction, reset
 
1849
    OPTION_STATUS_NO_TRANS_UPDATE | OPTION_KEEP_LOG to not get warnings
 
1850
    in ha_rollback_trans() about some tables couldn't be rolled back.
 
1851
  */
 
1852
  if (!(options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
 
1853
  {
 
1854
    options&= ~OPTION_KEEP_LOG;
 
1855
    transaction.all.modified_non_trans_table= false;
 
1856
  }
1741
1857
 
1742
1858
  clear_error();
1743
1859
  main_da.reset_diagnostics_area();
1747
1863
 
1748
1864
/*
1749
1865
  Close all temporary tables created by 'CREATE TEMPORARY TABLE' for thread
 
1866
  creates one DROP TEMPORARY Table binlog event for each pseudo-thread
1750
1867
*/
1751
1868
 
1752
1869
void Session::close_temporary_tables()
1754
1871
  Table *table;
1755
1872
  Table *tmp_next;
1756
1873
 
1757
 
  if (not temporary_tables)
 
1874
  if (!temporary_tables)
1758
1875
    return;
1759
1876
 
1760
1877
  for (table= temporary_tables; table; table= tmp_next)
1761
1878
  {
1762
1879
    tmp_next= table->next;
1763
 
    nukeTable(table);
 
1880
    close_temporary(table, true, true);
1764
1881
  }
1765
1882
  temporary_tables= NULL;
1766
1883
}
1769
1886
  unlink from session->temporary tables and close temporary table
1770
1887
*/
1771
1888
 
1772
 
void Session::close_temporary_table(Table *table)
 
1889
void Session::close_temporary_table(Table *table,
 
1890
                                    bool free_share, bool delete_table)
1773
1891
{
1774
1892
  if (table->prev)
1775
1893
  {
1790
1908
    if (temporary_tables)
1791
1909
      table->next->prev= NULL;
1792
1910
  }
1793
 
  nukeTable(table);
 
1911
  close_temporary(table, free_share, delete_table);
1794
1912
}
1795
1913
 
1796
1914
/*
1797
 
  Close and drop a temporary table
 
1915
  Close and delete a temporary table
1798
1916
 
1799
1917
  NOTE
1800
1918
  This dosn't unlink table from session->temporary
1801
1919
  If this is needed, use close_temporary_table()
1802
1920
*/
1803
1921
 
1804
 
void Session::nukeTable(Table *table)
 
1922
void Session::close_temporary(Table *table, bool free_share, bool delete_table)
1805
1923
{
1806
 
  plugin::StorageEngine *table_type= table->s->db_type();
 
1924
  StorageEngine *table_type= table->s->db_type();
1807
1925
 
1808
1926
  table->free_io_cache();
1809
1927
  table->closefrm(false);
1810
1928
 
1811
 
  TableIdentifier identifier(table->s->getSchemaName(), table->s->table_name.str, table->s->path.str);
1812
 
  rm_temporary_table(table_type, identifier);
1813
 
 
1814
 
  table->s->free_table_share();
1815
 
 
1816
 
  /* This makes me sad, but we're allocating it via malloc */
1817
 
  free(table);
 
1929
  if (delete_table)
 
1930
    rm_temporary_table(table_type, table->s->path.str);
 
1931
 
 
1932
  if (free_share)
 
1933
  {
 
1934
    table->s->free_table_share();
 
1935
    /* This makes me sad, but we're allocating it via malloc */
 
1936
    free(table);
 
1937
  }
1818
1938
}
1819
1939
 
1820
1940
/** Clear most status variables. */
1841
1961
  pthread_mutex_unlock(&LOCK_status);
1842
1962
}
1843
1963
 
 
1964
#define extra_size sizeof(double)
 
1965
 
1844
1966
user_var_entry *Session::getVariable(LEX_STRING &name, bool create_if_not_exists)
1845
1967
{
1846
1968
  user_var_entry *entry= NULL;
1875
1997
    if (table->query_id == query_id)
1876
1998
    {
1877
1999
      table->query_id= 0;
1878
 
      table->cursor->ha_reset();
 
2000
      table->file->ha_reset();
1879
2001
    }
1880
2002
  }
1881
2003
}
1887
2009
    if (table->query_id == query_id)
1888
2010
    {
1889
2011
      table->query_id= 0;
1890
 
      table->cursor->ha_reset();
 
2012
      table->file->ha_reset();
1891
2013
    }
1892
2014
  }
1893
2015
}
1945
2067
   */
1946
2068
  if (backups_available == false)
1947
2069
  {
1948
 
    TransactionServices &transaction_services= TransactionServices::singleton();
1949
2070
    main_da.can_overwrite_status= true;
1950
 
    transaction_services.ha_autocommit_or_rollback(this, is_error());
 
2071
    ha_autocommit_or_rollback(this, is_error());
1951
2072
    main_da.can_overwrite_status= false;
1952
2073
    transaction.stmt.reset();
1953
2074
  }
2001
2122
    if (open_tables_from_list(&tables, &counter))
2002
2123
      return true;
2003
2124
 
2004
 
    if (not lock_tables(tables, counter, &need_reopen))
 
2125
    if (!lock_tables(tables, counter, &need_reopen))
2005
2126
      break;
2006
 
    if (not need_reopen)
 
2127
    if (!need_reopen)
2007
2128
      return true;
2008
2129
    close_tables_for_reopen(&tables);
2009
2130
  }
2010
2131
  if ((mysql_handle_derived(lex, &mysql_derived_prepare) ||
2011
2132
       (fill_derived_tables() &&
2012
2133
        mysql_handle_derived(lex, &mysql_derived_filling))))
2013
 
    return true;
 
2134
    return true; /* purecov: inspected */
2014
2135
 
2015
2136
  return false;
2016
2137
}
2022
2143
  assert(ret == false);
2023
2144
  if (open_tables_from_list(&tables, &counter, flags) ||
2024
2145
      mysql_handle_derived(lex, &mysql_derived_prepare))
2025
 
    return true;
2026
 
  return false;
2027
 
}
2028
 
 
2029
 
bool Session::rm_temporary_table(TableIdentifier &identifier)
2030
 
{
2031
 
  if (plugin::StorageEngine::dropTable(*this, identifier))
2032
 
  {
2033
 
    errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
2034
 
                  identifier.getSQLPath().c_str(), errno);
2035
 
    dumpTemporaryTableNames("rm_temporary_table()");
2036
 
 
2037
 
    return true;
2038
 
  }
2039
 
 
2040
 
  return false;
2041
 
}
2042
 
 
2043
 
bool Session::rm_temporary_table(plugin::StorageEngine *base, TableIdentifier &identifier)
2044
 
{
 
2146
    return true; /* purecov: inspected */
 
2147
  return false;
 
2148
}
 
2149
 
 
2150
bool Session::rm_temporary_table(StorageEngine *base, char *path)
 
2151
{
 
2152
  bool error=0;
 
2153
 
2045
2154
  assert(base);
2046
2155
 
2047
 
  if (plugin::StorageEngine::dropTable(*this, *base, identifier))
 
2156
  if (delete_table_proto_file(path))
 
2157
    error=1; /* purecov: inspected */
 
2158
 
 
2159
  if (base->deleteTable(this, path))
2048
2160
  {
 
2161
    error=1;
2049
2162
    errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
2050
 
                  identifier.getSQLPath().c_str(), errno);
2051
 
    dumpTemporaryTableNames("rm_temporary_table()");
2052
 
 
2053
 
    return true;
2054
 
  }
2055
 
 
2056
 
  return false;
2057
 
}
2058
 
 
2059
 
/**
2060
 
  @note this will be removed, I am looking through Hudson to see if it is finding
2061
 
  any tables that are missed during cleanup.
2062
 
*/
2063
 
void Session::dumpTemporaryTableNames(const char *foo)
2064
 
{
2065
 
  Table *table;
2066
 
 
2067
 
  if (not temporary_tables)
2068
 
    return;
2069
 
 
2070
 
  cerr << "Begin Run: " << foo << "\n";
2071
 
  for (table= temporary_tables; table; table= table->next)
2072
 
  {
2073
 
    bool have_proto= false;
2074
 
 
2075
 
    message::Table *proto= table->s->getTableProto();
2076
 
    if (table->s->getTableProto())
2077
 
      have_proto= true;
2078
 
 
2079
 
    const char *answer= have_proto ? "true" : "false";
2080
 
 
2081
 
    if (have_proto)
2082
 
    {
2083
 
      cerr << "\tTable Name " << table->s->getSchemaName() << "." << table->s->table_name.str << " : " << answer << "\n";
2084
 
      cerr << "\t\t Proto " << proto->schema() << " " << proto->name() << "\n";
2085
 
    }
2086
 
    else
2087
 
      cerr << "\tTabl;e Name " << table->s->getSchemaName() << "." << table->s->table_name.str << " : " << answer << "\n";
2088
 
  }
2089
 
}
2090
 
 
2091
 
bool Session::storeTableMessage(TableIdentifier &identifier, message::Table &table_message)
2092
 
{
2093
 
  table_message_cache.insert(make_pair(identifier.getPath(), table_message));
2094
 
 
2095
 
  return true;
2096
 
}
2097
 
 
2098
 
bool Session::removeTableMessage(TableIdentifier &identifier)
2099
 
{
2100
 
  TableMessageCache::iterator iter;
2101
 
 
2102
 
  iter= table_message_cache.find(identifier.getPath());
2103
 
 
2104
 
  if (iter == table_message_cache.end())
2105
 
    return false;
2106
 
 
2107
 
  table_message_cache.erase(iter);
2108
 
 
2109
 
  return true;
2110
 
}
2111
 
 
2112
 
bool Session::getTableMessage(TableIdentifier &identifier, message::Table &table_message)
2113
 
{
2114
 
  TableMessageCache::iterator iter;
2115
 
 
2116
 
  iter= table_message_cache.find(identifier.getPath());
2117
 
 
2118
 
  if (iter == table_message_cache.end())
2119
 
    return false;
2120
 
 
2121
 
  table_message.CopyFrom(((*iter).second));
2122
 
 
2123
 
  return true;
2124
 
}
2125
 
 
2126
 
bool Session::doesTableMessageExist(TableIdentifier &identifier)
2127
 
{
2128
 
  TableMessageCache::iterator iter;
2129
 
 
2130
 
  iter= table_message_cache.find(identifier.getPath());
2131
 
 
2132
 
  if (iter == table_message_cache.end())
2133
 
  {
2134
 
    return false;
2135
 
  }
2136
 
 
2137
 
  return true;
2138
 
}
2139
 
 
2140
 
bool Session::renameTableMessage(TableIdentifier &from, TableIdentifier &to)
2141
 
{
2142
 
  TableMessageCache::iterator iter;
2143
 
 
2144
 
  table_message_cache[to.getPath()]= table_message_cache[from.getPath()];
2145
 
 
2146
 
  iter= table_message_cache.find(to.getPath());
2147
 
 
2148
 
  if (iter == table_message_cache.end())
2149
 
  {
2150
 
    return false;
2151
 
  }
2152
 
 
2153
 
  (*iter).second.set_schema(to.getSchemaName());
2154
 
  (*iter).second.set_name(to.getTableName());
2155
 
 
2156
 
  return true;
2157
 
}
2158
 
 
2159
 
} /* namespace drizzled */
 
2163
                  path, my_errno);
 
2164
  }
 
2165
  return(error);
 
2166
}
 
2167
 
 
2168