~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/session.cc

  • Committer: Brian Aker
  • Date: 2010-08-18 19:37:19 UTC
  • mto: This revision was merged to the branch mainline in revision 1720.
  • Revision ID: brian@tangent.org-20100818193719-bxxzn1pi22styowd
created function that can be used to simply crash the server.

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
55
#include "drizzled/internal/thread_var.h"
57
56
#include "drizzled/plugin/event_observer.h"
58
57
 
59
 
#include "drizzled/util/functors.h"
60
 
 
61
 
#include "drizzled/display.h"
62
 
 
63
58
#include <fcntl.h>
64
59
#include <algorithm>
65
60
#include <climits>
66
 
#include <boost/filesystem.hpp>
67
 
 
68
 
#include "drizzled/util/backtrace.h"
69
61
 
70
62
using namespace std;
71
 
 
72
 
namespace fs=boost::filesystem;
73
63
namespace drizzled
74
64
{
75
65
 
81
71
char empty_c_string[1]= {0};    /* used for not defined db */
82
72
 
83
73
const char * const Session::DEFAULT_WHERE= "field list";
 
74
extern pthread_key_t THR_Session;
 
75
extern pthread_key_t THR_Mem_root;
84
76
 
85
77
bool Key_part_spec::operator==(const Key_part_spec& other) const
86
78
{
87
79
  return length == other.length &&
88
80
         field_name.length == other.field_name.length &&
89
 
    !my_strcasecmp(system_charset_info, field_name.str, other.field_name.str);
 
81
         !strcmp(field_name.str, other.field_name.str);
90
82
}
91
83
 
92
84
Open_tables_state::Open_tables_state(uint64_t version_arg) :
162
154
Session::Session(plugin::Client *client_arg) :
163
155
  Open_tables_state(refresh_version),
164
156
  mem_root(&main_mem_root),
165
 
  xa_id(0),
166
157
  lex(&main_lex),
167
 
  query(new std::string),
168
 
  _schema(new std::string("")),
169
 
  catalog("LOCAL"),
 
158
  query(),
170
159
  client(client_arg),
171
160
  scheduler(NULL),
172
161
  scheduler_arg(NULL),
173
162
  lock_id(&main_lock_id),
174
163
  user_time(0),
175
164
  ha_data(plugin::num_trx_monitored_objects),
176
 
  concurrent_execute_allowed(true),
177
165
  arg_of_last_insert_id_function(false),
178
166
  first_successful_insert_id_in_prev_stmt(0),
179
167
  first_successful_insert_id_in_cur_stmt(0),
180
168
  limit_found_rows(0),
181
 
  _global_read_lock(NONE),
182
 
  _killed(NOT_KILLED),
 
169
  global_read_lock(0),
183
170
  some_tables_deleted(false),
184
171
  no_errors(false),
185
172
  password(false),
192
179
  cached_table(0),
193
180
  transaction_message(NULL),
194
181
  statement_message(NULL),
195
 
  session_event_observers(NULL),
196
 
  use_usage(false)
 
182
  session_event_observers(NULL)
197
183
{
 
184
  memset(process_list_info, 0, PROCESS_LIST_WIDTH);
198
185
  client->setSession(this);
199
186
 
200
187
  /*
205
192
  memory::init_sql_alloc(&main_mem_root, memory::ROOT_MIN_BLOCK_SIZE, 0);
206
193
  thread_stack= NULL;
207
194
  count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
 
195
  killed= NOT_KILLED;
208
196
  col_access= 0;
209
197
  tmp_table= 0;
210
198
  used_tables= 0;
224
212
  mysys_var= 0;
225
213
  scoreboard_index= -1;
226
214
  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;
 
215
  cleanup_done= abort_on_warning= no_warnings_for_error= false;
232
216
 
233
217
  /* Variables with default values */
234
218
  proc_info="login";
313
297
    return;
314
298
 
315
299
  setAbort(true);
316
 
  boost_unique_lock_t scopedLock(mysys_var->mutex);
 
300
  pthread_mutex_lock(&mysys_var->mutex);
317
301
  if (mysys_var->current_cond)
318
302
  {
319
 
    mysys_var->current_mutex->lock();
320
 
    mysys_var->current_cond->notify_all();
321
 
    mysys_var->current_mutex->unlock();
 
303
    pthread_mutex_lock(mysys_var->current_mutex);
 
304
    pthread_cond_broadcast(mysys_var->current_cond);
 
305
    pthread_mutex_unlock(mysys_var->current_mutex);
322
306
  }
 
307
  pthread_mutex_unlock(&mysys_var->mutex);
323
308
}
324
309
 
325
310
void Session::pop_internal_handler()
339
324
{
340
325
  assert(cleanup_done == false);
341
326
 
342
 
  setKilled(KILL_CONNECTION);
 
327
  killed= KILL_CONNECTION;
343
328
#ifdef ENABLE_WHEN_BINLOG_WILL_BE_ABLE_TO_PREPARE
344
329
  if (transaction.xid_state.xa_state == XA_PREPARED)
345
330
  {
365
350
  close_temporary_tables();
366
351
 
367
352
  if (global_read_lock)
368
 
  {
369
 
    unlockGlobalReadLock();
370
 
  }
 
353
    unlock_global_read_lock(this);
371
354
 
372
355
  cleanup_done= true;
373
356
}
401
384
  dbug_sentry= Session_SENTRY_GONE;
402
385
 
403
386
  main_mem_root.free_root(MYF(0));
404
 
  currentMemRoot().release();
405
 
  currentSession().release();
 
387
  pthread_setspecific(THR_Session,  0);
406
388
 
407
389
  plugin::Logging::postEndDo(this);
408
390
  plugin::EventObserver::deregisterSessionEvents(*this); 
409
391
 
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
 
 
 
392
  /* Ensure that no one is using Session */
 
393
  LOCK_delete.unlock();
 
394
}
 
395
 
 
396
void Session::awake(Session::killed_state state_to_set)
 
397
{
428
398
  this->checkSentry();
429
 
 
430
 
  setKilled(state_to_set);
431
 
  scheduler->killSession(this);
432
 
 
 
399
  safe_mutex_assert_owner(&LOCK_delete);
 
400
 
 
401
  killed= state_to_set;
433
402
  if (state_to_set != Session::KILL_QUERY)
434
403
  {
 
404
    scheduler->killSession(this);
435
405
    DRIZZLE_CONNECTION_DONE(thread_id);
436
406
  }
437
 
 
438
407
  if (mysys_var)
439
408
  {
440
 
    boost_unique_lock_t scopedLock(mysys_var->mutex);
 
409
    pthread_mutex_lock(&mysys_var->mutex);
441
410
    /*
442
 
      "
443
411
      This broadcast could be up in the air if the victim thread
444
412
      exits the cond in the time between read and broadcast, but that is
445
413
      ok since all we want to do is to make the victim thread get out
460
428
    */
461
429
    if (mysys_var->current_cond && mysys_var->current_mutex)
462
430
    {
463
 
      mysys_var->current_mutex->lock();
464
 
      mysys_var->current_cond->notify_all();
465
 
      mysys_var->current_mutex->unlock();
 
431
      pthread_mutex_lock(mysys_var->current_mutex);
 
432
      pthread_cond_broadcast(mysys_var->current_cond);
 
433
      pthread_mutex_unlock(mysys_var->current_mutex);
466
434
    }
 
435
    pthread_mutex_unlock(&mysys_var->mutex);
467
436
  }
468
437
}
469
438
 
479
448
  */
480
449
  assert(thread_stack);
481
450
 
482
 
  currentSession().release();
483
 
  currentSession().reset(this);
484
 
 
485
 
  currentMemRoot().release();
486
 
  currentMemRoot().reset(&mem_root);
 
451
  if (pthread_setspecific(THR_Session,  this) ||
 
452
      pthread_setspecific(THR_Mem_root, &mem_root))
 
453
    return true;
487
454
 
488
455
  mysys_var=my_thread_var;
489
456
 
492
459
    This allows us to move Session to different threads if needed.
493
460
  */
494
461
  mysys_var->id= thread_id;
 
462
  real_id= pthread_self();                      // For debugging
495
463
 
496
464
  /*
497
465
    We have to call thr_lock_info_init() again here as Session may have been
522
490
                                variables.query_prealloc_size);
523
491
  transaction.xid_state.xid.null();
524
492
  transaction.xid_state.in_session=1;
525
 
  if (use_usage)
526
 
    resetUsage();
527
493
}
528
494
 
529
495
bool Session::initGlobals()
547
513
 
548
514
  prepareForQueries();
549
515
 
550
 
  while (not client->haveError() && getKilled() != KILL_CONNECTION)
 
516
  while (! client->haveError() && killed != KILL_CONNECTION)
551
517
  {
552
 
    if (not executeStatement())
 
518
    if (! executeStatement())
553
519
      break;
554
520
  }
555
521
 
556
522
  disconnect(0, true);
557
523
}
558
524
 
559
 
bool Session::schedule(Session::shared_ptr &arg)
 
525
bool Session::schedule()
560
526
{
561
 
  arg->scheduler= plugin::Scheduler::getScheduler();
562
 
  assert(arg->scheduler);
 
527
  scheduler= plugin::Scheduler::getScheduler();
 
528
  assert(scheduler);
563
529
 
564
530
  connection_count.increment();
565
531
 
568
534
    current_global_counters.max_used_connections= connection_count;
569
535
  }
570
536
 
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());
 
537
  thread_id= variables.pseudo_thread_id= global_thread_id++;
 
538
 
 
539
  LOCK_thread_count.lock();
 
540
  getSessionList().push_back(this);
 
541
  LOCK_thread_count.unlock();
 
542
 
 
543
  if (scheduler->addSession(this))
 
544
  {
 
545
    DRIZZLE_CONNECTION_START(thread_id);
584
546
    char error_message_buff[DRIZZLE_ERRMSG_SIZE];
585
547
 
586
 
    arg->setKilled(Session::KILL_CONNECTION);
 
548
    killed= Session::KILL_CONNECTION;
587
549
 
588
 
    arg->status_var.aborted_connects++;
 
550
    status_var.aborted_connects++;
589
551
 
590
552
    /* Can't use my_error() since store_globals has not been called. */
591
553
    /* TODO replace will better error message */
592
554
    snprintf(error_message_buff, sizeof(error_message_buff),
593
555
             ER(ER_CANT_CREATE_THREAD), 1);
594
 
    arg->client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
595
 
 
 
556
    client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
596
557
    return true;
597
558
  }
598
559
 
600
561
}
601
562
 
602
563
 
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)
 
564
const char* Session::enter_cond(boost::condition_variable &cond, boost::mutex &mutex, const char* msg)
615
565
{
616
566
  const char* old_msg = get_proc_info();
617
567
  safe_mutex_assert_owner(mutex);
618
 
  mysys_var->current_mutex = &mutex;
619
 
  mysys_var->current_cond = &cond;
 
568
  mysys_var->current_mutex = mutex.native_handle();
 
569
  mysys_var->current_cond = cond.native_handle();
620
570
  this->set_proc_info(msg);
621
571
  return old_msg;
622
572
}
629
579
    locked (if that would not be the case, you'll get a deadlock if someone
630
580
    does a Session::awake() on you).
631
581
  */
632
 
  mysys_var->current_mutex->unlock();
633
 
  boost_unique_lock_t scopedLock(mysys_var->mutex);
 
582
  pthread_mutex_unlock(mysys_var->current_mutex);
 
583
  pthread_mutex_lock(&mysys_var->mutex);
634
584
  mysys_var->current_mutex = 0;
635
585
  mysys_var->current_cond = 0;
636
586
  this->set_proc_info(old_msg);
 
587
  pthread_mutex_unlock(&mysys_var->mutex);
637
588
}
638
589
 
639
590
bool Session::authenticate()
640
591
{
641
 
  lex->start(this);
 
592
  lex_start(this);
642
593
  if (client->authenticate())
643
594
    return false;
644
595
 
647
598
  return true;
648
599
}
649
600
 
650
 
bool Session::checkUser(const std::string &passwd_str,
651
 
                        const std::string &in_db)
 
601
bool Session::checkUser(const char *passwd, uint32_t passwd_len, const char *in_db)
652
602
{
 
603
  const string passwd_str(passwd, passwd_len);
653
604
  bool is_authenticated=
654
605
    plugin::Authentication::isAuthenticated(getSecurityContext(),
655
606
                                            passwd_str);
662
613
  }
663
614
 
664
615
  /* Change database if necessary */
665
 
  if (not in_db.empty())
 
616
  if (in_db && in_db[0])
666
617
  {
667
618
    SchemaIdentifier identifier(in_db);
668
619
    if (mysql_change_db(this, identifier))
672
623
    }
673
624
  }
674
625
  my_ok();
675
 
  password= not passwd_str.empty();
 
626
  password= test(passwd_len);          // remember for error messages
676
627
 
677
628
  /* Ready to handle queries */
678
629
  return true;
694
645
  main_da.reset_diagnostics_area();
695
646
 
696
647
  if (client->readCommand(&l_packet, &packet_length) == false)
697
 
  {
698
 
    return false;
699
 
  }
700
 
 
701
 
  if (getKilled() == KILL_CONNECTION)
702
648
    return false;
703
649
 
704
650
  if (packet_length == 0)
705
651
    return true;
706
652
 
707
 
  l_command= static_cast<enum_server_command>(l_packet[0]);
 
653
  l_command= (enum enum_server_command) (unsigned char) l_packet[0];
708
654
 
709
655
  if (command >= COM_END)
710
656
    command= COM_END;                           // Wrong command
711
657
 
712
658
  assert(packet_length);
713
 
  return not dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
 
659
  return ! dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
714
660
}
715
661
 
716
662
bool Session::readAndStoreQuery(const char *in_packet, uint32_t in_packet_length)
722
668
    in_packet_length--;
723
669
  }
724
670
  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])))
 
671
  while (in_packet_length > 0 &&
 
672
         (pos[-1] == ';' || my_isspace(charset() ,pos[-1])))
726
673
  {
727
674
    pos--;
728
675
    in_packet_length--;
729
676
  }
730
677
 
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));
 
678
  query.assign(in_packet, in_packet + in_packet_length);
739
679
 
740
680
  return true;
741
681
}
790
730
  }
791
731
 
792
732
  if (result == false)
793
 
  {
794
733
    my_error(killed_errno(), MYF(0));
795
 
  }
796
734
  else if ((result == true) && do_release)
797
 
  {
798
 
    setKilled(Session::KILL_CONNECTION);
799
 
  }
 
735
    killed= Session::KILL_CONNECTION;
800
736
 
801
737
  return result;
802
738
}
867
803
  where= Session::DEFAULT_WHERE;
868
804
 
869
805
  /* Reset the temporary shares we built */
870
 
  for_each(temporary_shares.begin(),
871
 
           temporary_shares.end(),
872
 
           DeletePtr());
 
806
  for (std::vector<TableShareInstance *>::iterator iter= temporary_shares.begin();
 
807
       iter != temporary_shares.end(); iter++)
 
808
  {
 
809
    delete *iter;
 
810
  }
873
811
  temporary_shares.clear();
874
812
}
875
813
 
955
893
  my_message(errcode, err, MYF(0));
956
894
  if (file > 0)
957
895
  {
958
 
    (void) cache->end_io_cache();
 
896
    (void) end_io_cache(cache);
959
897
    (void) internal::my_close(file, MYF(0));
960
 
    (void) internal::my_delete(path.file_string().c_str(), MYF(0));             // Delete file on error
 
898
    (void) internal::my_delete(path, MYF(0));           // Delete file on error
961
899
    file= -1;
962
900
  }
963
901
}
965
903
 
966
904
bool select_to_file::send_eof()
967
905
{
968
 
  int error= test(cache->end_io_cache());
 
906
  int error= test(end_io_cache(cache));
969
907
  if (internal::my_close(file, MYF(MY_WME)))
970
908
    error= 1;
971
909
  if (!error)
987
925
  /* In case of error send_eof() may be not called: close the file here. */
988
926
  if (file >= 0)
989
927
  {
990
 
    (void) cache->end_io_cache();
 
928
    (void) end_io_cache(cache);
991
929
    (void) internal::my_close(file, MYF(0));
992
930
    file= -1;
993
931
  }
994
 
  path= "";
 
932
  path[0]= '\0';
995
933
  row_count= 0;
996
934
}
997
935
 
1001
939
    cache(static_cast<internal::IO_CACHE *>(memory::sql_calloc(sizeof(internal::IO_CACHE)))),
1002
940
    row_count(0L)
1003
941
{
1004
 
  path= "";
 
942
  path[0]=0;
1005
943
}
1006
944
 
1007
945
select_to_file::~select_to_file()
1035
973
*/
1036
974
 
1037
975
 
1038
 
static int create_file(Session *session,
1039
 
                       fs::path &target_path,
1040
 
                       file_exchange *exchange,
1041
 
                       internal::IO_CACHE *cache)
 
976
static int create_file(Session *session, char *path, file_exchange *exchange, internal::IO_CACHE *cache)
1042
977
{
1043
 
  fs::path to_file(exchange->file_name);
1044
978
  int file;
1045
 
 
1046
 
  if (not to_file.has_root_directory())
 
979
  uint32_t option= MY_UNPACK_FILENAME | MY_RELATIVE_PATH;
 
980
 
 
981
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
 
982
  option|= MY_REPLACE_DIR;                      // Force use of db directory
 
983
#endif
 
984
 
 
985
  if (!internal::dirname_length(exchange->file_name))
1047
986
  {
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;
 
987
    strcpy(path, data_home_real);
 
988
    if (! session->db.empty())
 
989
      strncat(path, session->db.c_str(), FN_REFLEN-strlen(data_home_real)-1);
 
990
    (void) internal::fn_format(path, exchange->file_name, path, "", option);
1064
991
  }
1065
992
  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))
 
993
    (void) internal::fn_format(path, exchange->file_name, data_home_real, "", option);
 
994
 
 
995
  if (opt_secure_file_priv &&
 
996
      strncmp(opt_secure_file_priv, path, strlen(opt_secure_file_priv)))
 
997
  {
 
998
    /* Write only allowed to dir or subdir specified by secure_file_priv */
 
999
    my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
 
1000
    return -1;
 
1001
  }
 
1002
 
 
1003
  if (!access(path, F_OK))
1081
1004
  {
1082
1005
    my_error(ER_FILE_EXISTS_ERROR, MYF(0), exchange->file_name);
1083
1006
    return -1;
1084
1007
  }
1085
1008
  /* 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)
 
1009
  if ((file= internal::my_create(path, 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
1087
1010
    return file;
1088
1011
  (void) fchmod(file, 0666);                    // Because of umask()
1089
 
  if (cache->init_io_cache(file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
 
1012
  if (init_io_cache(cache, file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1090
1013
  {
1091
1014
    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
 
1015
    internal::my_delete(path, MYF(0));  // Delete file on error, it was just created
1093
1016
    return -1;
1094
1017
  }
1095
1018
  return file;
1103
1026
  bool string_results= false, non_string_results= false;
1104
1027
  unit= u;
1105
1028
  if ((uint32_t) strlen(exchange->file_name) + NAME_LEN >= FN_REFLEN)
1106
 
  {
1107
 
    path= exchange->file_name;
1108
 
  }
 
1029
    strncpy(path,exchange->file_name,FN_REFLEN-1);
1109
1030
 
1110
1031
  /* Check if there is any blobs in data */
1111
1032
  {
1115
1036
    {
1116
1037
      if (item->max_length >= MAX_BLOB_WIDTH)
1117
1038
      {
1118
 
        blob_flag=1;
1119
 
        break;
 
1039
        blob_flag=1;
 
1040
        break;
1120
1041
      }
1121
 
 
1122
1042
      if (item->result_type() == STRING_RESULT)
1123
1043
        string_results= true;
1124
1044
      else
1169
1089
  if (unit->offset_limit_cnt)
1170
1090
  {                                             // using limit offset,count
1171
1091
    unit->offset_limit_cnt--;
1172
 
    return false;
 
1092
    return(0);
1173
1093
  }
1174
1094
  row_count++;
1175
1095
  Item *item;
1178
1098
 
1179
1099
  if (my_b_write(cache,(unsigned char*) exchange->line_start->ptr(),
1180
1100
                 exchange->line_start->length()))
1181
 
    return true;
1182
 
 
 
1101
    goto err;
1183
1102
  while ((item=li++))
1184
1103
  {
1185
1104
    Item_result result_type=item->result_type();
1190
1109
    {
1191
1110
      if (my_b_write(cache,(unsigned char*) exchange->enclosed->ptr(),
1192
1111
                     exchange->enclosed->length()))
1193
 
        return true;
 
1112
        goto err;
1194
1113
    }
1195
1114
    if (!res)
1196
1115
    {                                           // NULL
1201
1120
          null_buff[0]=escape_char;
1202
1121
          null_buff[1]='N';
1203
1122
          if (my_b_write(cache,(unsigned char*) null_buff,2))
1204
 
            return true;
 
1123
            goto err;
1205
1124
        }
1206
1125
        else if (my_b_write(cache,(unsigned char*) "NULL",4))
1207
 
          return true;
 
1126
          goto err;
1208
1127
      }
1209
1128
      else
1210
1129
      {
1214
1133
    else
1215
1134
    {
1216
1135
      if (fixed_row_size)
1217
 
        used_length= min(res->length(), static_cast<size_t>(item->max_length));
 
1136
        used_length= min(res->length(),item->max_length);
1218
1137
      else
1219
1138
        used_length= res->length();
1220
1139
 
1295
1214
            tmp_buff[1]= *pos ? *pos : '0';
1296
1215
            if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)) ||
1297
1216
                my_b_write(cache,(unsigned char*) tmp_buff,2))
1298
 
              return true;
 
1217
              goto err;
1299
1218
            start=pos+1;
1300
1219
          }
1301
1220
        }
1302
1221
        if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)))
1303
 
          return true;
 
1222
          goto err;
1304
1223
      }
1305
1224
      else if (my_b_write(cache,(unsigned char*) res->ptr(),used_length))
1306
 
        return true;
 
1225
        goto err;
1307
1226
    }
1308
1227
    if (fixed_row_size)
1309
1228
    {                                           // Fill with space
1319
1238
        for (; length > sizeof(space) ; length-=sizeof(space))
1320
1239
        {
1321
1240
          if (my_b_write(cache,(unsigned char*) space,sizeof(space)))
1322
 
            return true;
 
1241
            goto err;
1323
1242
        }
1324
1243
        if (my_b_write(cache,(unsigned char*) space,length))
1325
 
          return true;
 
1244
          goto err;
1326
1245
      }
1327
1246
    }
1328
1247
    if (res && enclosed)
1329
1248
    {
1330
1249
      if (my_b_write(cache, (unsigned char*) exchange->enclosed->ptr(),
1331
1250
                     exchange->enclosed->length()))
1332
 
        return true;
 
1251
        goto err;
1333
1252
    }
1334
1253
    if (--items_left)
1335
1254
    {
1336
1255
      if (my_b_write(cache, (unsigned char*) exchange->field_term->ptr(),
1337
1256
                     field_term_length))
1338
 
        return true;
 
1257
        goto err;
1339
1258
    }
1340
1259
  }
1341
1260
  if (my_b_write(cache,(unsigned char*) exchange->line_term->ptr(),
1342
1261
                 exchange->line_term->length()))
1343
 
  {
1344
 
    return true;
1345
 
  }
1346
 
 
1347
 
  return false;
 
1262
    goto err;
 
1263
  return(0);
 
1264
err:
 
1265
  return(1);
1348
1266
}
1349
1267
 
1350
1268
 
1377
1295
  if (row_count++ > 1)
1378
1296
  {
1379
1297
    my_message(ER_TOO_MANY_ROWS, ER(ER_TOO_MANY_ROWS), MYF(0));
1380
 
    return 1;
 
1298
    goto err;
1381
1299
  }
1382
1300
  while ((item=li++))
1383
1301
  {
1385
1303
    if (!res)                                   // If NULL
1386
1304
    {
1387
1305
      if (my_b_write(cache,(unsigned char*) "",1))
1388
 
        return 1;
 
1306
        goto err;
1389
1307
    }
1390
1308
    else if (my_b_write(cache,(unsigned char*) res->ptr(),res->length()))
1391
1309
    {
1392
 
      my_error(ER_ERROR_ON_WRITE, MYF(0), path.file_string().c_str(), errno);
1393
 
      return 1;
 
1310
      my_error(ER_ERROR_ON_WRITE, MYF(0), path, errno);
 
1311
      goto err;
1394
1312
    }
1395
1313
  }
1396
1314
  return(0);
 
1315
err:
 
1316
  return(1);
1397
1317
}
1398
1318
 
1399
1319
 
1451
1371
      switch (val_item->result_type())
1452
1372
      {
1453
1373
      case REAL_RESULT:
1454
 
        op= &select_max_min_finder_subselect::cmp_real;
1455
 
        break;
 
1374
        op= &select_max_min_finder_subselect::cmp_real;
 
1375
        break;
1456
1376
      case INT_RESULT:
1457
 
        op= &select_max_min_finder_subselect::cmp_int;
1458
 
        break;
 
1377
        op= &select_max_min_finder_subselect::cmp_int;
 
1378
        break;
1459
1379
      case STRING_RESULT:
1460
 
        op= &select_max_min_finder_subselect::cmp_str;
1461
 
        break;
 
1380
        op= &select_max_min_finder_subselect::cmp_str;
 
1381
        break;
1462
1382
      case DECIMAL_RESULT:
1463
1383
        op= &select_max_min_finder_subselect::cmp_decimal;
1464
1384
        break;
1465
1385
      case ROW_RESULT:
1466
1386
        // This case should never be choosen
1467
 
        assert(0);
1468
 
        op= 0;
 
1387
        assert(0);
 
1388
        op= 0;
1469
1389
      }
1470
1390
    }
1471
1391
    cache->store(val_item);
1554
1474
void Session::end_statement()
1555
1475
{
1556
1476
  /* Cleanup SQL processing state to reuse this statement in next query. */
1557
 
  lex->end();
1558
 
  query_cache_key= ""; // reset the cache key
1559
 
  resetResultsetMessage();
 
1477
  lex_end(lex);
1560
1478
}
1561
1479
 
1562
1480
bool Session::copy_db_to(char **p_db, size_t *p_db_length)
1563
1481
{
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
 
 
 
1482
  if (db.empty())
 
1483
  {
 
1484
    my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
 
1485
    return true;
 
1486
  }
 
1487
  *p_db= strmake(db.c_str(), db.length());
 
1488
  *p_db_length= db.length();
1580
1489
  return false;
1581
1490
}
1582
1491
 
1616
1525
}
1617
1526
 
1618
1527
 
1619
 
void Session::set_db(const std::string &new_db)
 
1528
bool Session::set_db(const std::string &new_db)
1620
1529
{
1621
1530
  /* Do not reallocate memory if current chunk is big enough. */
1622
1531
  if (new_db.length())
1623
 
  {
1624
 
    _schema.reset(new std::string(new_db));
1625
 
  }
 
1532
    db= new_db;
1626
1533
  else
1627
 
  {
1628
 
    _schema.reset(new std::string(""));
1629
 
  }
1630
 
}
1631
 
 
 
1534
    db.clear();
 
1535
 
 
1536
  return false;
 
1537
}
 
1538
 
 
1539
 
 
1540
 
 
1541
 
 
1542
/**
 
1543
  Check the killed state of a user thread
 
1544
  @param session  user thread
 
1545
  @retval 0 the user thread is active
 
1546
  @retval 1 the user thread has been killed
 
1547
*/
 
1548
int session_killed(const Session *session)
 
1549
{
 
1550
  return(session->killed);
 
1551
}
 
1552
 
 
1553
 
 
1554
const struct charset_info_st *session_charset(Session *session)
 
1555
{
 
1556
  return(session->charset());
 
1557
}
1632
1558
 
1633
1559
/**
1634
1560
  Mark transaction to rollback and mark error as fatal to a sub-statement.
1651
1577
  plugin_sessionvar_cleanup(this);
1652
1578
 
1653
1579
  /* If necessary, log any aborted or unauthorized connections */
1654
 
  if (getKilled() || client->wasAborted())
 
1580
  if (killed || client->wasAborted())
1655
1581
  {
1656
1582
    status_var.aborted_threads++;
1657
1583
  }
1658
1584
 
1659
1585
  if (client->wasAborted())
1660
1586
  {
1661
 
    if (not getKilled() && variables.log_warnings > 1)
 
1587
    if (! killed && variables.log_warnings > 1)
1662
1588
    {
1663
1589
      SecurityContext *sctx= &security_ctx;
1664
1590
 
1665
1591
      errmsg_printf(ERRMSG_LVL_WARN, ER(ER_NEW_ABORTING_CONNECTION)
1666
1592
                  , thread_id
1667
 
                  , (_schema->empty() ? "unconnected" : _schema->c_str())
 
1593
                  , (db.empty() ? "unconnected" : db.c_str())
1668
1594
                  , sctx->getUser().empty() == false ? sctx->getUser().c_str() : "unauthenticated"
1669
1595
                  , sctx->getIp().c_str()
1670
1596
                  , (main_da.is_error() ? main_da.message() : ER(ER_UNKNOWN_ERROR)));
1673
1599
 
1674
1600
  /* Close out our connection to the client */
1675
1601
  if (should_lock)
1676
 
    session::Cache::singleton().mutex().lock();
1677
 
 
1678
 
  setKilled(Session::KILL_CONNECTION);
1679
 
 
 
1602
    LOCK_thread_count.lock();
 
1603
  killed= Session::KILL_CONNECTION;
1680
1604
  if (client->isConnected())
1681
1605
  {
1682
1606
    if (errcode)
1686
1610
    }
1687
1611
    client->close();
1688
1612
  }
1689
 
 
1690
1613
  if (should_lock)
1691
 
  {
1692
 
    session::Cache::singleton().mutex().unlock();
1693
 
  }
 
1614
    (void) LOCK_thread_count.unlock();
1694
1615
}
1695
1616
 
1696
1617
void Session::reset_for_next_command()
1718
1639
  Close all temporary tables created by 'CREATE TEMPORARY TABLE' for thread
1719
1640
*/
1720
1641
 
1721
 
void Open_tables_state::close_temporary_tables()
 
1642
void Session::close_temporary_tables()
1722
1643
{
1723
1644
  Table *table;
1724
1645
  Table *tmp_next;
1738
1659
  unlink from session->temporary tables and close temporary table
1739
1660
*/
1740
1661
 
1741
 
void Open_tables_state::close_temporary_table(Table *table)
 
1662
void Session::close_temporary_table(Table *table)
1742
1663
{
1743
1664
  if (table->getPrev())
1744
1665
  {
1774
1695
  If this is needed, use close_temporary_table()
1775
1696
*/
1776
1697
 
1777
 
void Open_tables_state::nukeTable(Table *table)
 
1698
void Session::nukeTable(Table *table)
1778
1699
{
1779
1700
  plugin::StorageEngine *table_type= table->getShare()->db_type();
1780
1701
 
1800
1721
 
1801
1722
  flush_status_time= time((time_t*) 0);
1802
1723
  current_global_counters.max_used_connections= 1; /* We set it to one, because we know we exist */
1803
 
  current_global_counters.connections= 0;
1804
1724
}
1805
1725
 
1806
1726
user_var_entry *Session::getVariable(LEX_STRING &name, bool create_if_not_exists)
1807
1727
{
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);
 
1728
  user_var_entry *entry= NULL;
 
1729
  UserVarsRange ppp= user_vars.equal_range(std::string(name.str, name.length));
1814
1730
 
1815
1731
  for (UserVars::iterator iter= ppp.first;
1816
 
       iter != ppp.second; ++iter)
 
1732
         iter != ppp.second; ++iter)
1817
1733
  {
1818
 
    return (*iter).second;
 
1734
    entry= (*iter).second;
1819
1735
  }
1820
1736
 
1821
 
  if (not create_if_not_exists)
1822
 
    return NULL;
1823
 
 
1824
 
  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)
 
1737
  if ((entry == NULL) && create_if_not_exists)
1833
1738
  {
1834
 
    delete entry;
 
1739
    entry= new (nothrow) user_var_entry(name.str, query_id);
 
1740
 
 
1741
    if (entry == NULL)
 
1742
      return NULL;
 
1743
 
 
1744
    std::pair<UserVars::iterator, bool> returnable= user_vars.insert(make_pair(std::string(name.str, name.length), entry));
 
1745
 
 
1746
    if (not returnable.second)
 
1747
    {
 
1748
      delete entry;
 
1749
      return NULL;
 
1750
    }
1835
1751
  }
1836
1752
 
1837
1753
  return entry;
1838
1754
}
1839
1755
 
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()
 
1756
void Session::mark_temp_tables_as_free_for_reuse()
1852
1757
{
1853
1758
  for (Table *table= temporary_tables ; table ; table= table->getNext())
1854
1759
  {
1855
 
    if (table->query_id == getQueryId())
 
1760
    if (table->query_id == query_id)
1856
1761
    {
1857
1762
      table->query_id= 0;
1858
1763
      table->cursor->ha_reset();
1864
1769
{
1865
1770
  for (; table ; table= table->getNext())
1866
1771
  {
1867
 
    if (table->query_id == getQueryId())
 
1772
    if (table->query_id == query_id)
1868
1773
    {
1869
1774
      table->query_id= 0;
1870
1775
      table->cursor->ha_reset();
1883
1788
*/
1884
1789
void Session::close_thread_tables()
1885
1790
{
1886
 
  clearDerivedTables();
 
1791
  if (derived_tables)
 
1792
    derived_tables= NULL; // They should all be invalid by this point
1887
1793
 
1888
1794
  /*
1889
1795
    Mark all temporary tables used by this statement as free for reuse.
1916
1822
      handled either before writing a query log event (inside
1917
1823
      binlog_query()) or when preparing a pending event.
1918
1824
     */
1919
 
    unlockTables(lock);
 
1825
    mysql_unlock_tables(this, lock);
1920
1826
    lock= 0;
1921
1827
  }
1922
1828
  /*
1923
 
    Note that we need to hold table::Cache::singleton().mutex() while changing the
 
1829
    Note that we need to hold LOCK_open while changing the
1924
1830
    open_tables list. Another thread may work on it.
1925
 
    (See: table::Cache::singleton().removeTable(), mysql_wait_completed_table())
 
1831
    (See: remove_table_from_cache(), mysql_wait_completed_table())
1926
1832
    Closing a MERGE child before the parent would be fatal if the
1927
1833
    other thread tries to abort the MERGE lock in between.
1928
1834
  */
1961
1867
    close_tables_for_reopen(&tables);
1962
1868
  }
1963
1869
  if ((mysql_handle_derived(lex, &mysql_derived_prepare) ||
1964
 
       (
 
1870
       (fill_derived_tables() &&
1965
1871
        mysql_handle_derived(lex, &mysql_derived_filling))))
1966
1872
    return true;
1967
1873
 
1968
1874
  return false;
1969
1875
}
1970
1876
 
 
1877
bool Session::openTables(TableList *tables, uint32_t flags)
 
1878
{
 
1879
  uint32_t counter;
 
1880
  bool ret= fill_derived_tables();
 
1881
  assert(ret == false);
 
1882
  if (open_tables_from_list(&tables, &counter, flags) ||
 
1883
      mysql_handle_derived(lex, &mysql_derived_prepare))
 
1884
  {
 
1885
    return true;
 
1886
  }
 
1887
  return false;
 
1888
}
 
1889
 
1971
1890
/*
1972
1891
  @note "best_effort" is used in cases were if a failure occurred on this
1973
1892
  operation it would not be surprising because we are only removing because there
1974
1893
  might be an issue (lame engines).
1975
1894
*/
1976
1895
 
1977
 
bool Open_tables_state::rm_temporary_table(const TableIdentifier &identifier, bool best_effort)
 
1896
bool Session::rm_temporary_table(TableIdentifier &identifier, bool best_effort)
1978
1897
{
1979
 
  if (plugin::StorageEngine::dropTable(*static_cast<Session *>(this), identifier))
 
1898
  if (plugin::StorageEngine::dropTable(*this, identifier))
1980
1899
  {
1981
1900
    if (not best_effort)
1982
1901
    {
1983
 
      std::string path;
1984
 
      identifier.getSQLPath(path);
1985
1902
      errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
1986
 
                    path.c_str(), errno);
 
1903
                    identifier.getSQLPath().c_str(), errno);
1987
1904
    }
1988
1905
 
1989
1906
    return true;
1992
1909
  return false;
1993
1910
}
1994
1911
 
1995
 
bool Open_tables_state::rm_temporary_table(plugin::StorageEngine *base, const TableIdentifier &identifier)
 
1912
bool Session::rm_temporary_table(plugin::StorageEngine *base, TableIdentifier &identifier)
1996
1913
{
1997
1914
  assert(base);
1998
1915
 
1999
 
  if (plugin::StorageEngine::dropTable(*static_cast<Session *>(this), *base, identifier))
 
1916
  if (plugin::StorageEngine::dropTable(*this, *base, identifier))
2000
1917
  {
2001
 
    std::string path;
2002
 
    identifier.getSQLPath(path);
2003
1918
    errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
2004
 
                  path.c_str(), errno);
 
1919
                  identifier.getSQLPath().c_str(), errno);
2005
1920
 
2006
1921
    return true;
2007
1922
  }
2013
1928
  @note this will be removed, I am looking through Hudson to see if it is finding
2014
1929
  any tables that are missed during cleanup.
2015
1930
*/
2016
 
void Open_tables_state::dumpTemporaryTableNames(const char *foo)
 
1931
void Session::dumpTemporaryTableNames(const char *foo)
2017
1932
{
2018
1933
  Table *table;
2019
1934
 
2037
1952
      cerr << "\t\t Proto " << proto->schema() << " " << proto->name() << "\n";
2038
1953
    }
2039
1954
    else
2040
 
    {
2041
1955
      cerr << "\tTabl;e Name " << table->getShare()->getSchemaName() << "." << table->getShare()->getTableName() << " : " << answer << "\n";
2042
 
    }
2043
1956
  }
2044
1957
}
2045
1958
 
2046
 
bool Session::TableMessages::storeTableMessage(const TableIdentifier &identifier, message::Table &table_message)
 
1959
bool Session::storeTableMessage(const TableIdentifier &identifier, message::Table &table_message)
2047
1960
{
2048
1961
  table_message_cache.insert(make_pair(identifier.getPath(), table_message));
2049
1962
 
2050
1963
  return true;
2051
1964
}
2052
1965
 
2053
 
bool Session::TableMessages::removeTableMessage(const TableIdentifier &identifier)
 
1966
bool Session::removeTableMessage(const TableIdentifier &identifier)
2054
1967
{
2055
1968
  TableMessageCache::iterator iter;
2056
1969
 
2064
1977
  return true;
2065
1978
}
2066
1979
 
2067
 
bool Session::TableMessages::getTableMessage(const TableIdentifier &identifier, message::Table &table_message)
 
1980
bool Session::getTableMessage(const TableIdentifier &identifier, message::Table &table_message)
2068
1981
{
2069
1982
  TableMessageCache::iterator iter;
2070
1983
 
2078
1991
  return true;
2079
1992
}
2080
1993
 
2081
 
bool Session::TableMessages::doesTableMessageExist(const TableIdentifier &identifier)
 
1994
bool Session::doesTableMessageExist(const TableIdentifier &identifier)
2082
1995
{
2083
1996
  TableMessageCache::iterator iter;
2084
1997
 
2092
2005
  return true;
2093
2006
}
2094
2007
 
2095
 
bool Session::TableMessages::renameTableMessage(const TableIdentifier &from, const TableIdentifier &to)
 
2008
bool Session::renameTableMessage(const TableIdentifier &from, const TableIdentifier &to)
2096
2009
{
2097
2010
  TableMessageCache::iterator iter;
2098
2011
 
2111
2024
  return true;
2112
2025
}
2113
2026
 
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 */
 
2027
TableShareInstance *Session::getTemporaryShare(TableIdentifier::Type type_arg)
 
2028
{
 
2029
  temporary_shares.push_back(new TableShareInstance(type_arg)); // This will not go into the tableshare cache, so no key is used.
 
2030
 
 
2031
  TableShareInstance *tmp_share= temporary_shares.back();
 
2032
 
 
2033
  assert(tmp_share);
 
2034
 
 
2035
  return tmp_share;
 
2036
}
2180
2037
 
2181
2038
} /* namespace drizzled */