~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/session.cc

  • Committer: Monty Taylor
  • Date: 2010-06-02 22:35:45 UTC
  • mto: This revision was merged to the branch mainline in revision 1586.
  • Revision ID: mordred@inaugust.com-20100602223545-q8ekf9b40a85nwuf
Rearragned unittests into a single exe because of how we need to link it
(thanks lifeless)
Link with server symbols without needing to build a library.
Added an additional atomics test which tests whatever version of the atomics
lib the running platform would actually use.

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"
26
 
#include "drizzled/session/cache.h"
 
25
#include <drizzled/session.h>
 
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"
43
43
#include "drizzled/plugin/transactional_storage_engine.h"
44
 
#include "drizzled/plugin/query_rewrite.h"
45
44
#include "drizzled/probes.h"
46
45
#include "drizzled/table_proto.h"
47
46
#include "drizzled/db.h"
49
48
#include "drizzled/transaction_services.h"
50
49
#include "drizzled/drizzled.h"
51
50
 
52
 
#include "drizzled/table/instance.h"
 
51
#include "drizzled/table_share_instance.h"
53
52
 
54
53
#include "plugin/myisam/myisam.h"
55
54
#include "drizzled/internal/iocache.h"
56
 
#include "drizzled/internal/thread_var.h"
57
55
#include "drizzled/plugin/event_observer.h"
58
56
 
59
 
#include "drizzled/util/functors.h"
60
 
 
61
 
#include "drizzled/display.h"
62
 
 
63
57
#include <fcntl.h>
64
58
#include <algorithm>
65
59
#include <climits>
66
 
#include <boost/filesystem.hpp>
67
 
 
68
 
#include "drizzled/util/backtrace.h"
69
60
 
70
61
using namespace std;
71
 
 
72
 
namespace fs=boost::filesystem;
73
62
namespace drizzled
74
63
{
75
64
 
81
70
char empty_c_string[1]= {0};    /* used for not defined db */
82
71
 
83
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
}
84
90
 
85
91
bool Key_part_spec::operator==(const Key_part_spec& other) const
86
92
{
87
93
  return length == other.length &&
88
94
         field_name.length == other.field_name.length &&
89
 
    !my_strcasecmp(system_charset_info, field_name.str, other.field_name.str);
 
95
         !strcmp(field_name.str, other.field_name.str);
90
96
}
91
97
 
92
98
Open_tables_state::Open_tables_state(uint64_t version_arg) :
154
160
  return (int) session->lex->sql_command;
155
161
}
156
162
 
157
 
enum_tx_isolation session_tx_isolation(const Session *session)
 
163
int session_tx_isolation(const Session *session)
158
164
{
159
 
  return (enum_tx_isolation)session->variables.tx_isolation;
 
165
  return (int) session->variables.tx_isolation;
160
166
}
161
167
 
162
168
Session::Session(plugin::Client *client_arg) :
163
169
  Open_tables_state(refresh_version),
164
170
  mem_root(&main_mem_root),
165
 
  xa_id(0),
166
171
  lex(&main_lex),
167
 
  query(new std::string),
168
 
  _schema(new std::string("")),
169
 
  catalog("LOCAL"),
 
172
  query(),
170
173
  client(client_arg),
171
174
  scheduler(NULL),
172
175
  scheduler_arg(NULL),
173
176
  lock_id(&main_lock_id),
174
177
  user_time(0),
175
178
  ha_data(plugin::num_trx_monitored_objects),
176
 
  concurrent_execute_allowed(true),
177
179
  arg_of_last_insert_id_function(false),
178
180
  first_successful_insert_id_in_prev_stmt(0),
179
181
  first_successful_insert_id_in_cur_stmt(0),
180
182
  limit_found_rows(0),
181
 
  _global_read_lock(NONE),
182
 
  _killed(NOT_KILLED),
 
183
  global_read_lock(0),
183
184
  some_tables_deleted(false),
184
185
  no_errors(false),
185
186
  password(false),
192
193
  cached_table(0),
193
194
  transaction_message(NULL),
194
195
  statement_message(NULL),
195
 
  session_event_observers(NULL),
196
 
  use_usage(false)
 
196
  session_event_observers(NULL)
197
197
{
 
198
  memset(process_list_info, 0, PROCESS_LIST_WIDTH);
198
199
  client->setSession(this);
199
200
 
200
201
  /*
204
205
  */
205
206
  memory::init_sql_alloc(&main_mem_root, memory::ROOT_MIN_BLOCK_SIZE, 0);
206
207
  thread_stack= NULL;
207
 
  count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
 
208
  count_cuted_fields= CHECK_FIELD_IGNORE;
 
209
  killed= NOT_KILLED;
208
210
  col_access= 0;
209
211
  tmp_table= 0;
210
212
  used_tables= 0;
222
224
  query_id= 0;
223
225
  warn_query_id= 0;
224
226
  mysys_var= 0;
225
 
  scoreboard_index= -1;
226
227
  dbug_sentry=Session_SENTRY_MAGIC;
227
 
  cleanup_done= abort_on_warning= no_warnings_for_error= false;  
228
 
 
229
 
  /* query_cache init */
230
 
  query_cache_key= "";
231
 
  resultset= NULL;
 
228
  cleanup_done= abort_on_warning= no_warnings_for_error= false;
 
229
  pthread_mutex_init(&LOCK_delete, MY_MUTEX_INIT_FAST);
232
230
 
233
231
  /* Variables with default values */
234
232
  proc_info="login";
260
258
 
261
259
  /* Initialize sub structures */
262
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);
263
264
 
264
265
  substitute_null_with_insert_id = false;
265
 
  lock_info.init(); /* safety: will be reset after start */
 
266
  thr_lock_info_init(&lock_info); /* safety: will be reset after start */
266
267
  thr_lock_owner_init(&main_lock_id, &lock_info);
267
268
 
268
269
  m_internal_handler= NULL;
302
303
  return false;                                 // 'false', as per coding style
303
304
}
304
305
 
305
 
void Session::setAbort(bool arg)
306
 
{
307
 
  mysys_var->abort= arg;
308
 
}
309
 
 
310
 
void Session::lockOnSys()
311
 
{
312
 
  if (not mysys_var)
313
 
    return;
314
 
 
315
 
  setAbort(true);
316
 
  boost_unique_lock_t scopedLock(mysys_var->mutex);
317
 
  if (mysys_var->current_cond)
318
 
  {
319
 
    mysys_var->current_mutex->lock();
320
 
    mysys_var->current_cond->notify_all();
321
 
    mysys_var->current_mutex->unlock();
322
 
  }
323
 
}
324
 
 
325
306
void Session::pop_internal_handler()
326
307
{
327
308
  assert(m_internal_handler != NULL);
339
320
{
340
321
  assert(cleanup_done == false);
341
322
 
342
 
  setKilled(KILL_CONNECTION);
 
323
  killed= KILL_CONNECTION;
343
324
#ifdef ENABLE_WHEN_BINLOG_WILL_BE_ABLE_TO_PREPARE
344
325
  if (transaction.xid_state.xa_state == XA_PREPARED)
345
326
  {
351
332
    transaction_services.rollbackTransaction(this, true);
352
333
    xid_cache_delete(&transaction.xid_state);
353
334
  }
354
 
 
355
 
  for (UserVars::iterator iter= user_vars.begin();
356
 
       iter != user_vars.end();
357
 
       iter++)
358
 
  {
359
 
    user_var_entry *entry= (*iter).second;
360
 
    delete entry;
361
 
  }
362
 
  user_vars.clear();
363
 
 
364
 
 
 
335
  hash_free(&user_vars);
365
336
  close_temporary_tables();
366
337
 
367
338
  if (global_read_lock)
368
 
  {
369
 
    unlockGlobalReadLock();
370
 
  }
 
339
    unlock_global_read_lock(this);
371
340
 
372
341
  cleanup_done= true;
373
342
}
375
344
Session::~Session()
376
345
{
377
346
  this->checkSentry();
 
347
  add_to_status(&global_status_var, &status_var);
378
348
 
379
349
  if (client->isConnected())
380
350
  {
401
371
  dbug_sentry= Session_SENTRY_GONE;
402
372
 
403
373
  main_mem_root.free_root(MYF(0));
404
 
  currentMemRoot().release();
405
 
  currentSession().release();
 
374
  pthread_setspecific(THR_Session,  0);
406
375
 
407
376
  plugin::Logging::postEndDo(this);
408
377
  plugin::EventObserver::deregisterSessionEvents(*this); 
409
378
 
410
 
  for (PropertyMap::iterator iter= life_properties.begin(); iter != life_properties.end(); iter++)
411
 
  {
412
 
    delete (*iter).second;
413
 
  }
414
 
  life_properties.clear();
415
 
}
416
 
 
417
 
void Session::setClient(plugin::Client *client_arg)
418
 
{
419
 
  client= client_arg;
420
 
  client->setSession(this);
421
 
}
422
 
 
423
 
void Session::awake(Session::killed_state_t state_to_set)
424
 
{
425
 
  if ((state_to_set == Session::KILL_QUERY) and (command == COM_SLEEP))
426
 
    return;
427
 
 
 
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)
 
433
{
428
434
  this->checkSentry();
429
 
 
430
 
  setKilled(state_to_set);
431
 
  scheduler->killSession(this);
432
 
 
 
435
  safe_mutex_assert_owner(&LOCK_delete);
 
436
 
 
437
  killed= state_to_set;
433
438
  if (state_to_set != Session::KILL_QUERY)
434
439
  {
 
440
    scheduler->killSession(this);
435
441
    DRIZZLE_CONNECTION_DONE(thread_id);
436
442
  }
437
 
 
438
443
  if (mysys_var)
439
444
  {
440
 
    boost_unique_lock_t scopedLock(mysys_var->mutex);
 
445
    pthread_mutex_lock(&mysys_var->mutex);
441
446
    /*
442
 
      "
443
447
      This broadcast could be up in the air if the victim thread
444
448
      exits the cond in the time between read and broadcast, but that is
445
449
      ok since all we want to do is to make the victim thread get out
460
464
    */
461
465
    if (mysys_var->current_cond && mysys_var->current_mutex)
462
466
    {
463
 
      mysys_var->current_mutex->lock();
464
 
      mysys_var->current_cond->notify_all();
465
 
      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);
466
470
    }
 
471
    pthread_mutex_unlock(&mysys_var->mutex);
467
472
  }
468
473
}
469
474
 
479
484
  */
480
485
  assert(thread_stack);
481
486
 
482
 
  currentSession().release();
483
 
  currentSession().reset(this);
484
 
 
485
 
  currentMemRoot().release();
486
 
  currentMemRoot().reset(&mem_root);
 
487
  if (pthread_setspecific(THR_Session,  this) ||
 
488
      pthread_setspecific(THR_Mem_root, &mem_root))
 
489
    return true;
487
490
 
488
491
  mysys_var=my_thread_var;
489
492
 
492
495
    This allows us to move Session to different threads if needed.
493
496
  */
494
497
  mysys_var->id= thread_id;
 
498
  real_id= pthread_self();                      // For debugging
495
499
 
496
500
  /*
497
501
    We have to call thr_lock_info_init() again here as Session may have been
498
502
    created in another thread
499
503
  */
500
 
  lock_info.init();
501
 
 
 
504
  thr_lock_info_init(&lock_info);
502
505
  return false;
503
506
}
504
507
 
522
525
                                variables.query_prealloc_size);
523
526
  transaction.xid_state.xid.null();
524
527
  transaction.xid_state.in_session=1;
525
 
  if (use_usage)
526
 
    resetUsage();
527
528
}
528
529
 
529
530
bool Session::initGlobals()
531
532
  if (storeGlobals())
532
533
  {
533
534
    disconnect(ER_OUT_OF_RESOURCES, true);
534
 
    status_var.aborted_connects++;
 
535
    status_var_increment(current_global_counters.aborted_connects);
535
536
    return true;
536
537
  }
537
538
  return false;
547
548
 
548
549
  prepareForQueries();
549
550
 
550
 
  while (not client->haveError() && getKilled() != KILL_CONNECTION)
 
551
  while (! client->haveError() && killed != KILL_CONNECTION)
551
552
  {
552
 
    if (not executeStatement())
 
553
    if (! executeStatement())
553
554
      break;
554
555
  }
555
556
 
556
557
  disconnect(0, true);
557
558
}
558
559
 
559
 
bool Session::schedule(Session::shared_ptr &arg)
 
560
bool Session::schedule()
560
561
{
561
 
  arg->scheduler= plugin::Scheduler::getScheduler();
562
 
  assert(arg->scheduler);
 
562
  scheduler= plugin::Scheduler::getScheduler();
 
563
  assert(scheduler);
563
564
 
564
565
  connection_count.increment();
565
566
 
568
569
    current_global_counters.max_used_connections= connection_count;
569
570
  }
570
571
 
571
 
  current_global_counters.connections++;
572
 
  arg->thread_id= arg->variables.pseudo_thread_id= global_thread_id++;
573
 
 
574
 
  session::Cache::singleton().insert(arg);
575
 
 
576
 
  if (unlikely(plugin::EventObserver::connectSession(*arg)))
577
 
  {
578
 
    // We should do something about an error...
579
 
  }
580
 
 
581
 
  if (plugin::Scheduler::getScheduler()->addSession(arg))
582
 
  {
583
 
    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);
584
581
    char error_message_buff[DRIZZLE_ERRMSG_SIZE];
585
582
 
586
 
    arg->setKilled(Session::KILL_CONNECTION);
 
583
    killed= Session::KILL_CONNECTION;
587
584
 
588
 
    arg->status_var.aborted_connects++;
 
585
    status_var_increment(current_global_counters.aborted_connects);
589
586
 
590
587
    /* Can't use my_error() since store_globals has not been called. */
591
588
    /* TODO replace will better error message */
592
589
    snprintf(error_message_buff, sizeof(error_message_buff),
593
590
             ER(ER_CANT_CREATE_THREAD), 1);
594
 
    arg->client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
595
 
 
 
591
    client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
596
592
    return true;
597
593
  }
598
594
 
600
596
}
601
597
 
602
598
 
603
 
/*
604
 
  Is this session viewable by the current user?
605
 
*/
606
 
bool Session::isViewable() const
607
 
{
608
 
  return plugin::Authorization::isAuthorized(current_session->getSecurityContext(),
609
 
                                             this,
610
 
                                             false);
611
 
}
612
 
 
613
 
 
614
 
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)
615
602
{
616
603
  const char* old_msg = get_proc_info();
617
604
  safe_mutex_assert_owner(mutex);
618
 
  mysys_var->current_mutex = &mutex;
619
 
  mysys_var->current_cond = &cond;
 
605
  mysys_var->current_mutex = mutex;
 
606
  mysys_var->current_cond = cond;
620
607
  this->set_proc_info(msg);
621
608
  return old_msg;
622
609
}
629
616
    locked (if that would not be the case, you'll get a deadlock if someone
630
617
    does a Session::awake() on you).
631
618
  */
632
 
  mysys_var->current_mutex->unlock();
633
 
  boost_unique_lock_t scopedLock(mysys_var->mutex);
 
619
  pthread_mutex_unlock(mysys_var->current_mutex);
 
620
  pthread_mutex_lock(&mysys_var->mutex);
634
621
  mysys_var->current_mutex = 0;
635
622
  mysys_var->current_cond = 0;
636
623
  this->set_proc_info(old_msg);
 
624
  pthread_mutex_unlock(&mysys_var->mutex);
637
625
}
638
626
 
639
627
bool Session::authenticate()
640
628
{
641
 
  lex->start(this);
 
629
  lex_start(this);
642
630
  if (client->authenticate())
643
631
    return false;
644
632
 
645
 
  status_var.aborted_connects++;
646
 
 
 
633
  status_var_increment(current_global_counters.aborted_connects);
647
634
  return true;
648
635
}
649
636
 
650
 
bool Session::checkUser(const std::string &passwd_str,
651
 
                        const std::string &in_db)
 
637
bool Session::checkUser(const char *passwd, uint32_t passwd_len, const char *in_db)
652
638
{
 
639
  const string passwd_str(passwd, passwd_len);
653
640
  bool is_authenticated=
654
641
    plugin::Authentication::isAuthenticated(getSecurityContext(),
655
642
                                            passwd_str);
656
643
 
657
644
  if (is_authenticated != true)
658
645
  {
659
 
    status_var.access_denied++;
660
646
    /* isAuthenticated has pushed the error message */
661
647
    return false;
662
648
  }
663
649
 
664
650
  /* Change database if necessary */
665
 
  if (not in_db.empty())
 
651
  if (in_db && in_db[0])
666
652
  {
667
653
    SchemaIdentifier identifier(in_db);
668
654
    if (mysql_change_db(this, identifier))
672
658
    }
673
659
  }
674
660
  my_ok();
675
 
  password= not passwd_str.empty();
 
661
  password= test(passwd_len);          // remember for error messages
676
662
 
677
663
  /* Ready to handle queries */
678
664
  return true;
694
680
  main_da.reset_diagnostics_area();
695
681
 
696
682
  if (client->readCommand(&l_packet, &packet_length) == false)
697
 
  {
698
 
    return false;
699
 
  }
700
 
 
701
 
  if (getKilled() == KILL_CONNECTION)
702
683
    return false;
703
684
 
704
685
  if (packet_length == 0)
705
686
    return true;
706
687
 
707
 
  l_command= static_cast<enum_server_command>(l_packet[0]);
 
688
  l_command= (enum enum_server_command) (unsigned char) l_packet[0];
708
689
 
709
690
  if (command >= COM_END)
710
691
    command= COM_END;                           // Wrong command
711
692
 
712
693
  assert(packet_length);
713
 
  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));
714
695
}
715
696
 
716
697
bool Session::readAndStoreQuery(const char *in_packet, uint32_t in_packet_length)
722
703
    in_packet_length--;
723
704
  }
724
705
  const char *pos= in_packet + in_packet_length; /* Point at end null */
725
 
  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])))
726
708
  {
727
709
    pos--;
728
710
    in_packet_length--;
729
711
  }
730
712
 
731
 
  std::string *new_query= new std::string(in_packet, in_packet + in_packet_length);
732
 
  // We can not be entirely sure _schema has a value
733
 
  if (_schema)
734
 
  {
735
 
    plugin::QueryRewriter::rewriteQuery(*_schema, *new_query);
736
 
  }
737
 
  query.reset(new_query);
738
 
  _state.reset(new State(in_packet, in_packet_length));
 
713
  query.assign(in_packet, in_packet + in_packet_length);
739
714
 
740
715
  return true;
741
716
}
790
765
  }
791
766
 
792
767
  if (result == false)
793
 
  {
794
768
    my_error(killed_errno(), MYF(0));
795
 
  }
796
769
  else if ((result == true) && do_release)
797
 
  {
798
 
    setKilled(Session::KILL_CONNECTION);
799
 
  }
 
770
    killed= Session::KILL_CONNECTION;
800
771
 
801
772
  return result;
802
773
}
867
838
  where= Session::DEFAULT_WHERE;
868
839
 
869
840
  /* Reset the temporary shares we built */
870
 
  for_each(temporary_shares.begin(),
871
 
           temporary_shares.end(),
872
 
           DeletePtr());
 
841
  for (std::vector<TableShareInstance *>::iterator iter= temporary_shares.begin();
 
842
       iter != temporary_shares.end(); iter++)
 
843
  {
 
844
    delete *iter;
 
845
  }
873
846
  temporary_shares.clear();
874
847
}
875
848
 
955
928
  my_message(errcode, err, MYF(0));
956
929
  if (file > 0)
957
930
  {
958
 
    (void) cache->end_io_cache();
 
931
    (void) end_io_cache(cache);
959
932
    (void) internal::my_close(file, MYF(0));
960
 
    (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
961
934
    file= -1;
962
935
  }
963
936
}
965
938
 
966
939
bool select_to_file::send_eof()
967
940
{
968
 
  int error= test(cache->end_io_cache());
 
941
  int error= test(end_io_cache(cache));
969
942
  if (internal::my_close(file, MYF(MY_WME)))
970
943
    error= 1;
971
944
  if (!error)
987
960
  /* In case of error send_eof() may be not called: close the file here. */
988
961
  if (file >= 0)
989
962
  {
990
 
    (void) cache->end_io_cache();
 
963
    (void) end_io_cache(cache);
991
964
    (void) internal::my_close(file, MYF(0));
992
965
    file= -1;
993
966
  }
994
 
  path= "";
 
967
  path[0]= '\0';
995
968
  row_count= 0;
996
969
}
997
970
 
1001
974
    cache(static_cast<internal::IO_CACHE *>(memory::sql_calloc(sizeof(internal::IO_CACHE)))),
1002
975
    row_count(0L)
1003
976
{
1004
 
  path= "";
 
977
  path[0]=0;
1005
978
}
1006
979
 
1007
980
select_to_file::~select_to_file()
1035
1008
*/
1036
1009
 
1037
1010
 
1038
 
static int create_file(Session *session,
1039
 
                       fs::path &target_path,
1040
 
                       file_exchange *exchange,
1041
 
                       internal::IO_CACHE *cache)
 
1011
static int create_file(Session *session, char *path, file_exchange *exchange, internal::IO_CACHE *cache)
1042
1012
{
1043
 
  fs::path to_file(exchange->file_name);
1044
1013
  int file;
1045
 
 
1046
 
  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))
1047
1021
  {
1048
 
    target_path= fs::system_complete(getDataHomeCatalog());
1049
 
    util::string::const_shared_ptr schema(session->schema());
1050
 
    if (schema and not schema->empty())
1051
 
    {
1052
 
      int count_elements= 0;
1053
 
      for (fs::path::iterator iter= to_file.begin();
1054
 
           iter != to_file.end();
1055
 
           ++iter, ++count_elements)
1056
 
      { }
1057
 
 
1058
 
      if (count_elements == 1)
1059
 
      {
1060
 
        target_path /= *schema;
1061
 
      }
1062
 
    }
1063
 
    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);
1064
1026
  }
1065
1027
  else
1066
 
  {
1067
 
    target_path = exchange->file_name;
1068
 
  }
1069
 
 
1070
 
  if (not secure_file_priv.string().empty())
1071
 
  {
1072
 
    if (target_path.file_string().substr(0, secure_file_priv.file_string().size()) != secure_file_priv.file_string())
1073
 
    {
1074
 
      /* Write only allowed to dir or subdir specified by secure_file_priv */
1075
 
      my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
1076
 
      return -1;
1077
 
    }
1078
 
  }
1079
 
 
1080
 
  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))
1081
1039
  {
1082
1040
    my_error(ER_FILE_EXISTS_ERROR, MYF(0), exchange->file_name);
1083
1041
    return -1;
1084
1042
  }
1085
1043
  /* Create the file world readable */
1086
 
  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)
1087
1045
    return file;
1088
1046
  (void) fchmod(file, 0666);                    // Because of umask()
1089
 
  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)))
1090
1048
  {
1091
1049
    internal::my_close(file, MYF(0));
1092
 
    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
1093
1051
    return -1;
1094
1052
  }
1095
1053
  return file;
1103
1061
  bool string_results= false, non_string_results= false;
1104
1062
  unit= u;
1105
1063
  if ((uint32_t) strlen(exchange->file_name) + NAME_LEN >= FN_REFLEN)
1106
 
  {
1107
 
    path= exchange->file_name;
1108
 
  }
 
1064
    strncpy(path,exchange->file_name,FN_REFLEN-1);
1109
1065
 
1110
1066
  /* Check if there is any blobs in data */
1111
1067
  {
1115
1071
    {
1116
1072
      if (item->max_length >= MAX_BLOB_WIDTH)
1117
1073
      {
1118
 
        blob_flag=1;
1119
 
        break;
 
1074
        blob_flag=1;
 
1075
        break;
1120
1076
      }
1121
 
 
1122
1077
      if (item->result_type() == STRING_RESULT)
1123
1078
        string_results= true;
1124
1079
      else
1169
1124
  if (unit->offset_limit_cnt)
1170
1125
  {                                             // using limit offset,count
1171
1126
    unit->offset_limit_cnt--;
1172
 
    return false;
 
1127
    return(0);
1173
1128
  }
1174
1129
  row_count++;
1175
1130
  Item *item;
1178
1133
 
1179
1134
  if (my_b_write(cache,(unsigned char*) exchange->line_start->ptr(),
1180
1135
                 exchange->line_start->length()))
1181
 
    return true;
1182
 
 
 
1136
    goto err;
1183
1137
  while ((item=li++))
1184
1138
  {
1185
1139
    Item_result result_type=item->result_type();
1190
1144
    {
1191
1145
      if (my_b_write(cache,(unsigned char*) exchange->enclosed->ptr(),
1192
1146
                     exchange->enclosed->length()))
1193
 
        return true;
 
1147
        goto err;
1194
1148
    }
1195
1149
    if (!res)
1196
1150
    {                                           // NULL
1201
1155
          null_buff[0]=escape_char;
1202
1156
          null_buff[1]='N';
1203
1157
          if (my_b_write(cache,(unsigned char*) null_buff,2))
1204
 
            return true;
 
1158
            goto err;
1205
1159
        }
1206
1160
        else if (my_b_write(cache,(unsigned char*) "NULL",4))
1207
 
          return true;
 
1161
          goto err;
1208
1162
      }
1209
1163
      else
1210
1164
      {
1214
1168
    else
1215
1169
    {
1216
1170
      if (fixed_row_size)
1217
 
        used_length= min(res->length(), static_cast<size_t>(item->max_length));
 
1171
        used_length= min(res->length(),item->max_length);
1218
1172
      else
1219
1173
        used_length= res->length();
1220
1174
 
1295
1249
            tmp_buff[1]= *pos ? *pos : '0';
1296
1250
            if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)) ||
1297
1251
                my_b_write(cache,(unsigned char*) tmp_buff,2))
1298
 
              return true;
 
1252
              goto err;
1299
1253
            start=pos+1;
1300
1254
          }
1301
1255
        }
1302
1256
        if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)))
1303
 
          return true;
 
1257
          goto err;
1304
1258
      }
1305
1259
      else if (my_b_write(cache,(unsigned char*) res->ptr(),used_length))
1306
 
        return true;
 
1260
        goto err;
1307
1261
    }
1308
1262
    if (fixed_row_size)
1309
1263
    {                                           // Fill with space
1319
1273
        for (; length > sizeof(space) ; length-=sizeof(space))
1320
1274
        {
1321
1275
          if (my_b_write(cache,(unsigned char*) space,sizeof(space)))
1322
 
            return true;
 
1276
            goto err;
1323
1277
        }
1324
1278
        if (my_b_write(cache,(unsigned char*) space,length))
1325
 
          return true;
 
1279
          goto err;
1326
1280
      }
1327
1281
    }
1328
1282
    if (res && enclosed)
1329
1283
    {
1330
1284
      if (my_b_write(cache, (unsigned char*) exchange->enclosed->ptr(),
1331
1285
                     exchange->enclosed->length()))
1332
 
        return true;
 
1286
        goto err;
1333
1287
    }
1334
1288
    if (--items_left)
1335
1289
    {
1336
1290
      if (my_b_write(cache, (unsigned char*) exchange->field_term->ptr(),
1337
1291
                     field_term_length))
1338
 
        return true;
 
1292
        goto err;
1339
1293
    }
1340
1294
  }
1341
1295
  if (my_b_write(cache,(unsigned char*) exchange->line_term->ptr(),
1342
1296
                 exchange->line_term->length()))
1343
 
  {
1344
 
    return true;
1345
 
  }
1346
 
 
1347
 
  return false;
 
1297
    goto err;
 
1298
  return(0);
 
1299
err:
 
1300
  return(1);
1348
1301
}
1349
1302
 
1350
1303
 
1377
1330
  if (row_count++ > 1)
1378
1331
  {
1379
1332
    my_message(ER_TOO_MANY_ROWS, ER(ER_TOO_MANY_ROWS), MYF(0));
1380
 
    return 1;
 
1333
    goto err;
1381
1334
  }
1382
1335
  while ((item=li++))
1383
1336
  {
1385
1338
    if (!res)                                   // If NULL
1386
1339
    {
1387
1340
      if (my_b_write(cache,(unsigned char*) "",1))
1388
 
        return 1;
 
1341
        goto err;
1389
1342
    }
1390
1343
    else if (my_b_write(cache,(unsigned char*) res->ptr(),res->length()))
1391
1344
    {
1392
 
      my_error(ER_ERROR_ON_WRITE, MYF(0), path.file_string().c_str(), errno);
1393
 
      return 1;
 
1345
      my_error(ER_ERROR_ON_WRITE, MYF(0), path, errno);
 
1346
      goto err;
1394
1347
    }
1395
1348
  }
1396
1349
  return(0);
 
1350
err:
 
1351
  return(1);
1397
1352
}
1398
1353
 
1399
1354
 
1451
1406
      switch (val_item->result_type())
1452
1407
      {
1453
1408
      case REAL_RESULT:
1454
 
        op= &select_max_min_finder_subselect::cmp_real;
1455
 
        break;
 
1409
        op= &select_max_min_finder_subselect::cmp_real;
 
1410
        break;
1456
1411
      case INT_RESULT:
1457
 
        op= &select_max_min_finder_subselect::cmp_int;
1458
 
        break;
 
1412
        op= &select_max_min_finder_subselect::cmp_int;
 
1413
        break;
1459
1414
      case STRING_RESULT:
1460
 
        op= &select_max_min_finder_subselect::cmp_str;
1461
 
        break;
 
1415
        op= &select_max_min_finder_subselect::cmp_str;
 
1416
        break;
1462
1417
      case DECIMAL_RESULT:
1463
1418
        op= &select_max_min_finder_subselect::cmp_decimal;
1464
1419
        break;
1465
1420
      case ROW_RESULT:
1466
1421
        // This case should never be choosen
1467
 
        assert(0);
1468
 
        op= 0;
 
1422
        assert(0);
 
1423
        op= 0;
1469
1424
      }
1470
1425
    }
1471
1426
    cache->store(val_item);
1554
1509
void Session::end_statement()
1555
1510
{
1556
1511
  /* Cleanup SQL processing state to reuse this statement in next query. */
1557
 
  lex->end();
1558
 
  query_cache_key= ""; // reset the cache key
1559
 
  resetResultsetMessage();
 
1512
  lex_end(lex);
1560
1513
}
1561
1514
 
1562
1515
bool Session::copy_db_to(char **p_db, size_t *p_db_length)
1563
1516
{
1564
 
  assert(_schema);
1565
 
  if (_schema and _schema->empty())
1566
 
  {
1567
 
    my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
1568
 
    return true;
1569
 
  }
1570
 
  else if (not _schema)
1571
 
  {
1572
 
    my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
1573
 
    return true;
1574
 
  }
1575
 
  assert(_schema);
1576
 
 
1577
 
  *p_db= strmake(_schema->c_str(), _schema->size());
1578
 
  *p_db_length= _schema->size();
1579
 
 
 
1517
  if (db.empty())
 
1518
  {
 
1519
    my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
 
1520
    return true;
 
1521
  }
 
1522
  *p_db= strmake(db.c_str(), db.length());
 
1523
  *p_db_length= db.length();
1580
1524
  return false;
1581
1525
}
1582
1526
 
1616
1560
}
1617
1561
 
1618
1562
 
1619
 
void Session::set_db(const std::string &new_db)
 
1563
bool Session::set_db(const std::string &new_db)
1620
1564
{
1621
1565
  /* Do not reallocate memory if current chunk is big enough. */
1622
1566
  if (new_db.length())
1623
 
  {
1624
 
    _schema.reset(new std::string(new_db));
1625
 
  }
 
1567
    db= new_db;
1626
1568
  else
1627
 
  {
1628
 
    _schema.reset(new std::string(""));
1629
 
  }
1630
 
}
1631
 
 
 
1569
    db.clear();
 
1570
 
 
1571
  return false;
 
1572
}
 
1573
 
 
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
}
1632
1593
 
1633
1594
/**
1634
1595
  Mark transaction to rollback and mark error as fatal to a sub-statement.
1651
1612
  plugin_sessionvar_cleanup(this);
1652
1613
 
1653
1614
  /* If necessary, log any aborted or unauthorized connections */
1654
 
  if (getKilled() || client->wasAborted())
 
1615
  if (killed || client->wasAborted())
1655
1616
  {
1656
 
    status_var.aborted_threads++;
 
1617
    status_var_increment(current_global_counters.aborted_threads);
1657
1618
  }
1658
1619
 
1659
1620
  if (client->wasAborted())
1660
1621
  {
1661
 
    if (not getKilled() && variables.log_warnings > 1)
 
1622
    if (! killed && variables.log_warnings > 1)
1662
1623
    {
1663
1624
      SecurityContext *sctx= &security_ctx;
1664
1625
 
1665
1626
      errmsg_printf(ERRMSG_LVL_WARN, ER(ER_NEW_ABORTING_CONNECTION)
1666
1627
                  , thread_id
1667
 
                  , (_schema->empty() ? "unconnected" : _schema->c_str())
 
1628
                  , (db.empty() ? "unconnected" : db.c_str())
1668
1629
                  , sctx->getUser().empty() == false ? sctx->getUser().c_str() : "unauthenticated"
1669
1630
                  , sctx->getIp().c_str()
1670
1631
                  , (main_da.is_error() ? main_da.message() : ER(ER_UNKNOWN_ERROR)));
1673
1634
 
1674
1635
  /* Close out our connection to the client */
1675
1636
  if (should_lock)
1676
 
    session::Cache::singleton().mutex().lock();
1677
 
 
1678
 
  setKilled(Session::KILL_CONNECTION);
1679
 
 
 
1637
    (void) pthread_mutex_lock(&LOCK_thread_count);
 
1638
  killed= Session::KILL_CONNECTION;
1680
1639
  if (client->isConnected())
1681
1640
  {
1682
1641
    if (errcode)
1686
1645
    }
1687
1646
    client->close();
1688
1647
  }
1689
 
 
1690
1648
  if (should_lock)
1691
 
  {
1692
 
    session::Cache::singleton().mutex().unlock();
1693
 
  }
 
1649
    (void) pthread_mutex_unlock(&LOCK_thread_count);
1694
1650
}
1695
1651
 
1696
1652
void Session::reset_for_next_command()
1718
1674
  Close all temporary tables created by 'CREATE TEMPORARY TABLE' for thread
1719
1675
*/
1720
1676
 
1721
 
void Open_tables_state::close_temporary_tables()
 
1677
void Session::close_temporary_tables()
1722
1678
{
1723
1679
  Table *table;
1724
1680
  Table *tmp_next;
1728
1684
 
1729
1685
  for (table= temporary_tables; table; table= tmp_next)
1730
1686
  {
1731
 
    tmp_next= table->getNext();
 
1687
    tmp_next= table->next;
1732
1688
    nukeTable(table);
1733
1689
  }
1734
1690
  temporary_tables= NULL;
1738
1694
  unlink from session->temporary tables and close temporary table
1739
1695
*/
1740
1696
 
1741
 
void Open_tables_state::close_temporary_table(Table *table)
 
1697
void Session::close_temporary_table(Table *table)
1742
1698
{
1743
 
  if (table->getPrev())
 
1699
  if (table->prev)
1744
1700
  {
1745
 
    table->getPrev()->setNext(table->getNext());
1746
 
    if (table->getPrev()->getNext())
1747
 
    {
1748
 
      table->getNext()->setPrev(table->getPrev());
1749
 
    }
 
1701
    table->prev->next= table->next;
 
1702
    if (table->prev->next)
 
1703
      table->next->prev= table->prev;
1750
1704
  }
1751
1705
  else
1752
1706
  {
1757
1711
      passing non-zero value to end_slave via rli->save_temporary_tables
1758
1712
      when no temp tables opened, see an invariant below.
1759
1713
    */
1760
 
    temporary_tables= table->getNext();
 
1714
    temporary_tables= table->next;
1761
1715
    if (temporary_tables)
1762
 
    {
1763
 
      table->getNext()->setPrev(NULL);
1764
 
    }
 
1716
      table->next->prev= NULL;
1765
1717
  }
1766
1718
  nukeTable(table);
1767
1719
}
1774
1726
  If this is needed, use close_temporary_table()
1775
1727
*/
1776
1728
 
1777
 
void Open_tables_state::nukeTable(Table *table)
 
1729
void Session::nukeTable(Table *table)
1778
1730
{
1779
1731
  plugin::StorageEngine *table_type= table->getShare()->db_type();
1780
1732
 
1781
1733
  table->free_io_cache();
1782
 
  table->delete_table();
 
1734
  table->delete_table(false);
1783
1735
 
1784
1736
  TableIdentifier identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName(), table->getShare()->getPath());
1785
1737
  rm_temporary_table(table_type, identifier);
1787
1739
  delete table->getMutableShare();
1788
1740
 
1789
1741
  /* This makes me sad, but we're allocating it via malloc */
1790
 
  delete table;
 
1742
  free(table);
1791
1743
}
1792
1744
 
1793
1745
/** Clear most status variables. */
1795
1747
 
1796
1748
void Session::refresh_status()
1797
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
 
1798
1755
  /* Reset thread's status variables */
1799
1756
  memset(&status_var, 0, sizeof(status_var));
1800
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();
1801
1763
  flush_status_time= time((time_t*) 0);
1802
1764
  current_global_counters.max_used_connections= 1; /* We set it to one, because we know we exist */
1803
 
  current_global_counters.connections= 0;
 
1765
  pthread_mutex_unlock(&LOCK_status);
1804
1766
}
1805
1767
 
1806
1768
user_var_entry *Session::getVariable(LEX_STRING &name, bool create_if_not_exists)
1807
1769
{
1808
 
  return getVariable(std::string(name.str, name.length), create_if_not_exists);
1809
 
}
1810
 
 
1811
 
user_var_entry *Session::getVariable(const std::string  &name, bool create_if_not_exists)
1812
 
{
1813
 
  UserVarsRange ppp= user_vars.equal_range(name);
1814
 
 
1815
 
  for (UserVars::iterator iter= ppp.first;
1816
 
       iter != ppp.second; ++iter)
1817
 
  {
1818
 
    return (*iter).second;
1819
 
  }
1820
 
 
1821
 
  if (not create_if_not_exists)
1822
 
    return NULL;
1823
 
 
1824
1770
  user_var_entry *entry= NULL;
1825
 
  entry= new (nothrow) user_var_entry(name.c_str(), query_id);
1826
 
 
1827
 
  if (entry == NULL)
1828
 
    return NULL;
1829
 
 
1830
 
  std::pair<UserVars::iterator, bool> returnable= user_vars.insert(make_pair(name, entry));
1831
 
 
1832
 
  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)
1833
1775
  {
1834
 
    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
 
1835
1790
  }
1836
1791
 
1837
1792
  return entry;
1838
1793
}
1839
1794
 
1840
 
void Session::setVariable(const std::string &name, const std::string &value)
1841
 
{
1842
 
  user_var_entry *updateable_var= getVariable(name.c_str(), true);
1843
 
 
1844
 
  updateable_var->update_hash(false,
1845
 
                              (void*)value.c_str(),
1846
 
                              static_cast<uint32_t>(value.length()), STRING_RESULT,
1847
 
                              &my_charset_bin,
1848
 
                              DERIVATION_IMPLICIT, false);
1849
 
}
1850
 
 
1851
 
void Open_tables_state::mark_temp_tables_as_free_for_reuse()
1852
 
{
1853
 
  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)
1854
1798
  {
1855
 
    if (table->query_id == getQueryId())
 
1799
    if (table->query_id == query_id)
1856
1800
    {
1857
1801
      table->query_id= 0;
1858
1802
      table->cursor->ha_reset();
1862
1806
 
1863
1807
void Session::mark_used_tables_as_free_for_reuse(Table *table)
1864
1808
{
1865
 
  for (; table ; table= table->getNext())
 
1809
  for (; table ; table= table->next)
1866
1810
  {
1867
 
    if (table->query_id == getQueryId())
 
1811
    if (table->query_id == query_id)
1868
1812
    {
1869
1813
      table->query_id= 0;
1870
1814
      table->cursor->ha_reset();
1883
1827
*/
1884
1828
void Session::close_thread_tables()
1885
1829
{
1886
 
  clearDerivedTables();
 
1830
  if (derived_tables)
 
1831
    derived_tables= NULL; // They should all be invalid by this point
1887
1832
 
1888
1833
  /*
1889
1834
    Mark all temporary tables used by this statement as free for reuse.
1916
1861
      handled either before writing a query log event (inside
1917
1862
      binlog_query()) or when preparing a pending event.
1918
1863
     */
1919
 
    unlockTables(lock);
 
1864
    mysql_unlock_tables(this, lock);
1920
1865
    lock= 0;
1921
1866
  }
1922
1867
  /*
1923
 
    Note that we need to hold table::Cache::singleton().mutex() while changing the
 
1868
    Note that we need to hold LOCK_open while changing the
1924
1869
    open_tables list. Another thread may work on it.
1925
 
    (See: table::Cache::singleton().removeTable(), mysql_wait_completed_table())
 
1870
    (See: remove_table_from_cache(), mysql_wait_completed_table())
1926
1871
    Closing a MERGE child before the parent would be fatal if the
1927
1872
    other thread tries to abort the MERGE lock in between.
1928
1873
  */
1961
1906
    close_tables_for_reopen(&tables);
1962
1907
  }
1963
1908
  if ((mysql_handle_derived(lex, &mysql_derived_prepare) ||
1964
 
       (
 
1909
       (fill_derived_tables() &&
1965
1910
        mysql_handle_derived(lex, &mysql_derived_filling))))
1966
1911
    return true;
1967
1912
 
1968
1913
  return false;
1969
1914
}
1970
1915
 
1971
 
/*
1972
 
  @note "best_effort" is used in cases were if a failure occurred on this
1973
 
  operation it would not be surprising because we are only removing because there
1974
 
  might be an issue (lame engines).
1975
 
*/
 
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
}
1976
1926
 
1977
 
bool Open_tables_state::rm_temporary_table(const TableIdentifier &identifier, bool best_effort)
 
1927
bool Session::rm_temporary_table(TableIdentifier &identifier)
1978
1928
{
1979
 
  if (plugin::StorageEngine::dropTable(*static_cast<Session *>(this), identifier))
 
1929
  if (plugin::StorageEngine::dropTable(*this, identifier))
1980
1930
  {
1981
 
    if (not best_effort)
1982
 
    {
1983
 
      std::string path;
1984
 
      identifier.getSQLPath(path);
1985
 
      errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
1986
 
                    path.c_str(), errno);
1987
 
    }
 
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()");
1988
1934
 
1989
1935
    return true;
1990
1936
  }
1992
1938
  return false;
1993
1939
}
1994
1940
 
1995
 
bool Open_tables_state::rm_temporary_table(plugin::StorageEngine *base, const TableIdentifier &identifier)
 
1941
bool Session::rm_temporary_table(plugin::StorageEngine *base, TableIdentifier &identifier)
1996
1942
{
1997
1943
  assert(base);
1998
1944
 
1999
 
  if (plugin::StorageEngine::dropTable(*static_cast<Session *>(this), *base, identifier))
 
1945
  if (plugin::StorageEngine::dropTable(*this, *base, identifier))
2000
1946
  {
2001
 
    std::string path;
2002
 
    identifier.getSQLPath(path);
2003
1947
    errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
2004
 
                  path.c_str(), errno);
 
1948
                  identifier.getSQLPath().c_str(), errno);
 
1949
    dumpTemporaryTableNames("rm_temporary_table()");
2005
1950
 
2006
1951
    return true;
2007
1952
  }
2013
1958
  @note this will be removed, I am looking through Hudson to see if it is finding
2014
1959
  any tables that are missed during cleanup.
2015
1960
*/
2016
 
void Open_tables_state::dumpTemporaryTableNames(const char *foo)
 
1961
void Session::dumpTemporaryTableNames(const char *foo)
2017
1962
{
2018
1963
  Table *table;
2019
1964
 
2021
1966
    return;
2022
1967
 
2023
1968
  cerr << "Begin Run: " << foo << "\n";
2024
 
  for (table= temporary_tables; table; table= table->getNext())
 
1969
  for (table= temporary_tables; table; table= table->next)
2025
1970
  {
2026
1971
    bool have_proto= false;
2027
1972
 
2037
1982
      cerr << "\t\t Proto " << proto->schema() << " " << proto->name() << "\n";
2038
1983
    }
2039
1984
    else
2040
 
    {
2041
1985
      cerr << "\tTabl;e Name " << table->getShare()->getSchemaName() << "." << table->getShare()->getTableName() << " : " << answer << "\n";
2042
 
    }
2043
1986
  }
2044
1987
}
2045
1988
 
2046
 
bool Session::TableMessages::storeTableMessage(const TableIdentifier &identifier, message::Table &table_message)
 
1989
bool Session::storeTableMessage(TableIdentifier &identifier, message::Table &table_message)
2047
1990
{
2048
1991
  table_message_cache.insert(make_pair(identifier.getPath(), table_message));
2049
1992
 
2050
1993
  return true;
2051
1994
}
2052
1995
 
2053
 
bool Session::TableMessages::removeTableMessage(const TableIdentifier &identifier)
 
1996
bool Session::removeTableMessage(TableIdentifier &identifier)
2054
1997
{
2055
1998
  TableMessageCache::iterator iter;
2056
1999
 
2064
2007
  return true;
2065
2008
}
2066
2009
 
2067
 
bool Session::TableMessages::getTableMessage(const TableIdentifier &identifier, message::Table &table_message)
 
2010
bool Session::getTableMessage(TableIdentifier &identifier, message::Table &table_message)
2068
2011
{
2069
2012
  TableMessageCache::iterator iter;
2070
2013
 
2078
2021
  return true;
2079
2022
}
2080
2023
 
2081
 
bool Session::TableMessages::doesTableMessageExist(const TableIdentifier &identifier)
 
2024
bool Session::doesTableMessageExist(TableIdentifier &identifier)
2082
2025
{
2083
2026
  TableMessageCache::iterator iter;
2084
2027
 
2092
2035
  return true;
2093
2036
}
2094
2037
 
2095
 
bool Session::TableMessages::renameTableMessage(const TableIdentifier &from, const TableIdentifier &to)
 
2038
bool Session::renameTableMessage(TableIdentifier &from, TableIdentifier &to)
2096
2039
{
2097
2040
  TableMessageCache::iterator iter;
2098
2041
 
2111
2054
  return true;
2112
2055
}
2113
2056
 
2114
 
table::Instance *Session::getInstanceTable()
2115
 
{
2116
 
  temporary_shares.push_back(new table::Instance()); // This will not go into the tableshare cache, so no key is used.
2117
 
 
2118
 
  table::Instance *tmp_share= temporary_shares.back();
2119
 
 
2120
 
  assert(tmp_share);
2121
 
 
2122
 
  return tmp_share;
2123
 
}
2124
 
 
2125
 
 
2126
 
/**
2127
 
  Create a reduced Table object with properly set up Field list from a
2128
 
  list of field definitions.
2129
 
 
2130
 
    The created table doesn't have a table Cursor associated with
2131
 
    it, has no keys, no group/distinct, no copy_funcs array.
2132
 
    The sole purpose of this Table object is to use the power of Field
2133
 
    class to read/write data to/from table->getInsertRecord(). Then one can store
2134
 
    the record in any container (RB tree, hash, etc).
2135
 
    The table is created in Session mem_root, so are the table's fields.
2136
 
    Consequently, if you don't BLOB fields, you don't need to free it.
2137
 
 
2138
 
  @param session         connection handle
2139
 
  @param field_list  list of column definitions
2140
 
 
2141
 
  @return
2142
 
    0 if out of memory, Table object in case of success
2143
 
*/
2144
 
table::Instance *Session::getInstanceTable(List<CreateField> &field_list)
2145
 
{
2146
 
  temporary_shares.push_back(new table::Instance(this, field_list)); // This will not go into the tableshare cache, so no key is used.
2147
 
 
2148
 
  table::Instance *tmp_share= temporary_shares.back();
2149
 
 
2150
 
  assert(tmp_share);
2151
 
 
2152
 
  return tmp_share;
2153
 
}
2154
 
 
2155
 
namespace display  {
2156
 
 
2157
 
static const std::string NONE= "NONE";
2158
 
static const std::string GOT_GLOBAL_READ_LOCK= "HAS GLOBAL READ LOCK";
2159
 
static const std::string MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT= "HAS GLOBAL READ LOCK WITH BLOCKING COMMIT";
2160
 
 
2161
 
const std::string &type(drizzled::Session::global_read_lock_t type)
2162
 
{
2163
 
  switch (type) {
2164
 
    default:
2165
 
    case Session::NONE:
2166
 
      return NONE;
2167
 
    case Session::GOT_GLOBAL_READ_LOCK:
2168
 
      return GOT_GLOBAL_READ_LOCK;
2169
 
    case Session::MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT:
2170
 
      return MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT;
2171
 
  }
2172
 
}
2173
 
 
2174
 
size_t max_string_length(drizzled::Session::global_read_lock_t)
2175
 
{
2176
 
  return MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT.size();
2177
 
}
2178
 
 
2179
 
} /* namespace display */
 
2057
TableShareInstance *Session::getTemporaryShare()
 
2058
{
 
2059
  temporary_shares.push_back(new TableShareInstance()); // This will not go into the tableshare cache, so no key is used.
 
2060
 
 
2061
  TableShareInstance *tmp_share= temporary_shares.back();
 
2062
 
 
2063
  assert(tmp_share);
 
2064
 
 
2065
  return tmp_share;
 
2066
}
 
2067
 
 
2068
TableShareInstance *Session::getTemporaryShare(const char *tmpname_arg)
 
2069
{
 
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();
 
2075
 
 
2076
  assert(tmp_share);
 
2077
 
 
2078
  return tmp_share;
 
2079
}
2180
2080
 
2181
2081
} /* namespace drizzled */