~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/session.cc

fix pthread atomics. operator precedence is important. The unit test now passes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
 */
23
23
 
24
24
#include "config.h"
25
 
#include "drizzled/session.h"
 
25
#include <drizzled/session.h>
26
26
#include "drizzled/session_list.h"
27
27
#include <sys/stat.h>
28
 
#include "drizzled/error.h"
29
 
#include "drizzled/gettext.h"
30
 
#include "drizzled/query_id.h"
31
 
#include "drizzled/data_home.h"
32
 
#include "drizzled/sql_base.h"
33
 
#include "drizzled/lock.h"
34
 
#include "drizzled/item/cache.h"
35
 
#include "drizzled/item/float.h"
36
 
#include "drizzled/item/return_int.h"
37
 
#include "drizzled/item/empty_string.h"
38
 
#include "drizzled/show.h"
39
 
#include "drizzled/plugin/client.h"
 
28
#include <drizzled/error.h>
 
29
#include <drizzled/gettext.h>
 
30
#include <drizzled/query_id.h>
 
31
#include <drizzled/data_home.h>
 
32
#include <drizzled/sql_base.h>
 
33
#include <drizzled/lock.h>
 
34
#include <drizzled/item/cache.h>
 
35
#include <drizzled/item/float.h>
 
36
#include <drizzled/item/return_int.h>
 
37
#include <drizzled/item/empty_string.h>
 
38
#include <drizzled/show.h>
 
39
#include <drizzled/plugin/client.h>
40
40
#include "drizzled/plugin/scheduler.h"
41
41
#include "drizzled/plugin/authentication.h"
42
42
#include "drizzled/plugin/logging.h"
48
48
#include "drizzled/transaction_services.h"
49
49
#include "drizzled/drizzled.h"
50
50
 
51
 
#include "drizzled/table/instance.h"
 
51
#include "drizzled/table_share_instance.h"
52
52
 
53
53
#include "plugin/myisam/myisam.h"
54
54
#include "drizzled/internal/iocache.h"
55
 
#include "drizzled/internal/thread_var.h"
56
55
#include "drizzled/plugin/event_observer.h"
57
56
 
58
 
#include "drizzled/util/functors.h"
59
 
 
60
 
#include "drizzled/display.h"
61
 
 
62
57
#include <fcntl.h>
63
58
#include <algorithm>
64
59
#include <climits>
65
 
#include <boost/filesystem.hpp>
66
 
 
67
 
#include "drizzled/util/backtrace.h"
68
60
 
69
61
using namespace std;
70
 
 
71
 
namespace fs=boost::filesystem;
72
62
namespace drizzled
73
63
{
74
64
 
80
70
char empty_c_string[1]= {0};    /* used for not defined db */
81
71
 
82
72
const char * const Session::DEFAULT_WHERE= "field list";
 
73
extern pthread_key_t THR_Session;
 
74
extern pthread_key_t THR_Mem_root;
 
75
 
 
76
 
 
77
/****************************************************************************
 
78
** User variables
 
79
****************************************************************************/
 
80
static unsigned char *get_var_key(user_var_entry *entry, size_t *length, bool)
 
81
{
 
82
  *length= entry->name.length;
 
83
  return (unsigned char*) entry->name.str;
 
84
}
 
85
 
 
86
static void free_user_var(user_var_entry *entry)
 
87
{
 
88
  delete entry;
 
89
}
83
90
 
84
91
bool Key_part_spec::operator==(const Key_part_spec& other) const
85
92
{
153
160
  return (int) session->lex->sql_command;
154
161
}
155
162
 
156
 
enum_tx_isolation session_tx_isolation(const Session *session)
 
163
int session_tx_isolation(const Session *session)
157
164
{
158
 
  return (enum_tx_isolation)session->variables.tx_isolation;
 
165
  return (int) session->variables.tx_isolation;
159
166
}
160
167
 
161
168
Session::Session(plugin::Client *client_arg) :
162
169
  Open_tables_state(refresh_version),
163
170
  mem_root(&main_mem_root),
164
 
  xa_id(0),
165
171
  lex(&main_lex),
166
 
  query(new std::string),
167
 
  catalog("LOCAL"),
 
172
  query(),
168
173
  client(client_arg),
169
174
  scheduler(NULL),
170
175
  scheduler_arg(NULL),
171
176
  lock_id(&main_lock_id),
172
177
  user_time(0),
173
178
  ha_data(plugin::num_trx_monitored_objects),
174
 
  concurrent_execute_allowed(true),
175
179
  arg_of_last_insert_id_function(false),
176
180
  first_successful_insert_id_in_prev_stmt(0),
177
181
  first_successful_insert_id_in_cur_stmt(0),
178
182
  limit_found_rows(0),
179
 
  _global_read_lock(NONE),
180
 
  _killed(NOT_KILLED),
 
183
  global_read_lock(0),
181
184
  some_tables_deleted(false),
182
185
  no_errors(false),
183
186
  password(false),
190
193
  cached_table(0),
191
194
  transaction_message(NULL),
192
195
  statement_message(NULL),
193
 
  session_event_observers(NULL),
194
 
  use_usage(false)
 
196
  session_event_observers(NULL)
195
197
{
 
198
  memset(process_list_info, 0, PROCESS_LIST_WIDTH);
196
199
  client->setSession(this);
197
200
 
198
201
  /*
202
205
  */
203
206
  memory::init_sql_alloc(&main_mem_root, memory::ROOT_MIN_BLOCK_SIZE, 0);
204
207
  thread_stack= NULL;
205
 
  count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
 
208
  count_cuted_fields= CHECK_FIELD_IGNORE;
 
209
  killed= NOT_KILLED;
206
210
  col_access= 0;
207
211
  tmp_table= 0;
208
212
  used_tables= 0;
220
224
  query_id= 0;
221
225
  warn_query_id= 0;
222
226
  mysys_var= 0;
223
 
  scoreboard_index= -1;
224
227
  dbug_sentry=Session_SENTRY_MAGIC;
225
 
  cleanup_done= abort_on_warning= no_warnings_for_error= false;  
226
 
 
227
 
  /* query_cache init */
228
 
  query_cache_key= "";
229
 
  resultset= NULL;
 
228
  cleanup_done= abort_on_warning= no_warnings_for_error= false;
 
229
  pthread_mutex_init(&LOCK_delete, MY_MUTEX_INIT_FAST);
230
230
 
231
231
  /* Variables with default values */
232
232
  proc_info="login";
258
258
 
259
259
  /* Initialize sub structures */
260
260
  memory::init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
 
261
  hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
 
262
            (hash_get_key) get_var_key,
 
263
            (hash_free_key) free_user_var, 0);
261
264
 
262
265
  substitute_null_with_insert_id = false;
263
 
  lock_info.init(); /* safety: will be reset after start */
 
266
  thr_lock_info_init(&lock_info); /* safety: will be reset after start */
264
267
  thr_lock_owner_init(&main_lock_id, &lock_info);
265
268
 
266
269
  m_internal_handler= NULL;
300
303
  return false;                                 // 'false', as per coding style
301
304
}
302
305
 
303
 
void Session::setAbort(bool arg)
304
 
{
305
 
  mysys_var->abort= arg;
306
 
}
307
 
 
308
 
void Session::lockOnSys()
309
 
{
310
 
  if (not mysys_var)
311
 
    return;
312
 
 
313
 
  setAbort(true);
314
 
  boost_unique_lock_t scopedLock(mysys_var->mutex);
315
 
  if (mysys_var->current_cond)
316
 
  {
317
 
    mysys_var->current_mutex->lock();
318
 
    mysys_var->current_cond->notify_all();
319
 
    mysys_var->current_mutex->unlock();
320
 
  }
321
 
}
322
 
 
323
306
void Session::pop_internal_handler()
324
307
{
325
308
  assert(m_internal_handler != NULL);
337
320
{
338
321
  assert(cleanup_done == false);
339
322
 
340
 
  setKilled(KILL_CONNECTION);
 
323
  killed= KILL_CONNECTION;
341
324
#ifdef ENABLE_WHEN_BINLOG_WILL_BE_ABLE_TO_PREPARE
342
325
  if (transaction.xid_state.xa_state == XA_PREPARED)
343
326
  {
349
332
    transaction_services.rollbackTransaction(this, true);
350
333
    xid_cache_delete(&transaction.xid_state);
351
334
  }
352
 
 
353
 
  for (UserVars::iterator iter= user_vars.begin();
354
 
       iter != user_vars.end();
355
 
       iter++)
356
 
  {
357
 
    user_var_entry *entry= (*iter).second;
358
 
    delete entry;
359
 
  }
360
 
  user_vars.clear();
361
 
 
362
 
 
 
335
  hash_free(&user_vars);
363
336
  close_temporary_tables();
364
337
 
365
338
  if (global_read_lock)
366
 
  {
367
 
    unlockGlobalReadLock();
368
 
  }
 
339
    unlock_global_read_lock(this);
369
340
 
370
341
  cleanup_done= true;
371
342
}
373
344
Session::~Session()
374
345
{
375
346
  this->checkSentry();
 
347
  add_to_status(&global_status_var, &status_var);
376
348
 
377
349
  if (client->isConnected())
378
350
  {
399
371
  dbug_sentry= Session_SENTRY_GONE;
400
372
 
401
373
  main_mem_root.free_root(MYF(0));
402
 
  currentMemRoot().release();
403
 
  currentSession().release();
 
374
  pthread_setspecific(THR_Session,  0);
404
375
 
405
376
  plugin::Logging::postEndDo(this);
406
377
  plugin::EventObserver::deregisterSessionEvents(*this); 
407
378
 
408
 
  for (PropertyMap::iterator iter= life_properties.begin(); iter != life_properties.end(); iter++)
409
 
  {
410
 
    delete (*iter).second;
411
 
  }
412
 
  life_properties.clear();
413
 
 
414
 
#if 0
415
 
  drizzled::util::custom_backtrace();
416
 
#endif
417
 
}
418
 
 
419
 
void Session::setClient(plugin::Client *client_arg)
420
 
{
421
 
  client= client_arg;
422
 
  client->setSession(this);
423
 
}
424
 
 
425
 
void Session::awake(Session::killed_state_t state_to_set)
 
379
  /* Ensure that no one is using Session */
 
380
  pthread_mutex_unlock(&LOCK_delete);
 
381
  pthread_mutex_destroy(&LOCK_delete);
 
382
}
 
383
 
 
384
/*
 
385
  Add all status variables to another status variable array
 
386
 
 
387
  SYNOPSIS
 
388
   add_to_status()
 
389
   to_var       add to this array
 
390
   from_var     from this array
 
391
 
 
392
  NOTES
 
393
    This function assumes that all variables are long/ulong.
 
394
    If this assumption will change, then we have to explictely add
 
395
    the other variables after the while loop
 
396
*/
 
397
void add_to_status(system_status_var *to_var, system_status_var *from_var)
 
398
{
 
399
  ulong *end= (ulong*) ((unsigned char*) to_var +
 
400
                        offsetof(system_status_var, last_system_status_var) +
 
401
                        sizeof(ulong));
 
402
  ulong *to= (ulong*) to_var, *from= (ulong*) from_var;
 
403
 
 
404
  while (to != end)
 
405
    *(to++)+= *(from++);
 
406
}
 
407
 
 
408
/*
 
409
  Add the difference between two status variable arrays to another one.
 
410
 
 
411
  SYNOPSIS
 
412
    add_diff_to_status
 
413
    to_var       add to this array
 
414
    from_var     from this array
 
415
    dec_var      minus this array
 
416
 
 
417
  NOTE
 
418
    This function assumes that all variables are long/ulong.
 
419
*/
 
420
void add_diff_to_status(system_status_var *to_var, system_status_var *from_var,
 
421
                        system_status_var *dec_var)
 
422
{
 
423
  ulong *end= (ulong*) ((unsigned char*) to_var + offsetof(system_status_var,
 
424
                                                  last_system_status_var) +
 
425
                        sizeof(ulong));
 
426
  ulong *to= (ulong*) to_var, *from= (ulong*) from_var, *dec= (ulong*) dec_var;
 
427
 
 
428
  while (to != end)
 
429
    *(to++)+= *(from++) - *(dec++);
 
430
}
 
431
 
 
432
void Session::awake(Session::killed_state state_to_set)
426
433
{
427
434
  this->checkSentry();
 
435
  safe_mutex_assert_owner(&LOCK_delete);
428
436
 
429
 
  setKilled(state_to_set);
 
437
  killed= state_to_set;
430
438
  if (state_to_set != Session::KILL_QUERY)
431
439
  {
432
440
    scheduler->killSession(this);
434
442
  }
435
443
  if (mysys_var)
436
444
  {
437
 
    boost_unique_lock_t scopedLock(mysys_var->mutex);
 
445
    pthread_mutex_lock(&mysys_var->mutex);
438
446
    /*
439
 
      "
440
447
      This broadcast could be up in the air if the victim thread
441
448
      exits the cond in the time between read and broadcast, but that is
442
449
      ok since all we want to do is to make the victim thread get out
457
464
    */
458
465
    if (mysys_var->current_cond && mysys_var->current_mutex)
459
466
    {
460
 
      mysys_var->current_mutex->lock();
461
 
      mysys_var->current_cond->notify_all();
462
 
      mysys_var->current_mutex->unlock();
 
467
      pthread_mutex_lock(mysys_var->current_mutex);
 
468
      pthread_cond_broadcast(mysys_var->current_cond);
 
469
      pthread_mutex_unlock(mysys_var->current_mutex);
463
470
    }
 
471
    pthread_mutex_unlock(&mysys_var->mutex);
464
472
  }
465
473
}
466
474
 
476
484
  */
477
485
  assert(thread_stack);
478
486
 
479
 
  currentSession().release();
480
 
  currentSession().reset(this);
481
 
 
482
 
  currentMemRoot().release();
483
 
  currentMemRoot().reset(&mem_root);
 
487
  if (pthread_setspecific(THR_Session,  this) ||
 
488
      pthread_setspecific(THR_Mem_root, &mem_root))
 
489
    return true;
484
490
 
485
491
  mysys_var=my_thread_var;
486
492
 
489
495
    This allows us to move Session to different threads if needed.
490
496
  */
491
497
  mysys_var->id= thread_id;
 
498
  real_id= pthread_self();                      // For debugging
492
499
 
493
500
  /*
494
501
    We have to call thr_lock_info_init() again here as Session may have been
495
502
    created in another thread
496
503
  */
497
 
  lock_info.init();
498
 
 
 
504
  thr_lock_info_init(&lock_info);
499
505
  return false;
500
506
}
501
507
 
519
525
                                variables.query_prealloc_size);
520
526
  transaction.xid_state.xid.null();
521
527
  transaction.xid_state.in_session=1;
522
 
  if (use_usage)
523
 
    resetUsage();
524
528
}
525
529
 
526
530
bool Session::initGlobals()
528
532
  if (storeGlobals())
529
533
  {
530
534
    disconnect(ER_OUT_OF_RESOURCES, true);
531
 
    status_var.aborted_connects++;
 
535
    status_var_increment(current_global_counters.aborted_connects);
532
536
    return true;
533
537
  }
534
538
  return false;
544
548
 
545
549
  prepareForQueries();
546
550
 
547
 
  while (not client->haveError() && getKilled() != KILL_CONNECTION)
 
551
  while (! client->haveError() && killed != KILL_CONNECTION)
548
552
  {
549
 
    if (not executeStatement())
 
553
    if (! executeStatement())
550
554
      break;
551
555
  }
552
556
 
553
557
  disconnect(0, true);
554
558
}
555
559
 
556
 
bool Session::schedule(Session::shared_ptr &arg)
 
560
bool Session::schedule()
557
561
{
558
 
  arg->scheduler= plugin::Scheduler::getScheduler();
559
 
  assert(arg->scheduler);
 
562
  scheduler= plugin::Scheduler::getScheduler();
 
563
  assert(scheduler);
560
564
 
561
565
  connection_count.increment();
562
566
 
565
569
    current_global_counters.max_used_connections= connection_count;
566
570
  }
567
571
 
568
 
  current_global_counters.connections++;
569
 
  arg->thread_id= arg->variables.pseudo_thread_id= global_thread_id++;
570
 
 
571
 
  session::Cache::singleton().insert(arg);
572
 
 
573
 
  if (unlikely(plugin::EventObserver::connectSession(*arg)))
574
 
  {
575
 
    // We should do something about an error...
576
 
  }
577
 
 
578
 
  if (plugin::Scheduler::getScheduler()->addSession(arg))
579
 
  {
580
 
    DRIZZLE_CONNECTION_START(arg->getSessionId());
 
572
  thread_id= variables.pseudo_thread_id= global_thread_id++;
 
573
 
 
574
  pthread_mutex_lock(&LOCK_thread_count);
 
575
  getSessionList().push_back(this);
 
576
  pthread_mutex_unlock(&LOCK_thread_count);
 
577
 
 
578
  if (scheduler->addSession(this))
 
579
  {
 
580
    DRIZZLE_CONNECTION_START(thread_id);
581
581
    char error_message_buff[DRIZZLE_ERRMSG_SIZE];
582
582
 
583
 
    arg->setKilled(Session::KILL_CONNECTION);
 
583
    killed= Session::KILL_CONNECTION;
584
584
 
585
 
    arg->status_var.aborted_connects++;
 
585
    status_var_increment(current_global_counters.aborted_connects);
586
586
 
587
587
    /* Can't use my_error() since store_globals has not been called. */
588
588
    /* TODO replace will better error message */
589
589
    snprintf(error_message_buff, sizeof(error_message_buff),
590
590
             ER(ER_CANT_CREATE_THREAD), 1);
591
 
    arg->client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
592
 
 
 
591
    client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
593
592
    return true;
594
593
  }
595
594
 
597
596
}
598
597
 
599
598
 
600
 
/*
601
 
  Is this session viewable by the current user?
602
 
*/
603
 
bool Session::isViewable() const
604
 
{
605
 
  return plugin::Authorization::isAuthorized(current_session->getSecurityContext(),
606
 
                                             this,
607
 
                                             false);
608
 
}
609
 
 
610
 
 
611
 
const char* Session::enter_cond(boost::condition_variable_any &cond, boost::mutex &mutex, const char* msg)
 
599
const char* Session::enter_cond(pthread_cond_t *cond,
 
600
                                pthread_mutex_t* mutex,
 
601
                                const char* msg)
612
602
{
613
603
  const char* old_msg = get_proc_info();
614
604
  safe_mutex_assert_owner(mutex);
615
 
  mysys_var->current_mutex = &mutex;
616
 
  mysys_var->current_cond = &cond;
 
605
  mysys_var->current_mutex = mutex;
 
606
  mysys_var->current_cond = cond;
617
607
  this->set_proc_info(msg);
618
608
  return old_msg;
619
609
}
626
616
    locked (if that would not be the case, you'll get a deadlock if someone
627
617
    does a Session::awake() on you).
628
618
  */
629
 
  mysys_var->current_mutex->unlock();
630
 
  boost_unique_lock_t scopedLock(mysys_var->mutex);
 
619
  pthread_mutex_unlock(mysys_var->current_mutex);
 
620
  pthread_mutex_lock(&mysys_var->mutex);
631
621
  mysys_var->current_mutex = 0;
632
622
  mysys_var->current_cond = 0;
633
623
  this->set_proc_info(old_msg);
 
624
  pthread_mutex_unlock(&mysys_var->mutex);
634
625
}
635
626
 
636
627
bool Session::authenticate()
637
628
{
638
 
  lex->start(this);
 
629
  lex_start(this);
639
630
  if (client->authenticate())
640
631
    return false;
641
632
 
642
 
  status_var.aborted_connects++;
643
 
 
 
633
  status_var_increment(current_global_counters.aborted_connects);
644
634
  return true;
645
635
}
646
636
 
647
 
bool Session::checkUser(const std::string &passwd_str,
648
 
                        const std::string &in_db)
 
637
bool Session::checkUser(const char *passwd, uint32_t passwd_len, const char *in_db)
649
638
{
 
639
  const string passwd_str(passwd, passwd_len);
650
640
  bool is_authenticated=
651
641
    plugin::Authentication::isAuthenticated(getSecurityContext(),
652
642
                                            passwd_str);
653
643
 
654
644
  if (is_authenticated != true)
655
645
  {
656
 
    status_var.access_denied++;
657
646
    /* isAuthenticated has pushed the error message */
658
647
    return false;
659
648
  }
660
649
 
661
650
  /* Change database if necessary */
662
 
  if (not in_db.empty())
 
651
  if (in_db && in_db[0])
663
652
  {
664
653
    SchemaIdentifier identifier(in_db);
665
654
    if (mysql_change_db(this, identifier))
669
658
    }
670
659
  }
671
660
  my_ok();
672
 
  password= not passwd_str.empty();
 
661
  password= test(passwd_len);          // remember for error messages
673
662
 
674
663
  /* Ready to handle queries */
675
664
  return true;
691
680
  main_da.reset_diagnostics_area();
692
681
 
693
682
  if (client->readCommand(&l_packet, &packet_length) == false)
694
 
  {
695
 
    return false;
696
 
  }
697
 
 
698
 
  if (getKilled() == KILL_CONNECTION)
699
683
    return false;
700
684
 
701
685
  if (packet_length == 0)
702
686
    return true;
703
687
 
704
 
  l_command= static_cast<enum_server_command>(l_packet[0]);
 
688
  l_command= (enum enum_server_command) (unsigned char) l_packet[0];
705
689
 
706
690
  if (command >= COM_END)
707
691
    command= COM_END;                           // Wrong command
708
692
 
709
693
  assert(packet_length);
710
 
  return not dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
 
694
  return ! dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
711
695
}
712
696
 
713
697
bool Session::readAndStoreQuery(const char *in_packet, uint32_t in_packet_length)
719
703
    in_packet_length--;
720
704
  }
721
705
  const char *pos= in_packet + in_packet_length; /* Point at end null */
722
 
  while (in_packet_length > 0 && (pos[-1] == ';' || my_isspace(charset() ,pos[-1])))
 
706
  while (in_packet_length > 0 &&
 
707
         (pos[-1] == ';' || my_isspace(charset() ,pos[-1])))
723
708
  {
724
709
    pos--;
725
710
    in_packet_length--;
726
711
  }
727
712
 
728
 
  query.reset(new std::string(in_packet, in_packet + in_packet_length));
 
713
  query.assign(in_packet, in_packet + in_packet_length);
729
714
 
730
715
  return true;
731
716
}
780
765
  }
781
766
 
782
767
  if (result == false)
783
 
  {
784
768
    my_error(killed_errno(), MYF(0));
785
 
  }
786
769
  else if ((result == true) && do_release)
787
 
  {
788
 
    setKilled(Session::KILL_CONNECTION);
789
 
  }
 
770
    killed= Session::KILL_CONNECTION;
790
771
 
791
772
  return result;
792
773
}
857
838
  where= Session::DEFAULT_WHERE;
858
839
 
859
840
  /* Reset the temporary shares we built */
860
 
  for_each(temporary_shares.begin(),
861
 
           temporary_shares.end(),
862
 
           DeletePtr());
 
841
  for (std::vector<TableShareInstance *>::iterator iter= temporary_shares.begin();
 
842
       iter != temporary_shares.end(); iter++)
 
843
  {
 
844
    delete *iter;
 
845
  }
863
846
  temporary_shares.clear();
864
847
}
865
848
 
945
928
  my_message(errcode, err, MYF(0));
946
929
  if (file > 0)
947
930
  {
948
 
    (void) cache->end_io_cache();
 
931
    (void) end_io_cache(cache);
949
932
    (void) internal::my_close(file, MYF(0));
950
 
    (void) internal::my_delete(path.file_string().c_str(), MYF(0));             // Delete file on error
 
933
    (void) internal::my_delete(path, MYF(0));           // Delete file on error
951
934
    file= -1;
952
935
  }
953
936
}
955
938
 
956
939
bool select_to_file::send_eof()
957
940
{
958
 
  int error= test(cache->end_io_cache());
 
941
  int error= test(end_io_cache(cache));
959
942
  if (internal::my_close(file, MYF(MY_WME)))
960
943
    error= 1;
961
944
  if (!error)
977
960
  /* In case of error send_eof() may be not called: close the file here. */
978
961
  if (file >= 0)
979
962
  {
980
 
    (void) cache->end_io_cache();
 
963
    (void) end_io_cache(cache);
981
964
    (void) internal::my_close(file, MYF(0));
982
965
    file= -1;
983
966
  }
984
 
  path= "";
 
967
  path[0]= '\0';
985
968
  row_count= 0;
986
969
}
987
970
 
991
974
    cache(static_cast<internal::IO_CACHE *>(memory::sql_calloc(sizeof(internal::IO_CACHE)))),
992
975
    row_count(0L)
993
976
{
994
 
  path= "";
 
977
  path[0]=0;
995
978
}
996
979
 
997
980
select_to_file::~select_to_file()
1025
1008
*/
1026
1009
 
1027
1010
 
1028
 
static int create_file(Session *session,
1029
 
                       fs::path &target_path,
1030
 
                       file_exchange *exchange,
1031
 
                       internal::IO_CACHE *cache)
 
1011
static int create_file(Session *session, char *path, file_exchange *exchange, internal::IO_CACHE *cache)
1032
1012
{
1033
 
  fs::path to_file(exchange->file_name);
1034
1013
  int file;
1035
 
 
1036
 
  if (not to_file.has_root_directory())
 
1014
  uint32_t option= MY_UNPACK_FILENAME | MY_RELATIVE_PATH;
 
1015
 
 
1016
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
 
1017
  option|= MY_REPLACE_DIR;                      // Force use of db directory
 
1018
#endif
 
1019
 
 
1020
  if (!internal::dirname_length(exchange->file_name))
1037
1021
  {
1038
 
    target_path= fs::system_complete(getDataHomeCatalog());
1039
 
    if (not session->db.empty())
1040
 
    {
1041
 
      int count_elements= 0;
1042
 
      for (fs::path::iterator iter= to_file.begin();
1043
 
           iter != to_file.end();
1044
 
           ++iter, ++count_elements)
1045
 
      { }
1046
 
 
1047
 
      if (count_elements == 1)
1048
 
      {
1049
 
        target_path /= session->db;
1050
 
      }
1051
 
    }
1052
 
    target_path /= to_file;
 
1022
    strcpy(path, data_home_real);
 
1023
    if (! session->db.empty())
 
1024
      strncat(path, session->db.c_str(), FN_REFLEN-strlen(data_home_real)-1);
 
1025
    (void) internal::fn_format(path, exchange->file_name, path, "", option);
1053
1026
  }
1054
1027
  else
1055
 
  {
1056
 
    target_path = exchange->file_name;
1057
 
  }
1058
 
 
1059
 
  if (not secure_file_priv.string().empty())
1060
 
  {
1061
 
    if (target_path.file_string().substr(0, secure_file_priv.file_string().size()) != secure_file_priv.file_string())
1062
 
    {
1063
 
      /* Write only allowed to dir or subdir specified by secure_file_priv */
1064
 
      my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
1065
 
      return -1;
1066
 
    }
1067
 
  }
1068
 
 
1069
 
  if (!access(target_path.file_string().c_str(), F_OK))
 
1028
    (void) internal::fn_format(path, exchange->file_name, data_home_real, "", option);
 
1029
 
 
1030
  if (opt_secure_file_priv &&
 
1031
      strncmp(opt_secure_file_priv, path, strlen(opt_secure_file_priv)))
 
1032
  {
 
1033
    /* Write only allowed to dir or subdir specified by secure_file_priv */
 
1034
    my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
 
1035
    return -1;
 
1036
  }
 
1037
 
 
1038
  if (!access(path, F_OK))
1070
1039
  {
1071
1040
    my_error(ER_FILE_EXISTS_ERROR, MYF(0), exchange->file_name);
1072
1041
    return -1;
1073
1042
  }
1074
1043
  /* Create the file world readable */
1075
 
  if ((file= internal::my_create(target_path.file_string().c_str(), 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
 
1044
  if ((file= internal::my_create(path, 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
1076
1045
    return file;
1077
1046
  (void) fchmod(file, 0666);                    // Because of umask()
1078
 
  if (cache->init_io_cache(file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
 
1047
  if (init_io_cache(cache, file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1079
1048
  {
1080
1049
    internal::my_close(file, MYF(0));
1081
 
    internal::my_delete(target_path.file_string().c_str(), MYF(0));  // Delete file on error, it was just created
 
1050
    internal::my_delete(path, MYF(0));  // Delete file on error, it was just created
1082
1051
    return -1;
1083
1052
  }
1084
1053
  return file;
1092
1061
  bool string_results= false, non_string_results= false;
1093
1062
  unit= u;
1094
1063
  if ((uint32_t) strlen(exchange->file_name) + NAME_LEN >= FN_REFLEN)
1095
 
  {
1096
 
    path= exchange->file_name;
1097
 
  }
 
1064
    strncpy(path,exchange->file_name,FN_REFLEN-1);
1098
1065
 
1099
1066
  /* Check if there is any blobs in data */
1100
1067
  {
1157
1124
  if (unit->offset_limit_cnt)
1158
1125
  {                                             // using limit offset,count
1159
1126
    unit->offset_limit_cnt--;
1160
 
    return false;
 
1127
    return(0);
1161
1128
  }
1162
1129
  row_count++;
1163
1130
  Item *item;
1166
1133
 
1167
1134
  if (my_b_write(cache,(unsigned char*) exchange->line_start->ptr(),
1168
1135
                 exchange->line_start->length()))
1169
 
    return true;
1170
 
 
 
1136
    goto err;
1171
1137
  while ((item=li++))
1172
1138
  {
1173
1139
    Item_result result_type=item->result_type();
1178
1144
    {
1179
1145
      if (my_b_write(cache,(unsigned char*) exchange->enclosed->ptr(),
1180
1146
                     exchange->enclosed->length()))
1181
 
        return true;
 
1147
        goto err;
1182
1148
    }
1183
1149
    if (!res)
1184
1150
    {                                           // NULL
1189
1155
          null_buff[0]=escape_char;
1190
1156
          null_buff[1]='N';
1191
1157
          if (my_b_write(cache,(unsigned char*) null_buff,2))
1192
 
            return true;
 
1158
            goto err;
1193
1159
        }
1194
1160
        else if (my_b_write(cache,(unsigned char*) "NULL",4))
1195
 
          return true;
 
1161
          goto err;
1196
1162
      }
1197
1163
      else
1198
1164
      {
1202
1168
    else
1203
1169
    {
1204
1170
      if (fixed_row_size)
1205
 
        used_length= min(res->length(), static_cast<size_t>(item->max_length));
 
1171
        used_length= min(res->length(),item->max_length);
1206
1172
      else
1207
1173
        used_length= res->length();
1208
1174
 
1283
1249
            tmp_buff[1]= *pos ? *pos : '0';
1284
1250
            if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)) ||
1285
1251
                my_b_write(cache,(unsigned char*) tmp_buff,2))
1286
 
              return true;
 
1252
              goto err;
1287
1253
            start=pos+1;
1288
1254
          }
1289
1255
        }
1290
1256
        if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)))
1291
 
          return true;
 
1257
          goto err;
1292
1258
      }
1293
1259
      else if (my_b_write(cache,(unsigned char*) res->ptr(),used_length))
1294
 
        return true;
 
1260
        goto err;
1295
1261
    }
1296
1262
    if (fixed_row_size)
1297
1263
    {                                           // Fill with space
1307
1273
        for (; length > sizeof(space) ; length-=sizeof(space))
1308
1274
        {
1309
1275
          if (my_b_write(cache,(unsigned char*) space,sizeof(space)))
1310
 
            return true;
 
1276
            goto err;
1311
1277
        }
1312
1278
        if (my_b_write(cache,(unsigned char*) space,length))
1313
 
          return true;
 
1279
          goto err;
1314
1280
      }
1315
1281
    }
1316
1282
    if (res && enclosed)
1317
1283
    {
1318
1284
      if (my_b_write(cache, (unsigned char*) exchange->enclosed->ptr(),
1319
1285
                     exchange->enclosed->length()))
1320
 
        return true;
 
1286
        goto err;
1321
1287
    }
1322
1288
    if (--items_left)
1323
1289
    {
1324
1290
      if (my_b_write(cache, (unsigned char*) exchange->field_term->ptr(),
1325
1291
                     field_term_length))
1326
 
        return true;
 
1292
        goto err;
1327
1293
    }
1328
1294
  }
1329
1295
  if (my_b_write(cache,(unsigned char*) exchange->line_term->ptr(),
1330
1296
                 exchange->line_term->length()))
1331
 
  {
1332
 
    return true;
1333
 
  }
1334
 
 
1335
 
  return false;
 
1297
    goto err;
 
1298
  return(0);
 
1299
err:
 
1300
  return(1);
1336
1301
}
1337
1302
 
1338
1303
 
1365
1330
  if (row_count++ > 1)
1366
1331
  {
1367
1332
    my_message(ER_TOO_MANY_ROWS, ER(ER_TOO_MANY_ROWS), MYF(0));
1368
 
    return 1;
 
1333
    goto err;
1369
1334
  }
1370
1335
  while ((item=li++))
1371
1336
  {
1373
1338
    if (!res)                                   // If NULL
1374
1339
    {
1375
1340
      if (my_b_write(cache,(unsigned char*) "",1))
1376
 
        return 1;
 
1341
        goto err;
1377
1342
    }
1378
1343
    else if (my_b_write(cache,(unsigned char*) res->ptr(),res->length()))
1379
1344
    {
1380
 
      my_error(ER_ERROR_ON_WRITE, MYF(0), path.file_string().c_str(), errno);
1381
 
      return 1;
 
1345
      my_error(ER_ERROR_ON_WRITE, MYF(0), path, errno);
 
1346
      goto err;
1382
1347
    }
1383
1348
  }
1384
1349
  return(0);
 
1350
err:
 
1351
  return(1);
1385
1352
}
1386
1353
 
1387
1354
 
1439
1406
      switch (val_item->result_type())
1440
1407
      {
1441
1408
      case REAL_RESULT:
1442
 
        op= &select_max_min_finder_subselect::cmp_real;
1443
 
        break;
 
1409
        op= &select_max_min_finder_subselect::cmp_real;
 
1410
        break;
1444
1411
      case INT_RESULT:
1445
 
        op= &select_max_min_finder_subselect::cmp_int;
1446
 
        break;
 
1412
        op= &select_max_min_finder_subselect::cmp_int;
 
1413
        break;
1447
1414
      case STRING_RESULT:
1448
 
        op= &select_max_min_finder_subselect::cmp_str;
1449
 
        break;
 
1415
        op= &select_max_min_finder_subselect::cmp_str;
 
1416
        break;
1450
1417
      case DECIMAL_RESULT:
1451
1418
        op= &select_max_min_finder_subselect::cmp_decimal;
1452
1419
        break;
1453
1420
      case ROW_RESULT:
1454
1421
        // This case should never be choosen
1455
 
        assert(0);
1456
 
        op= 0;
 
1422
        assert(0);
 
1423
        op= 0;
1457
1424
      }
1458
1425
    }
1459
1426
    cache->store(val_item);
1542
1509
void Session::end_statement()
1543
1510
{
1544
1511
  /* Cleanup SQL processing state to reuse this statement in next query. */
1545
 
  lex->end();
1546
 
  query_cache_key= ""; // reset the cache key
1547
 
  resetResultsetMessage();
 
1512
  lex_end(lex);
1548
1513
}
1549
1514
 
1550
1515
bool Session::copy_db_to(char **p_db, size_t *p_db_length)
1607
1572
}
1608
1573
 
1609
1574
 
 
1575
 
 
1576
 
 
1577
/**
 
1578
  Check the killed state of a user thread
 
1579
  @param session  user thread
 
1580
  @retval 0 the user thread is active
 
1581
  @retval 1 the user thread has been killed
 
1582
*/
 
1583
int session_killed(const Session *session)
 
1584
{
 
1585
  return(session->killed);
 
1586
}
 
1587
 
 
1588
 
 
1589
const struct charset_info_st *session_charset(Session *session)
 
1590
{
 
1591
  return(session->charset());
 
1592
}
 
1593
 
1610
1594
/**
1611
1595
  Mark transaction to rollback and mark error as fatal to a sub-statement.
1612
1596
 
1628
1612
  plugin_sessionvar_cleanup(this);
1629
1613
 
1630
1614
  /* If necessary, log any aborted or unauthorized connections */
1631
 
  if (getKilled() || client->wasAborted())
 
1615
  if (killed || client->wasAborted())
1632
1616
  {
1633
 
    status_var.aborted_threads++;
 
1617
    status_var_increment(current_global_counters.aborted_threads);
1634
1618
  }
1635
1619
 
1636
1620
  if (client->wasAborted())
1637
1621
  {
1638
 
    if (not getKilled() && variables.log_warnings > 1)
 
1622
    if (! killed && variables.log_warnings > 1)
1639
1623
    {
1640
1624
      SecurityContext *sctx= &security_ctx;
1641
1625
 
1650
1634
 
1651
1635
  /* Close out our connection to the client */
1652
1636
  if (should_lock)
1653
 
    session::Cache::singleton().mutex().lock();
1654
 
 
1655
 
  setKilled(Session::KILL_CONNECTION);
1656
 
 
 
1637
    (void) pthread_mutex_lock(&LOCK_thread_count);
 
1638
  killed= Session::KILL_CONNECTION;
1657
1639
  if (client->isConnected())
1658
1640
  {
1659
1641
    if (errcode)
1663
1645
    }
1664
1646
    client->close();
1665
1647
  }
1666
 
 
1667
1648
  if (should_lock)
1668
 
  {
1669
 
    session::Cache::singleton().mutex().unlock();
1670
 
  }
 
1649
    (void) pthread_mutex_unlock(&LOCK_thread_count);
1671
1650
}
1672
1651
 
1673
1652
void Session::reset_for_next_command()
1695
1674
  Close all temporary tables created by 'CREATE TEMPORARY TABLE' for thread
1696
1675
*/
1697
1676
 
1698
 
void Open_tables_state::close_temporary_tables()
 
1677
void Session::close_temporary_tables()
1699
1678
{
1700
1679
  Table *table;
1701
1680
  Table *tmp_next;
1705
1684
 
1706
1685
  for (table= temporary_tables; table; table= tmp_next)
1707
1686
  {
1708
 
    tmp_next= table->getNext();
 
1687
    tmp_next= table->next;
1709
1688
    nukeTable(table);
1710
1689
  }
1711
1690
  temporary_tables= NULL;
1715
1694
  unlink from session->temporary tables and close temporary table
1716
1695
*/
1717
1696
 
1718
 
void Open_tables_state::close_temporary_table(Table *table)
 
1697
void Session::close_temporary_table(Table *table)
1719
1698
{
1720
 
  if (table->getPrev())
 
1699
  if (table->prev)
1721
1700
  {
1722
 
    table->getPrev()->setNext(table->getNext());
1723
 
    if (table->getPrev()->getNext())
1724
 
    {
1725
 
      table->getNext()->setPrev(table->getPrev());
1726
 
    }
 
1701
    table->prev->next= table->next;
 
1702
    if (table->prev->next)
 
1703
      table->next->prev= table->prev;
1727
1704
  }
1728
1705
  else
1729
1706
  {
1734
1711
      passing non-zero value to end_slave via rli->save_temporary_tables
1735
1712
      when no temp tables opened, see an invariant below.
1736
1713
    */
1737
 
    temporary_tables= table->getNext();
 
1714
    temporary_tables= table->next;
1738
1715
    if (temporary_tables)
1739
 
    {
1740
 
      table->getNext()->setPrev(NULL);
1741
 
    }
 
1716
      table->next->prev= NULL;
1742
1717
  }
1743
1718
  nukeTable(table);
1744
1719
}
1751
1726
  If this is needed, use close_temporary_table()
1752
1727
*/
1753
1728
 
1754
 
void Open_tables_state::nukeTable(Table *table)
 
1729
void Session::nukeTable(Table *table)
1755
1730
{
1756
1731
  plugin::StorageEngine *table_type= table->getShare()->db_type();
1757
1732
 
1758
1733
  table->free_io_cache();
1759
 
  table->delete_table();
 
1734
  table->delete_table(false);
1760
1735
 
1761
1736
  TableIdentifier identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName(), table->getShare()->getPath());
1762
1737
  rm_temporary_table(table_type, identifier);
1764
1739
  delete table->getMutableShare();
1765
1740
 
1766
1741
  /* This makes me sad, but we're allocating it via malloc */
1767
 
  delete table;
 
1742
  free(table);
1768
1743
}
1769
1744
 
1770
1745
/** Clear most status variables. */
1772
1747
 
1773
1748
void Session::refresh_status()
1774
1749
{
 
1750
  pthread_mutex_lock(&LOCK_status);
 
1751
 
 
1752
  /* Add thread's status variabes to global status */
 
1753
  add_to_status(&global_status_var, &status_var);
 
1754
 
1775
1755
  /* Reset thread's status variables */
1776
1756
  memset(&status_var, 0, sizeof(status_var));
1777
1757
 
 
1758
  /* Reset some global variables */
 
1759
  reset_status_vars();
 
1760
 
 
1761
  /* Reset the counters of all key caches (default and named). */
 
1762
  reset_key_cache_counters();
1778
1763
  flush_status_time= time((time_t*) 0);
1779
1764
  current_global_counters.max_used_connections= 1; /* We set it to one, because we know we exist */
1780
 
  current_global_counters.connections= 0;
 
1765
  pthread_mutex_unlock(&LOCK_status);
1781
1766
}
1782
1767
 
1783
1768
user_var_entry *Session::getVariable(LEX_STRING &name, bool create_if_not_exists)
1784
1769
{
1785
 
  return getVariable(std::string(name.str, name.length), create_if_not_exists);
1786
 
}
1787
 
 
1788
 
user_var_entry *Session::getVariable(const std::string  &name, bool create_if_not_exists)
1789
 
{
1790
 
  UserVarsRange ppp= user_vars.equal_range(name);
1791
 
 
1792
 
  for (UserVars::iterator iter= ppp.first;
1793
 
       iter != ppp.second; ++iter)
1794
 
  {
1795
 
    return (*iter).second;
1796
 
  }
1797
 
 
1798
 
  if (not create_if_not_exists)
1799
 
    return NULL;
1800
 
 
1801
1770
  user_var_entry *entry= NULL;
1802
 
  entry= new (nothrow) user_var_entry(name.c_str(), query_id);
1803
 
 
1804
 
  if (entry == NULL)
1805
 
    return NULL;
1806
 
 
1807
 
  std::pair<UserVars::iterator, bool> returnable= user_vars.insert(make_pair(name, entry));
1808
 
 
1809
 
  if (not returnable.second)
 
1771
 
 
1772
  entry= (user_var_entry*) hash_search(&user_vars, (unsigned char*) name.str, name.length);
 
1773
 
 
1774
  if ((entry == NULL) && create_if_not_exists)
1810
1775
  {
1811
 
    delete entry;
 
1776
    if (!hash_inited(&user_vars))
 
1777
      return NULL;
 
1778
    entry= new (nothrow) user_var_entry(name.str, query_id);
 
1779
 
 
1780
    if (entry == NULL)
 
1781
      return NULL;
 
1782
 
 
1783
    if (my_hash_insert(&user_vars, (unsigned char*) entry))
 
1784
    {
 
1785
      assert(1);
 
1786
      delete entry;
 
1787
      return 0;
 
1788
    }
 
1789
 
1812
1790
  }
1813
1791
 
1814
1792
  return entry;
1815
1793
}
1816
1794
 
1817
 
void Session::setVariable(const std::string &name, const std::string &value)
1818
 
{
1819
 
  user_var_entry *updateable_var= getVariable(name.c_str(), true);
1820
 
 
1821
 
  updateable_var->update_hash(false,
1822
 
                              (void*)value.c_str(),
1823
 
                              static_cast<uint32_t>(value.length()), STRING_RESULT,
1824
 
                              &my_charset_bin,
1825
 
                              DERIVATION_IMPLICIT, false);
1826
 
}
1827
 
 
1828
 
void Open_tables_state::mark_temp_tables_as_free_for_reuse()
1829
 
{
1830
 
  for (Table *table= temporary_tables ; table ; table= table->getNext())
 
1795
void Session::mark_temp_tables_as_free_for_reuse()
 
1796
{
 
1797
  for (Table *table= temporary_tables ; table ; table= table->next)
1831
1798
  {
1832
 
    if (table->query_id == getQueryId())
 
1799
    if (table->query_id == query_id)
1833
1800
    {
1834
1801
      table->query_id= 0;
1835
1802
      table->cursor->ha_reset();
1839
1806
 
1840
1807
void Session::mark_used_tables_as_free_for_reuse(Table *table)
1841
1808
{
1842
 
  for (; table ; table= table->getNext())
 
1809
  for (; table ; table= table->next)
1843
1810
  {
1844
 
    if (table->query_id == getQueryId())
 
1811
    if (table->query_id == query_id)
1845
1812
    {
1846
1813
      table->query_id= 0;
1847
1814
      table->cursor->ha_reset();
1860
1827
*/
1861
1828
void Session::close_thread_tables()
1862
1829
{
1863
 
  clearDerivedTables();
 
1830
  if (derived_tables)
 
1831
    derived_tables= NULL; // They should all be invalid by this point
1864
1832
 
1865
1833
  /*
1866
1834
    Mark all temporary tables used by this statement as free for reuse.
1893
1861
      handled either before writing a query log event (inside
1894
1862
      binlog_query()) or when preparing a pending event.
1895
1863
     */
1896
 
    unlockTables(lock);
 
1864
    mysql_unlock_tables(this, lock);
1897
1865
    lock= 0;
1898
1866
  }
1899
1867
  /*
1900
1868
    Note that we need to hold LOCK_open while changing the
1901
1869
    open_tables list. Another thread may work on it.
1902
 
    (See: table::Cache::singleton().removeTable(), mysql_wait_completed_table())
 
1870
    (See: remove_table_from_cache(), mysql_wait_completed_table())
1903
1871
    Closing a MERGE child before the parent would be fatal if the
1904
1872
    other thread tries to abort the MERGE lock in between.
1905
1873
  */
1938
1906
    close_tables_for_reopen(&tables);
1939
1907
  }
1940
1908
  if ((mysql_handle_derived(lex, &mysql_derived_prepare) ||
1941
 
       (
 
1909
       (fill_derived_tables() &&
1942
1910
        mysql_handle_derived(lex, &mysql_derived_filling))))
1943
1911
    return true;
1944
1912
 
1945
1913
  return false;
1946
1914
}
1947
1915
 
1948
 
/*
1949
 
  @note "best_effort" is used in cases were if a failure occurred on this
1950
 
  operation it would not be surprising because we are only removing because there
1951
 
  might be an issue (lame engines).
1952
 
*/
 
1916
bool Session::openTables(TableList *tables, uint32_t flags)
 
1917
{
 
1918
  uint32_t counter;
 
1919
  bool ret= fill_derived_tables();
 
1920
  assert(ret == false);
 
1921
  if (open_tables_from_list(&tables, &counter, flags) ||
 
1922
      mysql_handle_derived(lex, &mysql_derived_prepare))
 
1923
    return true;
 
1924
  return false;
 
1925
}
1953
1926
 
1954
 
bool Open_tables_state::rm_temporary_table(TableIdentifier &identifier, bool best_effort)
 
1927
bool Session::rm_temporary_table(TableIdentifier &identifier)
1955
1928
{
1956
 
  if (plugin::StorageEngine::dropTable(*static_cast<Session *>(this), identifier))
 
1929
  if (plugin::StorageEngine::dropTable(*this, identifier))
1957
1930
  {
1958
 
    if (not best_effort)
1959
 
    {
1960
 
      errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
1961
 
                    identifier.getSQLPath().c_str(), errno);
1962
 
    }
 
1931
    errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
 
1932
                  identifier.getSQLPath().c_str(), errno);
 
1933
    dumpTemporaryTableNames("rm_temporary_table()");
1963
1934
 
1964
1935
    return true;
1965
1936
  }
1967
1938
  return false;
1968
1939
}
1969
1940
 
1970
 
bool Open_tables_state::rm_temporary_table(plugin::StorageEngine *base, TableIdentifier &identifier)
 
1941
bool Session::rm_temporary_table(plugin::StorageEngine *base, TableIdentifier &identifier)
1971
1942
{
1972
1943
  assert(base);
1973
1944
 
1974
 
  if (plugin::StorageEngine::dropTable(*static_cast<Session *>(this), *base, identifier))
 
1945
  if (plugin::StorageEngine::dropTable(*this, *base, identifier))
1975
1946
  {
1976
1947
    errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
1977
1948
                  identifier.getSQLPath().c_str(), errno);
 
1949
    dumpTemporaryTableNames("rm_temporary_table()");
1978
1950
 
1979
1951
    return true;
1980
1952
  }
1986
1958
  @note this will be removed, I am looking through Hudson to see if it is finding
1987
1959
  any tables that are missed during cleanup.
1988
1960
*/
1989
 
void Open_tables_state::dumpTemporaryTableNames(const char *foo)
 
1961
void Session::dumpTemporaryTableNames(const char *foo)
1990
1962
{
1991
1963
  Table *table;
1992
1964
 
1994
1966
    return;
1995
1967
 
1996
1968
  cerr << "Begin Run: " << foo << "\n";
1997
 
  for (table= temporary_tables; table; table= table->getNext())
 
1969
  for (table= temporary_tables; table; table= table->next)
1998
1970
  {
1999
1971
    bool have_proto= false;
2000
1972
 
2014
1986
  }
2015
1987
}
2016
1988
 
2017
 
bool Session::TableMessages::storeTableMessage(const TableIdentifier &identifier, message::Table &table_message)
 
1989
bool Session::storeTableMessage(TableIdentifier &identifier, message::Table &table_message)
2018
1990
{
2019
1991
  table_message_cache.insert(make_pair(identifier.getPath(), table_message));
2020
1992
 
2021
1993
  return true;
2022
1994
}
2023
1995
 
2024
 
bool Session::TableMessages::removeTableMessage(const TableIdentifier &identifier)
 
1996
bool Session::removeTableMessage(TableIdentifier &identifier)
2025
1997
{
2026
1998
  TableMessageCache::iterator iter;
2027
1999
 
2035
2007
  return true;
2036
2008
}
2037
2009
 
2038
 
bool Session::TableMessages::getTableMessage(const TableIdentifier &identifier, message::Table &table_message)
 
2010
bool Session::getTableMessage(TableIdentifier &identifier, message::Table &table_message)
2039
2011
{
2040
2012
  TableMessageCache::iterator iter;
2041
2013
 
2049
2021
  return true;
2050
2022
}
2051
2023
 
2052
 
bool Session::TableMessages::doesTableMessageExist(const TableIdentifier &identifier)
 
2024
bool Session::doesTableMessageExist(TableIdentifier &identifier)
2053
2025
{
2054
2026
  TableMessageCache::iterator iter;
2055
2027
 
2063
2035
  return true;
2064
2036
}
2065
2037
 
2066
 
bool Session::TableMessages::renameTableMessage(const TableIdentifier &from, const TableIdentifier &to)
 
2038
bool Session::renameTableMessage(TableIdentifier &from, TableIdentifier &to)
2067
2039
{
2068
2040
  TableMessageCache::iterator iter;
2069
2041
 
2082
2054
  return true;
2083
2055
}
2084
2056
 
2085
 
table::Instance *Session::getInstanceTable()
 
2057
TableShareInstance *Session::getTemporaryShare()
2086
2058
{
2087
 
  temporary_shares.push_back(new table::Instance()); // This will not go into the tableshare cache, so no key is used.
 
2059
  temporary_shares.push_back(new TableShareInstance()); // This will not go into the tableshare cache, so no key is used.
2088
2060
 
2089
 
  table::Instance *tmp_share= temporary_shares.back();
 
2061
  TableShareInstance *tmp_share= temporary_shares.back();
2090
2062
 
2091
2063
  assert(tmp_share);
2092
2064
 
2093
2065
  return tmp_share;
2094
2066
}
2095
2067
 
2096
 
 
2097
 
/**
2098
 
  Create a reduced Table object with properly set up Field list from a
2099
 
  list of field definitions.
2100
 
 
2101
 
    The created table doesn't have a table Cursor associated with
2102
 
    it, has no keys, no group/distinct, no copy_funcs array.
2103
 
    The sole purpose of this Table object is to use the power of Field
2104
 
    class to read/write data to/from table->getInsertRecord(). Then one can store
2105
 
    the record in any container (RB tree, hash, etc).
2106
 
    The table is created in Session mem_root, so are the table's fields.
2107
 
    Consequently, if you don't BLOB fields, you don't need to free it.
2108
 
 
2109
 
  @param session         connection handle
2110
 
  @param field_list  list of column definitions
2111
 
 
2112
 
  @return
2113
 
    0 if out of memory, Table object in case of success
2114
 
*/
2115
 
table::Instance *Session::getInstanceTable(List<CreateField> &field_list)
 
2068
TableShareInstance *Session::getTemporaryShare(const char *tmpname_arg)
2116
2069
{
2117
 
  temporary_shares.push_back(new table::Instance(this, field_list)); // This will not go into the tableshare cache, so no key is used.
2118
 
 
2119
 
  table::Instance *tmp_share= temporary_shares.back();
 
2070
  assert(tmpname_arg);
 
2071
 
 
2072
  temporary_shares.push_back(new TableShareInstance(tmpname_arg)); // This will not go into the tableshare cache, so no key is used.
 
2073
 
 
2074
  TableShareInstance *tmp_share= temporary_shares.back();
2120
2075
 
2121
2076
  assert(tmp_share);
2122
2077