~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/session.cc

  • Committer: Prafulla Tekawade
  • Date: 2010-07-18 03:36:32 UTC
  • mto: (1662.1.4 rollup)
  • mto: This revision was merged to the branch mainline in revision 1664.
  • Revision ID: prafulla_t@users.sourceforge.net-20100718033632-p7q6qtgliqbhe38p
Fix for Bug 592444

There were two problems:
o. In greedy_search optimizer method, best_extension_by_limited search
   maintains join embedding(nestedness) of tables added so far, so that 
   correct(valid)  join order is selected
   These are requirements from nested outer join executioner.
   The problem was, embedding_map was not correctly updated when a table 
   is added to optimal plan outside best_extension_by_limited search, 
   by greedy_search method. We need to update join->cur_embedding_map
   correctly here so that execution plan for other tables get
   generated.
   Invoked checked_interleaving_with_nj from greedy_search on the
   best_table selected. Fixed its prototype to take only one JoinTab
   This is same as mysql 5.1 source tree.
o. The other problem was, join->cur_embedding_map was not restored correctly
   when a table is added to the optimal plan to reflect the current embedding 
   map. 
   Taken good documented method restore_prev_nj_state which restores 
   cur_embedding_map from mysql 5.1 source tree and modified it for drizzled 
   code.

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
  /*
205
206
  memory::init_sql_alloc(&main_mem_root, memory::ROOT_MIN_BLOCK_SIZE, 0);
206
207
  thread_stack= NULL;
207
208
  count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
 
209
  killed= NOT_KILLED;
208
210
  col_access= 0;
209
211
  tmp_table= 0;
210
212
  used_tables= 0;
224
226
  mysys_var= 0;
225
227
  scoreboard_index= -1;
226
228
  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;
 
229
  cleanup_done= abort_on_warning= no_warnings_for_error= false;
 
230
  pthread_mutex_init(&LOCK_delete, MY_MUTEX_INIT_FAST);
232
231
 
233
232
  /* Variables with default values */
234
233
  proc_info="login";
260
259
 
261
260
  /* Initialize sub structures */
262
261
  memory::init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
 
262
  hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
 
263
            (hash_get_key) get_var_key,
 
264
            (hash_free_key) free_user_var, 0);
263
265
 
264
266
  substitute_null_with_insert_id = false;
265
 
  lock_info.init(); /* safety: will be reset after start */
 
267
  thr_lock_info_init(&lock_info); /* safety: will be reset after start */
266
268
  thr_lock_owner_init(&main_lock_id, &lock_info);
267
269
 
268
270
  m_internal_handler= NULL;
302
304
  return false;                                 // 'false', as per coding style
303
305
}
304
306
 
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
307
void Session::pop_internal_handler()
326
308
{
327
309
  assert(m_internal_handler != NULL);
339
321
{
340
322
  assert(cleanup_done == false);
341
323
 
342
 
  setKilled(KILL_CONNECTION);
 
324
  killed= KILL_CONNECTION;
343
325
#ifdef ENABLE_WHEN_BINLOG_WILL_BE_ABLE_TO_PREPARE
344
326
  if (transaction.xid_state.xa_state == XA_PREPARED)
345
327
  {
351
333
    transaction_services.rollbackTransaction(this, true);
352
334
    xid_cache_delete(&transaction.xid_state);
353
335
  }
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
 
 
 
336
  hash_free(&user_vars);
365
337
  close_temporary_tables();
366
338
 
367
339
  if (global_read_lock)
368
 
  {
369
 
    unlockGlobalReadLock();
370
 
  }
 
340
    unlock_global_read_lock(this);
371
341
 
372
342
  cleanup_done= true;
373
343
}
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
void Session::awake(Session::killed_state state_to_set)
 
385
{
428
386
  this->checkSentry();
429
 
 
430
 
  setKilled(state_to_set);
431
 
  scheduler->killSession(this);
432
 
 
 
387
  safe_mutex_assert_owner(&LOCK_delete);
 
388
 
 
389
  killed= state_to_set;
433
390
  if (state_to_set != Session::KILL_QUERY)
434
391
  {
 
392
    scheduler->killSession(this);
435
393
    DRIZZLE_CONNECTION_DONE(thread_id);
436
394
  }
437
 
 
438
395
  if (mysys_var)
439
396
  {
440
 
    boost_unique_lock_t scopedLock(mysys_var->mutex);
 
397
    pthread_mutex_lock(&mysys_var->mutex);
441
398
    /*
442
 
      "
443
399
      This broadcast could be up in the air if the victim thread
444
400
      exits the cond in the time between read and broadcast, but that is
445
401
      ok since all we want to do is to make the victim thread get out
460
416
    */
461
417
    if (mysys_var->current_cond && mysys_var->current_mutex)
462
418
    {
463
 
      mysys_var->current_mutex->lock();
464
 
      mysys_var->current_cond->notify_all();
465
 
      mysys_var->current_mutex->unlock();
 
419
      pthread_mutex_lock(mysys_var->current_mutex);
 
420
      pthread_cond_broadcast(mysys_var->current_cond);
 
421
      pthread_mutex_unlock(mysys_var->current_mutex);
466
422
    }
 
423
    pthread_mutex_unlock(&mysys_var->mutex);
467
424
  }
468
425
}
469
426
 
479
436
  */
480
437
  assert(thread_stack);
481
438
 
482
 
  currentSession().release();
483
 
  currentSession().reset(this);
484
 
 
485
 
  currentMemRoot().release();
486
 
  currentMemRoot().reset(&mem_root);
 
439
  if (pthread_setspecific(THR_Session,  this) ||
 
440
      pthread_setspecific(THR_Mem_root, &mem_root))
 
441
    return true;
487
442
 
488
443
  mysys_var=my_thread_var;
489
444
 
492
447
    This allows us to move Session to different threads if needed.
493
448
  */
494
449
  mysys_var->id= thread_id;
 
450
  real_id= pthread_self();                      // For debugging
495
451
 
496
452
  /*
497
453
    We have to call thr_lock_info_init() again here as Session may have been
498
454
    created in another thread
499
455
  */
500
 
  lock_info.init();
501
 
 
 
456
  thr_lock_info_init(&lock_info);
502
457
  return false;
503
458
}
504
459
 
522
477
                                variables.query_prealloc_size);
523
478
  transaction.xid_state.xid.null();
524
479
  transaction.xid_state.in_session=1;
525
 
  if (use_usage)
526
 
    resetUsage();
527
480
}
528
481
 
529
482
bool Session::initGlobals()
531
484
  if (storeGlobals())
532
485
  {
533
486
    disconnect(ER_OUT_OF_RESOURCES, true);
534
 
    status_var.aborted_connects++;
 
487
    status_var_increment(status_var.aborted_connects); 
535
488
    return true;
536
489
  }
537
490
  return false;
547
500
 
548
501
  prepareForQueries();
549
502
 
550
 
  while (not client->haveError() && getKilled() != KILL_CONNECTION)
 
503
  while (! client->haveError() && killed != KILL_CONNECTION)
551
504
  {
552
 
    if (not executeStatement())
 
505
    if (! executeStatement())
553
506
      break;
554
507
  }
555
508
 
556
509
  disconnect(0, true);
557
510
}
558
511
 
559
 
bool Session::schedule(Session::shared_ptr &arg)
 
512
bool Session::schedule()
560
513
{
561
 
  arg->scheduler= plugin::Scheduler::getScheduler();
562
 
  assert(arg->scheduler);
 
514
  scheduler= plugin::Scheduler::getScheduler();
 
515
  assert(scheduler);
563
516
 
564
517
  connection_count.increment();
565
518
 
568
521
    current_global_counters.max_used_connections= connection_count;
569
522
  }
570
523
 
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());
 
524
  thread_id= variables.pseudo_thread_id= global_thread_id++;
 
525
 
 
526
  pthread_mutex_lock(&LOCK_thread_count);
 
527
  getSessionList().push_back(this);
 
528
  pthread_mutex_unlock(&LOCK_thread_count);
 
529
 
 
530
  if (scheduler->addSession(this))
 
531
  {
 
532
    DRIZZLE_CONNECTION_START(thread_id);
584
533
    char error_message_buff[DRIZZLE_ERRMSG_SIZE];
585
534
 
586
 
    arg->setKilled(Session::KILL_CONNECTION);
 
535
    killed= Session::KILL_CONNECTION;
587
536
 
588
 
    arg->status_var.aborted_connects++;
 
537
    status_var_increment(status_var.aborted_connects);
589
538
 
590
539
    /* Can't use my_error() since store_globals has not been called. */
591
540
    /* TODO replace will better error message */
592
541
    snprintf(error_message_buff, sizeof(error_message_buff),
593
542
             ER(ER_CANT_CREATE_THREAD), 1);
594
 
    arg->client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
595
 
 
 
543
    client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
596
544
    return true;
597
545
  }
598
546
 
600
548
}
601
549
 
602
550
 
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)
 
551
const char* Session::enter_cond(pthread_cond_t *cond,
 
552
                                pthread_mutex_t* mutex,
 
553
                                const char* msg)
615
554
{
616
555
  const char* old_msg = get_proc_info();
617
556
  safe_mutex_assert_owner(mutex);
618
 
  mysys_var->current_mutex = &mutex;
619
 
  mysys_var->current_cond = &cond;
 
557
  mysys_var->current_mutex = mutex;
 
558
  mysys_var->current_cond = cond;
620
559
  this->set_proc_info(msg);
621
560
  return old_msg;
622
561
}
629
568
    locked (if that would not be the case, you'll get a deadlock if someone
630
569
    does a Session::awake() on you).
631
570
  */
632
 
  mysys_var->current_mutex->unlock();
633
 
  boost_unique_lock_t scopedLock(mysys_var->mutex);
 
571
  pthread_mutex_unlock(mysys_var->current_mutex);
 
572
  pthread_mutex_lock(&mysys_var->mutex);
634
573
  mysys_var->current_mutex = 0;
635
574
  mysys_var->current_cond = 0;
636
575
  this->set_proc_info(old_msg);
 
576
  pthread_mutex_unlock(&mysys_var->mutex);
637
577
}
638
578
 
639
579
bool Session::authenticate()
640
580
{
641
 
  lex->start(this);
 
581
  lex_start(this);
642
582
  if (client->authenticate())
643
583
    return false;
644
584
 
645
 
  status_var.aborted_connects++;
 
585
  status_var_increment(status_var.aborted_connects); 
646
586
 
647
587
  return true;
648
588
}
649
589
 
650
 
bool Session::checkUser(const std::string &passwd_str,
651
 
                        const std::string &in_db)
 
590
bool Session::checkUser(const char *passwd, uint32_t passwd_len, const char *in_db)
652
591
{
 
592
  const string passwd_str(passwd, passwd_len);
653
593
  bool is_authenticated=
654
594
    plugin::Authentication::isAuthenticated(getSecurityContext(),
655
595
                                            passwd_str);
656
596
 
657
597
  if (is_authenticated != true)
658
598
  {
659
 
    status_var.access_denied++;
 
599
    status_var_increment(status_var.access_denied);
660
600
    /* isAuthenticated has pushed the error message */
661
601
    return false;
662
602
  }
663
603
 
664
604
  /* Change database if necessary */
665
 
  if (not in_db.empty())
 
605
  if (in_db && in_db[0])
666
606
  {
667
607
    SchemaIdentifier identifier(in_db);
668
608
    if (mysql_change_db(this, identifier))
672
612
    }
673
613
  }
674
614
  my_ok();
675
 
  password= not passwd_str.empty();
 
615
  password= test(passwd_len);          // remember for error messages
676
616
 
677
617
  /* Ready to handle queries */
678
618
  return true;
694
634
  main_da.reset_diagnostics_area();
695
635
 
696
636
  if (client->readCommand(&l_packet, &packet_length) == false)
697
 
  {
698
 
    return false;
699
 
  }
700
 
 
701
 
  if (getKilled() == KILL_CONNECTION)
702
637
    return false;
703
638
 
704
639
  if (packet_length == 0)
705
640
    return true;
706
641
 
707
 
  l_command= static_cast<enum_server_command>(l_packet[0]);
 
642
  l_command= (enum enum_server_command) (unsigned char) l_packet[0];
708
643
 
709
644
  if (command >= COM_END)
710
645
    command= COM_END;                           // Wrong command
711
646
 
712
647
  assert(packet_length);
713
 
  return not dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
 
648
  return ! dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
714
649
}
715
650
 
716
651
bool Session::readAndStoreQuery(const char *in_packet, uint32_t in_packet_length)
722
657
    in_packet_length--;
723
658
  }
724
659
  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])))
 
660
  while (in_packet_length > 0 &&
 
661
         (pos[-1] == ';' || my_isspace(charset() ,pos[-1])))
726
662
  {
727
663
    pos--;
728
664
    in_packet_length--;
729
665
  }
730
666
 
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));
 
667
  query.assign(in_packet, in_packet + in_packet_length);
739
668
 
740
669
  return true;
741
670
}
790
719
  }
791
720
 
792
721
  if (result == false)
793
 
  {
794
722
    my_error(killed_errno(), MYF(0));
795
 
  }
796
723
  else if ((result == true) && do_release)
797
 
  {
798
 
    setKilled(Session::KILL_CONNECTION);
799
 
  }
 
724
    killed= Session::KILL_CONNECTION;
800
725
 
801
726
  return result;
802
727
}
867
792
  where= Session::DEFAULT_WHERE;
868
793
 
869
794
  /* Reset the temporary shares we built */
870
 
  for_each(temporary_shares.begin(),
871
 
           temporary_shares.end(),
872
 
           DeletePtr());
 
795
  for (std::vector<TableShareInstance *>::iterator iter= temporary_shares.begin();
 
796
       iter != temporary_shares.end(); iter++)
 
797
  {
 
798
    delete *iter;
 
799
  }
873
800
  temporary_shares.clear();
874
801
}
875
802
 
955
882
  my_message(errcode, err, MYF(0));
956
883
  if (file > 0)
957
884
  {
958
 
    (void) cache->end_io_cache();
 
885
    (void) end_io_cache(cache);
959
886
    (void) internal::my_close(file, MYF(0));
960
 
    (void) internal::my_delete(path.file_string().c_str(), MYF(0));             // Delete file on error
 
887
    (void) internal::my_delete(path, MYF(0));           // Delete file on error
961
888
    file= -1;
962
889
  }
963
890
}
965
892
 
966
893
bool select_to_file::send_eof()
967
894
{
968
 
  int error= test(cache->end_io_cache());
 
895
  int error= test(end_io_cache(cache));
969
896
  if (internal::my_close(file, MYF(MY_WME)))
970
897
    error= 1;
971
898
  if (!error)
987
914
  /* In case of error send_eof() may be not called: close the file here. */
988
915
  if (file >= 0)
989
916
  {
990
 
    (void) cache->end_io_cache();
 
917
    (void) end_io_cache(cache);
991
918
    (void) internal::my_close(file, MYF(0));
992
919
    file= -1;
993
920
  }
994
 
  path= "";
 
921
  path[0]= '\0';
995
922
  row_count= 0;
996
923
}
997
924
 
1001
928
    cache(static_cast<internal::IO_CACHE *>(memory::sql_calloc(sizeof(internal::IO_CACHE)))),
1002
929
    row_count(0L)
1003
930
{
1004
 
  path= "";
 
931
  path[0]=0;
1005
932
}
1006
933
 
1007
934
select_to_file::~select_to_file()
1035
962
*/
1036
963
 
1037
964
 
1038
 
static int create_file(Session *session,
1039
 
                       fs::path &target_path,
1040
 
                       file_exchange *exchange,
1041
 
                       internal::IO_CACHE *cache)
 
965
static int create_file(Session *session, char *path, file_exchange *exchange, internal::IO_CACHE *cache)
1042
966
{
1043
 
  fs::path to_file(exchange->file_name);
1044
967
  int file;
1045
 
 
1046
 
  if (not to_file.has_root_directory())
 
968
  uint32_t option= MY_UNPACK_FILENAME | MY_RELATIVE_PATH;
 
969
 
 
970
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
 
971
  option|= MY_REPLACE_DIR;                      // Force use of db directory
 
972
#endif
 
973
 
 
974
  if (!internal::dirname_length(exchange->file_name))
1047
975
  {
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;
 
976
    strcpy(path, data_home_real);
 
977
    if (! session->db.empty())
 
978
      strncat(path, session->db.c_str(), FN_REFLEN-strlen(data_home_real)-1);
 
979
    (void) internal::fn_format(path, exchange->file_name, path, "", option);
1064
980
  }
1065
981
  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))
 
982
    (void) internal::fn_format(path, exchange->file_name, data_home_real, "", option);
 
983
 
 
984
  if (opt_secure_file_priv &&
 
985
      strncmp(opt_secure_file_priv, path, strlen(opt_secure_file_priv)))
 
986
  {
 
987
    /* Write only allowed to dir or subdir specified by secure_file_priv */
 
988
    my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
 
989
    return -1;
 
990
  }
 
991
 
 
992
  if (!access(path, F_OK))
1081
993
  {
1082
994
    my_error(ER_FILE_EXISTS_ERROR, MYF(0), exchange->file_name);
1083
995
    return -1;
1084
996
  }
1085
997
  /* 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)
 
998
  if ((file= internal::my_create(path, 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
1087
999
    return file;
1088
1000
  (void) fchmod(file, 0666);                    // Because of umask()
1089
 
  if (cache->init_io_cache(file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
 
1001
  if (init_io_cache(cache, file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1090
1002
  {
1091
1003
    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
 
1004
    internal::my_delete(path, MYF(0));  // Delete file on error, it was just created
1093
1005
    return -1;
1094
1006
  }
1095
1007
  return file;
1103
1015
  bool string_results= false, non_string_results= false;
1104
1016
  unit= u;
1105
1017
  if ((uint32_t) strlen(exchange->file_name) + NAME_LEN >= FN_REFLEN)
1106
 
  {
1107
 
    path= exchange->file_name;
1108
 
  }
 
1018
    strncpy(path,exchange->file_name,FN_REFLEN-1);
1109
1019
 
1110
1020
  /* Check if there is any blobs in data */
1111
1021
  {
1115
1025
    {
1116
1026
      if (item->max_length >= MAX_BLOB_WIDTH)
1117
1027
      {
1118
 
        blob_flag=1;
1119
 
        break;
 
1028
        blob_flag=1;
 
1029
        break;
1120
1030
      }
1121
 
 
1122
1031
      if (item->result_type() == STRING_RESULT)
1123
1032
        string_results= true;
1124
1033
      else
1169
1078
  if (unit->offset_limit_cnt)
1170
1079
  {                                             // using limit offset,count
1171
1080
    unit->offset_limit_cnt--;
1172
 
    return false;
 
1081
    return(0);
1173
1082
  }
1174
1083
  row_count++;
1175
1084
  Item *item;
1178
1087
 
1179
1088
  if (my_b_write(cache,(unsigned char*) exchange->line_start->ptr(),
1180
1089
                 exchange->line_start->length()))
1181
 
    return true;
1182
 
 
 
1090
    goto err;
1183
1091
  while ((item=li++))
1184
1092
  {
1185
1093
    Item_result result_type=item->result_type();
1190
1098
    {
1191
1099
      if (my_b_write(cache,(unsigned char*) exchange->enclosed->ptr(),
1192
1100
                     exchange->enclosed->length()))
1193
 
        return true;
 
1101
        goto err;
1194
1102
    }
1195
1103
    if (!res)
1196
1104
    {                                           // NULL
1201
1109
          null_buff[0]=escape_char;
1202
1110
          null_buff[1]='N';
1203
1111
          if (my_b_write(cache,(unsigned char*) null_buff,2))
1204
 
            return true;
 
1112
            goto err;
1205
1113
        }
1206
1114
        else if (my_b_write(cache,(unsigned char*) "NULL",4))
1207
 
          return true;
 
1115
          goto err;
1208
1116
      }
1209
1117
      else
1210
1118
      {
1214
1122
    else
1215
1123
    {
1216
1124
      if (fixed_row_size)
1217
 
        used_length= min(res->length(), static_cast<size_t>(item->max_length));
 
1125
        used_length= min(res->length(),item->max_length);
1218
1126
      else
1219
1127
        used_length= res->length();
1220
1128
 
1295
1203
            tmp_buff[1]= *pos ? *pos : '0';
1296
1204
            if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)) ||
1297
1205
                my_b_write(cache,(unsigned char*) tmp_buff,2))
1298
 
              return true;
 
1206
              goto err;
1299
1207
            start=pos+1;
1300
1208
          }
1301
1209
        }
1302
1210
        if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)))
1303
 
          return true;
 
1211
          goto err;
1304
1212
      }
1305
1213
      else if (my_b_write(cache,(unsigned char*) res->ptr(),used_length))
1306
 
        return true;
 
1214
        goto err;
1307
1215
    }
1308
1216
    if (fixed_row_size)
1309
1217
    {                                           // Fill with space
1319
1227
        for (; length > sizeof(space) ; length-=sizeof(space))
1320
1228
        {
1321
1229
          if (my_b_write(cache,(unsigned char*) space,sizeof(space)))
1322
 
            return true;
 
1230
            goto err;
1323
1231
        }
1324
1232
        if (my_b_write(cache,(unsigned char*) space,length))
1325
 
          return true;
 
1233
          goto err;
1326
1234
      }
1327
1235
    }
1328
1236
    if (res && enclosed)
1329
1237
    {
1330
1238
      if (my_b_write(cache, (unsigned char*) exchange->enclosed->ptr(),
1331
1239
                     exchange->enclosed->length()))
1332
 
        return true;
 
1240
        goto err;
1333
1241
    }
1334
1242
    if (--items_left)
1335
1243
    {
1336
1244
      if (my_b_write(cache, (unsigned char*) exchange->field_term->ptr(),
1337
1245
                     field_term_length))
1338
 
        return true;
 
1246
        goto err;
1339
1247
    }
1340
1248
  }
1341
1249
  if (my_b_write(cache,(unsigned char*) exchange->line_term->ptr(),
1342
1250
                 exchange->line_term->length()))
1343
 
  {
1344
 
    return true;
1345
 
  }
1346
 
 
1347
 
  return false;
 
1251
    goto err;
 
1252
  return(0);
 
1253
err:
 
1254
  return(1);
1348
1255
}
1349
1256
 
1350
1257
 
1377
1284
  if (row_count++ > 1)
1378
1285
  {
1379
1286
    my_message(ER_TOO_MANY_ROWS, ER(ER_TOO_MANY_ROWS), MYF(0));
1380
 
    return 1;
 
1287
    goto err;
1381
1288
  }
1382
1289
  while ((item=li++))
1383
1290
  {
1385
1292
    if (!res)                                   // If NULL
1386
1293
    {
1387
1294
      if (my_b_write(cache,(unsigned char*) "",1))
1388
 
        return 1;
 
1295
        goto err;
1389
1296
    }
1390
1297
    else if (my_b_write(cache,(unsigned char*) res->ptr(),res->length()))
1391
1298
    {
1392
 
      my_error(ER_ERROR_ON_WRITE, MYF(0), path.file_string().c_str(), errno);
1393
 
      return 1;
 
1299
      my_error(ER_ERROR_ON_WRITE, MYF(0), path, errno);
 
1300
      goto err;
1394
1301
    }
1395
1302
  }
1396
1303
  return(0);
 
1304
err:
 
1305
  return(1);
1397
1306
}
1398
1307
 
1399
1308
 
1451
1360
      switch (val_item->result_type())
1452
1361
      {
1453
1362
      case REAL_RESULT:
1454
 
        op= &select_max_min_finder_subselect::cmp_real;
1455
 
        break;
 
1363
        op= &select_max_min_finder_subselect::cmp_real;
 
1364
        break;
1456
1365
      case INT_RESULT:
1457
 
        op= &select_max_min_finder_subselect::cmp_int;
1458
 
        break;
 
1366
        op= &select_max_min_finder_subselect::cmp_int;
 
1367
        break;
1459
1368
      case STRING_RESULT:
1460
 
        op= &select_max_min_finder_subselect::cmp_str;
1461
 
        break;
 
1369
        op= &select_max_min_finder_subselect::cmp_str;
 
1370
        break;
1462
1371
      case DECIMAL_RESULT:
1463
1372
        op= &select_max_min_finder_subselect::cmp_decimal;
1464
1373
        break;
1465
1374
      case ROW_RESULT:
1466
1375
        // This case should never be choosen
1467
 
        assert(0);
1468
 
        op= 0;
 
1376
        assert(0);
 
1377
        op= 0;
1469
1378
      }
1470
1379
    }
1471
1380
    cache->store(val_item);
1554
1463
void Session::end_statement()
1555
1464
{
1556
1465
  /* Cleanup SQL processing state to reuse this statement in next query. */
1557
 
  lex->end();
1558
 
  query_cache_key= ""; // reset the cache key
1559
 
  resetResultsetMessage();
 
1466
  lex_end(lex);
1560
1467
}
1561
1468
 
1562
1469
bool Session::copy_db_to(char **p_db, size_t *p_db_length)
1563
1470
{
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
 
 
 
1471
  if (db.empty())
 
1472
  {
 
1473
    my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
 
1474
    return true;
 
1475
  }
 
1476
  *p_db= strmake(db.c_str(), db.length());
 
1477
  *p_db_length= db.length();
1580
1478
  return false;
1581
1479
}
1582
1480
 
1616
1514
}
1617
1515
 
1618
1516
 
1619
 
void Session::set_db(const std::string &new_db)
 
1517
bool Session::set_db(const std::string &new_db)
1620
1518
{
1621
1519
  /* Do not reallocate memory if current chunk is big enough. */
1622
1520
  if (new_db.length())
1623
 
  {
1624
 
    _schema.reset(new std::string(new_db));
1625
 
  }
 
1521
    db= new_db;
1626
1522
  else
1627
 
  {
1628
 
    _schema.reset(new std::string(""));
1629
 
  }
1630
 
}
1631
 
 
 
1523
    db.clear();
 
1524
 
 
1525
  return false;
 
1526
}
 
1527
 
 
1528
 
 
1529
 
 
1530
 
 
1531
/**
 
1532
  Check the killed state of a user thread
 
1533
  @param session  user thread
 
1534
  @retval 0 the user thread is active
 
1535
  @retval 1 the user thread has been killed
 
1536
*/
 
1537
int session_killed(const Session *session)
 
1538
{
 
1539
  return(session->killed);
 
1540
}
 
1541
 
 
1542
 
 
1543
const struct charset_info_st *session_charset(Session *session)
 
1544
{
 
1545
  return(session->charset());
 
1546
}
1632
1547
 
1633
1548
/**
1634
1549
  Mark transaction to rollback and mark error as fatal to a sub-statement.
1651
1566
  plugin_sessionvar_cleanup(this);
1652
1567
 
1653
1568
  /* If necessary, log any aborted or unauthorized connections */
1654
 
  if (getKilled() || client->wasAborted())
 
1569
  if (killed || client->wasAborted())
1655
1570
  {
1656
 
    status_var.aborted_threads++;
 
1571
    status_var_increment(status_var.aborted_threads);
1657
1572
  }
1658
1573
 
1659
1574
  if (client->wasAborted())
1660
1575
  {
1661
 
    if (not getKilled() && variables.log_warnings > 1)
 
1576
    if (! killed && variables.log_warnings > 1)
1662
1577
    {
1663
1578
      SecurityContext *sctx= &security_ctx;
1664
1579
 
1665
1580
      errmsg_printf(ERRMSG_LVL_WARN, ER(ER_NEW_ABORTING_CONNECTION)
1666
1581
                  , thread_id
1667
 
                  , (_schema->empty() ? "unconnected" : _schema->c_str())
 
1582
                  , (db.empty() ? "unconnected" : db.c_str())
1668
1583
                  , sctx->getUser().empty() == false ? sctx->getUser().c_str() : "unauthenticated"
1669
1584
                  , sctx->getIp().c_str()
1670
1585
                  , (main_da.is_error() ? main_da.message() : ER(ER_UNKNOWN_ERROR)));
1673
1588
 
1674
1589
  /* Close out our connection to the client */
1675
1590
  if (should_lock)
1676
 
    session::Cache::singleton().mutex().lock();
1677
 
 
1678
 
  setKilled(Session::KILL_CONNECTION);
1679
 
 
 
1591
    (void) pthread_mutex_lock(&LOCK_thread_count);
 
1592
  killed= Session::KILL_CONNECTION;
1680
1593
  if (client->isConnected())
1681
1594
  {
1682
1595
    if (errcode)
1686
1599
    }
1687
1600
    client->close();
1688
1601
  }
1689
 
 
1690
1602
  if (should_lock)
1691
 
  {
1692
 
    session::Cache::singleton().mutex().unlock();
1693
 
  }
 
1603
    (void) pthread_mutex_unlock(&LOCK_thread_count);
1694
1604
}
1695
1605
 
1696
1606
void Session::reset_for_next_command()
1718
1628
  Close all temporary tables created by 'CREATE TEMPORARY TABLE' for thread
1719
1629
*/
1720
1630
 
1721
 
void Open_tables_state::close_temporary_tables()
 
1631
void Session::close_temporary_tables()
1722
1632
{
1723
1633
  Table *table;
1724
1634
  Table *tmp_next;
1738
1648
  unlink from session->temporary tables and close temporary table
1739
1649
*/
1740
1650
 
1741
 
void Open_tables_state::close_temporary_table(Table *table)
 
1651
void Session::close_temporary_table(Table *table)
1742
1652
{
1743
1653
  if (table->getPrev())
1744
1654
  {
1774
1684
  If this is needed, use close_temporary_table()
1775
1685
*/
1776
1686
 
1777
 
void Open_tables_state::nukeTable(Table *table)
 
1687
void Session::nukeTable(Table *table)
1778
1688
{
1779
1689
  plugin::StorageEngine *table_type= table->getShare()->db_type();
1780
1690
 
1781
1691
  table->free_io_cache();
1782
 
  table->delete_table();
 
1692
  table->delete_table(false);
1783
1693
 
1784
1694
  TableIdentifier identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName(), table->getShare()->getPath());
1785
1695
  rm_temporary_table(table_type, identifier);
1787
1697
  delete table->getMutableShare();
1788
1698
 
1789
1699
  /* This makes me sad, but we're allocating it via malloc */
1790
 
  delete table;
 
1700
  free(table);
1791
1701
}
1792
1702
 
1793
1703
/** Clear most status variables. */
1795
1705
 
1796
1706
void Session::refresh_status()
1797
1707
{
 
1708
  pthread_mutex_lock(&LOCK_status);
 
1709
 
1798
1710
  /* Reset thread's status variables */
1799
1711
  memset(&status_var, 0, sizeof(status_var));
1800
1712
 
 
1713
  /* Reset the counters of all key caches (default and named). */
 
1714
  reset_key_cache_counters();
1801
1715
  flush_status_time= time((time_t*) 0);
1802
1716
  current_global_counters.max_used_connections= 1; /* We set it to one, because we know we exist */
1803
 
  current_global_counters.connections= 0;
 
1717
  pthread_mutex_unlock(&LOCK_status);
1804
1718
}
1805
1719
 
1806
1720
user_var_entry *Session::getVariable(LEX_STRING &name, bool create_if_not_exists)
1807
1721
{
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
1722
  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)
 
1723
 
 
1724
  entry= (user_var_entry*) hash_search(&user_vars, (unsigned char*) name.str, name.length);
 
1725
 
 
1726
  if ((entry == NULL) && create_if_not_exists)
1833
1727
  {
1834
 
    delete entry;
 
1728
    if (!hash_inited(&user_vars))
 
1729
      return NULL;
 
1730
    entry= new (nothrow) user_var_entry(name.str, query_id);
 
1731
 
 
1732
    if (entry == NULL)
 
1733
      return NULL;
 
1734
 
 
1735
    if (my_hash_insert(&user_vars, (unsigned char*) entry))
 
1736
    {
 
1737
      assert(1);
 
1738
      delete entry;
 
1739
      return 0;
 
1740
    }
 
1741
 
1835
1742
  }
1836
1743
 
1837
1744
  return entry;
1838
1745
}
1839
1746
 
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()
 
1747
void Session::mark_temp_tables_as_free_for_reuse()
1852
1748
{
1853
1749
  for (Table *table= temporary_tables ; table ; table= table->getNext())
1854
1750
  {
1855
 
    if (table->query_id == getQueryId())
 
1751
    if (table->query_id == query_id)
1856
1752
    {
1857
1753
      table->query_id= 0;
1858
1754
      table->cursor->ha_reset();
1864
1760
{
1865
1761
  for (; table ; table= table->getNext())
1866
1762
  {
1867
 
    if (table->query_id == getQueryId())
 
1763
    if (table->query_id == query_id)
1868
1764
    {
1869
1765
      table->query_id= 0;
1870
1766
      table->cursor->ha_reset();
1883
1779
*/
1884
1780
void Session::close_thread_tables()
1885
1781
{
1886
 
  clearDerivedTables();
 
1782
  if (derived_tables)
 
1783
    derived_tables= NULL; // They should all be invalid by this point
1887
1784
 
1888
1785
  /*
1889
1786
    Mark all temporary tables used by this statement as free for reuse.
1916
1813
      handled either before writing a query log event (inside
1917
1814
      binlog_query()) or when preparing a pending event.
1918
1815
     */
1919
 
    unlockTables(lock);
 
1816
    mysql_unlock_tables(this, lock);
1920
1817
    lock= 0;
1921
1818
  }
1922
1819
  /*
1923
 
    Note that we need to hold table::Cache::singleton().mutex() while changing the
 
1820
    Note that we need to hold LOCK_open while changing the
1924
1821
    open_tables list. Another thread may work on it.
1925
 
    (See: table::Cache::singleton().removeTable(), mysql_wait_completed_table())
 
1822
    (See: remove_table_from_cache(), mysql_wait_completed_table())
1926
1823
    Closing a MERGE child before the parent would be fatal if the
1927
1824
    other thread tries to abort the MERGE lock in between.
1928
1825
  */
1961
1858
    close_tables_for_reopen(&tables);
1962
1859
  }
1963
1860
  if ((mysql_handle_derived(lex, &mysql_derived_prepare) ||
1964
 
       (
 
1861
       (fill_derived_tables() &&
1965
1862
        mysql_handle_derived(lex, &mysql_derived_filling))))
1966
1863
    return true;
1967
1864
 
1968
1865
  return false;
1969
1866
}
1970
1867
 
 
1868
bool Session::openTables(TableList *tables, uint32_t flags)
 
1869
{
 
1870
  uint32_t counter;
 
1871
  bool ret= fill_derived_tables();
 
1872
  assert(ret == false);
 
1873
  if (open_tables_from_list(&tables, &counter, flags) ||
 
1874
      mysql_handle_derived(lex, &mysql_derived_prepare))
 
1875
  {
 
1876
    return true;
 
1877
  }
 
1878
  return false;
 
1879
}
 
1880
 
1971
1881
/*
1972
1882
  @note "best_effort" is used in cases were if a failure occurred on this
1973
1883
  operation it would not be surprising because we are only removing because there
1974
1884
  might be an issue (lame engines).
1975
1885
*/
1976
1886
 
1977
 
bool Open_tables_state::rm_temporary_table(const TableIdentifier &identifier, bool best_effort)
 
1887
bool Session::rm_temporary_table(TableIdentifier &identifier, bool best_effort)
1978
1888
{
1979
 
  if (plugin::StorageEngine::dropTable(*static_cast<Session *>(this), identifier))
 
1889
  if (plugin::StorageEngine::dropTable(*this, identifier))
1980
1890
  {
1981
1891
    if (not best_effort)
1982
1892
    {
1983
 
      std::string path;
1984
 
      identifier.getSQLPath(path);
1985
1893
      errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
1986
 
                    path.c_str(), errno);
 
1894
                    identifier.getSQLPath().c_str(), errno);
1987
1895
    }
1988
1896
 
1989
1897
    return true;
1992
1900
  return false;
1993
1901
}
1994
1902
 
1995
 
bool Open_tables_state::rm_temporary_table(plugin::StorageEngine *base, const TableIdentifier &identifier)
 
1903
bool Session::rm_temporary_table(plugin::StorageEngine *base, TableIdentifier &identifier)
1996
1904
{
1997
1905
  assert(base);
1998
1906
 
1999
 
  if (plugin::StorageEngine::dropTable(*static_cast<Session *>(this), *base, identifier))
 
1907
  if (plugin::StorageEngine::dropTable(*this, *base, identifier))
2000
1908
  {
2001
 
    std::string path;
2002
 
    identifier.getSQLPath(path);
2003
1909
    errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
2004
 
                  path.c_str(), errno);
 
1910
                  identifier.getSQLPath().c_str(), errno);
2005
1911
 
2006
1912
    return true;
2007
1913
  }
2013
1919
  @note this will be removed, I am looking through Hudson to see if it is finding
2014
1920
  any tables that are missed during cleanup.
2015
1921
*/
2016
 
void Open_tables_state::dumpTemporaryTableNames(const char *foo)
 
1922
void Session::dumpTemporaryTableNames(const char *foo)
2017
1923
{
2018
1924
  Table *table;
2019
1925
 
2037
1943
      cerr << "\t\t Proto " << proto->schema() << " " << proto->name() << "\n";
2038
1944
    }
2039
1945
    else
2040
 
    {
2041
1946
      cerr << "\tTabl;e Name " << table->getShare()->getSchemaName() << "." << table->getShare()->getTableName() << " : " << answer << "\n";
2042
 
    }
2043
1947
  }
2044
1948
}
2045
1949
 
2046
 
bool Session::TableMessages::storeTableMessage(const TableIdentifier &identifier, message::Table &table_message)
 
1950
bool Session::storeTableMessage(const TableIdentifier &identifier, message::Table &table_message)
2047
1951
{
2048
1952
  table_message_cache.insert(make_pair(identifier.getPath(), table_message));
2049
1953
 
2050
1954
  return true;
2051
1955
}
2052
1956
 
2053
 
bool Session::TableMessages::removeTableMessage(const TableIdentifier &identifier)
 
1957
bool Session::removeTableMessage(const TableIdentifier &identifier)
2054
1958
{
2055
1959
  TableMessageCache::iterator iter;
2056
1960
 
2064
1968
  return true;
2065
1969
}
2066
1970
 
2067
 
bool Session::TableMessages::getTableMessage(const TableIdentifier &identifier, message::Table &table_message)
 
1971
bool Session::getTableMessage(const TableIdentifier &identifier, message::Table &table_message)
2068
1972
{
2069
1973
  TableMessageCache::iterator iter;
2070
1974
 
2078
1982
  return true;
2079
1983
}
2080
1984
 
2081
 
bool Session::TableMessages::doesTableMessageExist(const TableIdentifier &identifier)
 
1985
bool Session::doesTableMessageExist(const TableIdentifier &identifier)
2082
1986
{
2083
1987
  TableMessageCache::iterator iter;
2084
1988
 
2092
1996
  return true;
2093
1997
}
2094
1998
 
2095
 
bool Session::TableMessages::renameTableMessage(const TableIdentifier &from, const TableIdentifier &to)
 
1999
bool Session::renameTableMessage(const TableIdentifier &from, const TableIdentifier &to)
2096
2000
{
2097
2001
  TableMessageCache::iterator iter;
2098
2002
 
2111
2015
  return true;
2112
2016
}
2113
2017
 
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 */
 
2018
TableShareInstance *Session::getTemporaryShare(TableIdentifier::Type type_arg)
 
2019
{
 
2020
  temporary_shares.push_back(new TableShareInstance(type_arg)); // This will not go into the tableshare cache, so no key is used.
 
2021
 
 
2022
  TableShareInstance *tmp_share= temporary_shares.back();
 
2023
 
 
2024
  assert(tmp_share);
 
2025
 
 
2026
  return tmp_share;
 
2027
}
2180
2028
 
2181
2029
} /* namespace drizzled */