~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/session.cc

  • Committer: Brian Aker
  • Date: 2010-09-22 22:29:55 UTC
  • mto: (1787.3.1 drizzle)
  • mto: This revision was merged to the branch mainline in revision 1789.
  • Revision ID: brian@tangent.org-20100922222955-cg1bddv4b72jwe31
Fix enum at being an intefer (which is what PG did, and it saves on
alignment issues).

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
 
86
76
{
87
77
  return length == other.length &&
88
78
         field_name.length == other.field_name.length &&
89
 
    !my_strcasecmp(system_charset_info, field_name.str, other.field_name.str);
 
79
         !strcmp(field_name.str, other.field_name.str);
90
80
}
91
81
 
92
82
Open_tables_state::Open_tables_state(uint64_t version_arg) :
162
152
Session::Session(plugin::Client *client_arg) :
163
153
  Open_tables_state(refresh_version),
164
154
  mem_root(&main_mem_root),
165
 
  xa_id(0),
166
155
  lex(&main_lex),
167
 
  query(new std::string),
168
 
  _schema(new std::string("")),
169
 
  catalog("LOCAL"),
 
156
  query(),
170
157
  client(client_arg),
171
158
  scheduler(NULL),
172
159
  scheduler_arg(NULL),
173
160
  lock_id(&main_lock_id),
174
161
  user_time(0),
175
162
  ha_data(plugin::num_trx_monitored_objects),
176
 
  concurrent_execute_allowed(true),
177
163
  arg_of_last_insert_id_function(false),
178
164
  first_successful_insert_id_in_prev_stmt(0),
179
165
  first_successful_insert_id_in_cur_stmt(0),
180
166
  limit_found_rows(0),
181
 
  _global_read_lock(NONE),
182
 
  _killed(NOT_KILLED),
 
167
  global_read_lock(0),
183
168
  some_tables_deleted(false),
184
169
  no_errors(false),
185
170
  password(false),
192
177
  cached_table(0),
193
178
  transaction_message(NULL),
194
179
  statement_message(NULL),
195
 
  session_event_observers(NULL),
196
 
  use_usage(false)
 
180
  session_event_observers(NULL)
197
181
{
 
182
  memset(process_list_info, 0, PROCESS_LIST_WIDTH);
198
183
  client->setSession(this);
199
184
 
200
185
  /*
205
190
  memory::init_sql_alloc(&main_mem_root, memory::ROOT_MIN_BLOCK_SIZE, 0);
206
191
  thread_stack= NULL;
207
192
  count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
 
193
  killed= NOT_KILLED;
208
194
  col_access= 0;
209
195
  tmp_table= 0;
210
196
  used_tables= 0;
313
299
    return;
314
300
 
315
301
  setAbort(true);
316
 
  boost_unique_lock_t scopedLock(mysys_var->mutex);
 
302
  pthread_mutex_lock(&mysys_var->mutex);
317
303
  if (mysys_var->current_cond)
318
304
  {
319
 
    mysys_var->current_mutex->lock();
320
 
    mysys_var->current_cond->notify_all();
321
 
    mysys_var->current_mutex->unlock();
 
305
    pthread_mutex_lock(mysys_var->current_mutex);
 
306
    pthread_cond_broadcast(mysys_var->current_cond);
 
307
    pthread_mutex_unlock(mysys_var->current_mutex);
322
308
  }
 
309
  pthread_mutex_unlock(&mysys_var->mutex);
323
310
}
324
311
 
325
312
void Session::pop_internal_handler()
339
326
{
340
327
  assert(cleanup_done == false);
341
328
 
342
 
  setKilled(KILL_CONNECTION);
 
329
  killed= KILL_CONNECTION;
343
330
#ifdef ENABLE_WHEN_BINLOG_WILL_BE_ABLE_TO_PREPARE
344
331
  if (transaction.xid_state.xa_state == XA_PREPARED)
345
332
  {
365
352
  close_temporary_tables();
366
353
 
367
354
  if (global_read_lock)
368
 
  {
369
 
    unlockGlobalReadLock();
370
 
  }
 
355
    unlock_global_read_lock(this);
371
356
 
372
357
  cleanup_done= true;
373
358
}
407
392
  plugin::Logging::postEndDo(this);
408
393
  plugin::EventObserver::deregisterSessionEvents(*this); 
409
394
 
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
 
 
 
395
  /* Ensure that no one is using Session */
 
396
  LOCK_delete.unlock();
 
397
}
 
398
 
 
399
void Session::awake(Session::killed_state state_to_set)
 
400
{
428
401
  this->checkSentry();
429
 
 
430
 
  setKilled(state_to_set);
431
 
  scheduler->killSession(this);
432
 
 
 
402
  safe_mutex_assert_owner(&LOCK_delete);
 
403
 
 
404
  killed= state_to_set;
433
405
  if (state_to_set != Session::KILL_QUERY)
434
406
  {
 
407
    scheduler->killSession(this);
435
408
    DRIZZLE_CONNECTION_DONE(thread_id);
436
409
  }
437
 
 
438
410
  if (mysys_var)
439
411
  {
440
 
    boost_unique_lock_t scopedLock(mysys_var->mutex);
 
412
    pthread_mutex_lock(&mysys_var->mutex);
441
413
    /*
442
 
      "
443
414
      This broadcast could be up in the air if the victim thread
444
415
      exits the cond in the time between read and broadcast, but that is
445
416
      ok since all we want to do is to make the victim thread get out
460
431
    */
461
432
    if (mysys_var->current_cond && mysys_var->current_mutex)
462
433
    {
463
 
      mysys_var->current_mutex->lock();
464
 
      mysys_var->current_cond->notify_all();
465
 
      mysys_var->current_mutex->unlock();
 
434
      pthread_mutex_lock(mysys_var->current_mutex);
 
435
      pthread_cond_broadcast(mysys_var->current_cond);
 
436
      pthread_mutex_unlock(mysys_var->current_mutex);
466
437
    }
 
438
    pthread_mutex_unlock(&mysys_var->mutex);
467
439
  }
468
440
}
469
441
 
522
494
                                variables.query_prealloc_size);
523
495
  transaction.xid_state.xid.null();
524
496
  transaction.xid_state.in_session=1;
525
 
  if (use_usage)
526
 
    resetUsage();
527
497
}
528
498
 
529
499
bool Session::initGlobals()
547
517
 
548
518
  prepareForQueries();
549
519
 
550
 
  while (not client->haveError() && getKilled() != KILL_CONNECTION)
 
520
  while (! client->haveError() && killed != KILL_CONNECTION)
551
521
  {
552
 
    if (not executeStatement())
 
522
    if (! executeStatement())
553
523
      break;
554
524
  }
555
525
 
556
526
  disconnect(0, true);
557
527
}
558
528
 
559
 
bool Session::schedule(Session::shared_ptr &arg)
 
529
bool Session::schedule()
560
530
{
561
 
  arg->scheduler= plugin::Scheduler::getScheduler();
562
 
  assert(arg->scheduler);
 
531
  scheduler= plugin::Scheduler::getScheduler();
 
532
  assert(scheduler);
563
533
 
564
534
  connection_count.increment();
565
535
 
569
539
  }
570
540
 
571
541
  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());
 
542
  thread_id= variables.pseudo_thread_id= global_thread_id++;
 
543
 
 
544
  LOCK_thread_count.lock();
 
545
  getSessionList().push_back(this);
 
546
  LOCK_thread_count.unlock();
 
547
 
 
548
  if (scheduler->addSession(this))
 
549
  {
 
550
    DRIZZLE_CONNECTION_START(thread_id);
584
551
    char error_message_buff[DRIZZLE_ERRMSG_SIZE];
585
552
 
586
 
    arg->setKilled(Session::KILL_CONNECTION);
 
553
    killed= Session::KILL_CONNECTION;
587
554
 
588
 
    arg->status_var.aborted_connects++;
 
555
    status_var.aborted_connects++;
589
556
 
590
557
    /* Can't use my_error() since store_globals has not been called. */
591
558
    /* TODO replace will better error message */
592
559
    snprintf(error_message_buff, sizeof(error_message_buff),
593
560
             ER(ER_CANT_CREATE_THREAD), 1);
594
 
    arg->client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
595
 
 
 
561
    client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
596
562
    return true;
597
563
  }
598
564
 
600
566
}
601
567
 
602
568
 
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)
 
569
const char* Session::enter_cond(boost::condition_variable &cond, boost::mutex &mutex, const char* msg)
615
570
{
616
571
  const char* old_msg = get_proc_info();
617
572
  safe_mutex_assert_owner(mutex);
618
 
  mysys_var->current_mutex = &mutex;
619
 
  mysys_var->current_cond = &cond;
 
573
  mysys_var->current_mutex = mutex.native_handle();
 
574
  mysys_var->current_cond = cond.native_handle();
620
575
  this->set_proc_info(msg);
621
576
  return old_msg;
622
577
}
629
584
    locked (if that would not be the case, you'll get a deadlock if someone
630
585
    does a Session::awake() on you).
631
586
  */
632
 
  mysys_var->current_mutex->unlock();
633
 
  boost_unique_lock_t scopedLock(mysys_var->mutex);
 
587
  pthread_mutex_unlock(mysys_var->current_mutex);
 
588
  pthread_mutex_lock(&mysys_var->mutex);
634
589
  mysys_var->current_mutex = 0;
635
590
  mysys_var->current_cond = 0;
636
591
  this->set_proc_info(old_msg);
 
592
  pthread_mutex_unlock(&mysys_var->mutex);
637
593
}
638
594
 
639
595
bool Session::authenticate()
640
596
{
641
 
  lex->start(this);
 
597
  lex_start(this);
642
598
  if (client->authenticate())
643
599
    return false;
644
600
 
647
603
  return true;
648
604
}
649
605
 
650
 
bool Session::checkUser(const std::string &passwd_str,
651
 
                        const std::string &in_db)
 
606
bool Session::checkUser(const char *passwd, uint32_t passwd_len, const char *in_db)
652
607
{
 
608
  const string passwd_str(passwd, passwd_len);
653
609
  bool is_authenticated=
654
610
    plugin::Authentication::isAuthenticated(getSecurityContext(),
655
611
                                            passwd_str);
662
618
  }
663
619
 
664
620
  /* Change database if necessary */
665
 
  if (not in_db.empty())
 
621
  if (in_db && in_db[0])
666
622
  {
667
623
    SchemaIdentifier identifier(in_db);
668
624
    if (mysql_change_db(this, identifier))
672
628
    }
673
629
  }
674
630
  my_ok();
675
 
  password= not passwd_str.empty();
 
631
  password= test(passwd_len);          // remember for error messages
676
632
 
677
633
  /* Ready to handle queries */
678
634
  return true;
694
650
  main_da.reset_diagnostics_area();
695
651
 
696
652
  if (client->readCommand(&l_packet, &packet_length) == false)
697
 
  {
698
653
    return false;
699
 
  }
700
654
 
701
 
  if (getKilled() == KILL_CONNECTION)
 
655
  if (killed == KILL_CONNECTION)
702
656
    return false;
703
657
 
704
658
  if (packet_length == 0)
705
659
    return true;
706
660
 
707
 
  l_command= static_cast<enum_server_command>(l_packet[0]);
 
661
  l_command= (enum enum_server_command) (unsigned char) l_packet[0];
708
662
 
709
663
  if (command >= COM_END)
710
664
    command= COM_END;                           // Wrong command
711
665
 
712
666
  assert(packet_length);
713
 
  return not dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
 
667
  return ! dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
714
668
}
715
669
 
716
670
bool Session::readAndStoreQuery(const char *in_packet, uint32_t in_packet_length)
722
676
    in_packet_length--;
723
677
  }
724
678
  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])))
 
679
  while (in_packet_length > 0 &&
 
680
         (pos[-1] == ';' || my_isspace(charset() ,pos[-1])))
726
681
  {
727
682
    pos--;
728
683
    in_packet_length--;
729
684
  }
730
685
 
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));
 
686
  query.assign(in_packet, in_packet + in_packet_length);
739
687
 
740
688
  return true;
741
689
}
790
738
  }
791
739
 
792
740
  if (result == false)
793
 
  {
794
741
    my_error(killed_errno(), MYF(0));
795
 
  }
796
742
  else if ((result == true) && do_release)
797
 
  {
798
 
    setKilled(Session::KILL_CONNECTION);
799
 
  }
 
743
    killed= Session::KILL_CONNECTION;
800
744
 
801
745
  return result;
802
746
}
867
811
  where= Session::DEFAULT_WHERE;
868
812
 
869
813
  /* Reset the temporary shares we built */
870
 
  for_each(temporary_shares.begin(),
871
 
           temporary_shares.end(),
872
 
           DeletePtr());
 
814
  for (std::vector<TableShareInstance *>::iterator iter= temporary_shares.begin();
 
815
       iter != temporary_shares.end(); iter++)
 
816
  {
 
817
    delete *iter;
 
818
  }
873
819
  temporary_shares.clear();
874
820
}
875
821
 
955
901
  my_message(errcode, err, MYF(0));
956
902
  if (file > 0)
957
903
  {
958
 
    (void) cache->end_io_cache();
 
904
    (void) end_io_cache(cache);
959
905
    (void) internal::my_close(file, MYF(0));
960
 
    (void) internal::my_delete(path.file_string().c_str(), MYF(0));             // Delete file on error
 
906
    (void) internal::my_delete(path, MYF(0));           // Delete file on error
961
907
    file= -1;
962
908
  }
963
909
}
965
911
 
966
912
bool select_to_file::send_eof()
967
913
{
968
 
  int error= test(cache->end_io_cache());
 
914
  int error= test(end_io_cache(cache));
969
915
  if (internal::my_close(file, MYF(MY_WME)))
970
916
    error= 1;
971
917
  if (!error)
987
933
  /* In case of error send_eof() may be not called: close the file here. */
988
934
  if (file >= 0)
989
935
  {
990
 
    (void) cache->end_io_cache();
 
936
    (void) end_io_cache(cache);
991
937
    (void) internal::my_close(file, MYF(0));
992
938
    file= -1;
993
939
  }
994
 
  path= "";
 
940
  path[0]= '\0';
995
941
  row_count= 0;
996
942
}
997
943
 
1001
947
    cache(static_cast<internal::IO_CACHE *>(memory::sql_calloc(sizeof(internal::IO_CACHE)))),
1002
948
    row_count(0L)
1003
949
{
1004
 
  path= "";
 
950
  path[0]=0;
1005
951
}
1006
952
 
1007
953
select_to_file::~select_to_file()
1035
981
*/
1036
982
 
1037
983
 
1038
 
static int create_file(Session *session,
1039
 
                       fs::path &target_path,
1040
 
                       file_exchange *exchange,
1041
 
                       internal::IO_CACHE *cache)
 
984
static int create_file(Session *session, char *path, file_exchange *exchange, internal::IO_CACHE *cache)
1042
985
{
1043
 
  fs::path to_file(exchange->file_name);
1044
986
  int file;
1045
 
 
1046
 
  if (not to_file.has_root_directory())
 
987
  uint32_t option= MY_UNPACK_FILENAME | MY_RELATIVE_PATH;
 
988
 
 
989
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
 
990
  option|= MY_REPLACE_DIR;                      // Force use of db directory
 
991
#endif
 
992
 
 
993
  if (!internal::dirname_length(exchange->file_name))
1047
994
  {
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;
 
995
    strcpy(path, data_home_real);
 
996
    if (! session->db.empty())
 
997
      strncat(path, session->db.c_str(), FN_REFLEN-strlen(data_home_real)-1);
 
998
    (void) internal::fn_format(path, exchange->file_name, path, "", option);
1064
999
  }
1065
1000
  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))
 
1001
    (void) internal::fn_format(path, exchange->file_name, data_home_real, "", option);
 
1002
 
 
1003
  if (opt_secure_file_priv &&
 
1004
      strncmp(opt_secure_file_priv, path, strlen(opt_secure_file_priv)))
 
1005
  {
 
1006
    /* Write only allowed to dir or subdir specified by secure_file_priv */
 
1007
    my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
 
1008
    return -1;
 
1009
  }
 
1010
 
 
1011
  if (!access(path, F_OK))
1081
1012
  {
1082
1013
    my_error(ER_FILE_EXISTS_ERROR, MYF(0), exchange->file_name);
1083
1014
    return -1;
1084
1015
  }
1085
1016
  /* 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)
 
1017
  if ((file= internal::my_create(path, 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
1087
1018
    return file;
1088
1019
  (void) fchmod(file, 0666);                    // Because of umask()
1089
 
  if (cache->init_io_cache(file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
 
1020
  if (init_io_cache(cache, file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1090
1021
  {
1091
1022
    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
 
1023
    internal::my_delete(path, MYF(0));  // Delete file on error, it was just created
1093
1024
    return -1;
1094
1025
  }
1095
1026
  return file;
1103
1034
  bool string_results= false, non_string_results= false;
1104
1035
  unit= u;
1105
1036
  if ((uint32_t) strlen(exchange->file_name) + NAME_LEN >= FN_REFLEN)
1106
 
  {
1107
 
    path= exchange->file_name;
1108
 
  }
 
1037
    strncpy(path,exchange->file_name,FN_REFLEN-1);
1109
1038
 
1110
1039
  /* Check if there is any blobs in data */
1111
1040
  {
1115
1044
    {
1116
1045
      if (item->max_length >= MAX_BLOB_WIDTH)
1117
1046
      {
1118
 
        blob_flag=1;
1119
 
        break;
 
1047
        blob_flag=1;
 
1048
        break;
1120
1049
      }
1121
 
 
1122
1050
      if (item->result_type() == STRING_RESULT)
1123
1051
        string_results= true;
1124
1052
      else
1169
1097
  if (unit->offset_limit_cnt)
1170
1098
  {                                             // using limit offset,count
1171
1099
    unit->offset_limit_cnt--;
1172
 
    return false;
 
1100
    return(0);
1173
1101
  }
1174
1102
  row_count++;
1175
1103
  Item *item;
1178
1106
 
1179
1107
  if (my_b_write(cache,(unsigned char*) exchange->line_start->ptr(),
1180
1108
                 exchange->line_start->length()))
1181
 
    return true;
1182
 
 
 
1109
    goto err;
1183
1110
  while ((item=li++))
1184
1111
  {
1185
1112
    Item_result result_type=item->result_type();
1190
1117
    {
1191
1118
      if (my_b_write(cache,(unsigned char*) exchange->enclosed->ptr(),
1192
1119
                     exchange->enclosed->length()))
1193
 
        return true;
 
1120
        goto err;
1194
1121
    }
1195
1122
    if (!res)
1196
1123
    {                                           // NULL
1201
1128
          null_buff[0]=escape_char;
1202
1129
          null_buff[1]='N';
1203
1130
          if (my_b_write(cache,(unsigned char*) null_buff,2))
1204
 
            return true;
 
1131
            goto err;
1205
1132
        }
1206
1133
        else if (my_b_write(cache,(unsigned char*) "NULL",4))
1207
 
          return true;
 
1134
          goto err;
1208
1135
      }
1209
1136
      else
1210
1137
      {
1214
1141
    else
1215
1142
    {
1216
1143
      if (fixed_row_size)
1217
 
        used_length= min(res->length(), static_cast<size_t>(item->max_length));
 
1144
        used_length= min(res->length(),item->max_length);
1218
1145
      else
1219
1146
        used_length= res->length();
1220
1147
 
1295
1222
            tmp_buff[1]= *pos ? *pos : '0';
1296
1223
            if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)) ||
1297
1224
                my_b_write(cache,(unsigned char*) tmp_buff,2))
1298
 
              return true;
 
1225
              goto err;
1299
1226
            start=pos+1;
1300
1227
          }
1301
1228
        }
1302
1229
        if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)))
1303
 
          return true;
 
1230
          goto err;
1304
1231
      }
1305
1232
      else if (my_b_write(cache,(unsigned char*) res->ptr(),used_length))
1306
 
        return true;
 
1233
        goto err;
1307
1234
    }
1308
1235
    if (fixed_row_size)
1309
1236
    {                                           // Fill with space
1319
1246
        for (; length > sizeof(space) ; length-=sizeof(space))
1320
1247
        {
1321
1248
          if (my_b_write(cache,(unsigned char*) space,sizeof(space)))
1322
 
            return true;
 
1249
            goto err;
1323
1250
        }
1324
1251
        if (my_b_write(cache,(unsigned char*) space,length))
1325
 
          return true;
 
1252
          goto err;
1326
1253
      }
1327
1254
    }
1328
1255
    if (res && enclosed)
1329
1256
    {
1330
1257
      if (my_b_write(cache, (unsigned char*) exchange->enclosed->ptr(),
1331
1258
                     exchange->enclosed->length()))
1332
 
        return true;
 
1259
        goto err;
1333
1260
    }
1334
1261
    if (--items_left)
1335
1262
    {
1336
1263
      if (my_b_write(cache, (unsigned char*) exchange->field_term->ptr(),
1337
1264
                     field_term_length))
1338
 
        return true;
 
1265
        goto err;
1339
1266
    }
1340
1267
  }
1341
1268
  if (my_b_write(cache,(unsigned char*) exchange->line_term->ptr(),
1342
1269
                 exchange->line_term->length()))
1343
 
  {
1344
 
    return true;
1345
 
  }
1346
 
 
1347
 
  return false;
 
1270
    goto err;
 
1271
  return(0);
 
1272
err:
 
1273
  return(1);
1348
1274
}
1349
1275
 
1350
1276
 
1377
1303
  if (row_count++ > 1)
1378
1304
  {
1379
1305
    my_message(ER_TOO_MANY_ROWS, ER(ER_TOO_MANY_ROWS), MYF(0));
1380
 
    return 1;
 
1306
    goto err;
1381
1307
  }
1382
1308
  while ((item=li++))
1383
1309
  {
1385
1311
    if (!res)                                   // If NULL
1386
1312
    {
1387
1313
      if (my_b_write(cache,(unsigned char*) "",1))
1388
 
        return 1;
 
1314
        goto err;
1389
1315
    }
1390
1316
    else if (my_b_write(cache,(unsigned char*) res->ptr(),res->length()))
1391
1317
    {
1392
 
      my_error(ER_ERROR_ON_WRITE, MYF(0), path.file_string().c_str(), errno);
1393
 
      return 1;
 
1318
      my_error(ER_ERROR_ON_WRITE, MYF(0), path, errno);
 
1319
      goto err;
1394
1320
    }
1395
1321
  }
1396
1322
  return(0);
 
1323
err:
 
1324
  return(1);
1397
1325
}
1398
1326
 
1399
1327
 
1451
1379
      switch (val_item->result_type())
1452
1380
      {
1453
1381
      case REAL_RESULT:
1454
 
        op= &select_max_min_finder_subselect::cmp_real;
1455
 
        break;
 
1382
        op= &select_max_min_finder_subselect::cmp_real;
 
1383
        break;
1456
1384
      case INT_RESULT:
1457
 
        op= &select_max_min_finder_subselect::cmp_int;
1458
 
        break;
 
1385
        op= &select_max_min_finder_subselect::cmp_int;
 
1386
        break;
1459
1387
      case STRING_RESULT:
1460
 
        op= &select_max_min_finder_subselect::cmp_str;
1461
 
        break;
 
1388
        op= &select_max_min_finder_subselect::cmp_str;
 
1389
        break;
1462
1390
      case DECIMAL_RESULT:
1463
1391
        op= &select_max_min_finder_subselect::cmp_decimal;
1464
1392
        break;
1465
1393
      case ROW_RESULT:
1466
1394
        // This case should never be choosen
1467
 
        assert(0);
1468
 
        op= 0;
 
1395
        assert(0);
 
1396
        op= 0;
1469
1397
      }
1470
1398
    }
1471
1399
    cache->store(val_item);
1554
1482
void Session::end_statement()
1555
1483
{
1556
1484
  /* Cleanup SQL processing state to reuse this statement in next query. */
1557
 
  lex->end();
 
1485
  lex_end(lex);
1558
1486
  query_cache_key= ""; // reset the cache key
1559
1487
  resetResultsetMessage();
1560
1488
}
1561
1489
 
1562
1490
bool Session::copy_db_to(char **p_db, size_t *p_db_length)
1563
1491
{
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
 
 
 
1492
  if (db.empty())
 
1493
  {
 
1494
    my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
 
1495
    return true;
 
1496
  }
 
1497
  *p_db= strmake(db.c_str(), db.length());
 
1498
  *p_db_length= db.length();
1580
1499
  return false;
1581
1500
}
1582
1501
 
1616
1535
}
1617
1536
 
1618
1537
 
1619
 
void Session::set_db(const std::string &new_db)
 
1538
bool Session::set_db(const std::string &new_db)
1620
1539
{
1621
1540
  /* Do not reallocate memory if current chunk is big enough. */
1622
1541
  if (new_db.length())
1623
 
  {
1624
 
    _schema.reset(new std::string(new_db));
1625
 
  }
 
1542
    db= new_db;
1626
1543
  else
1627
 
  {
1628
 
    _schema.reset(new std::string(""));
1629
 
  }
1630
 
}
1631
 
 
 
1544
    db.clear();
 
1545
 
 
1546
  return false;
 
1547
}
 
1548
 
 
1549
 
 
1550
 
 
1551
 
 
1552
/**
 
1553
  Check the killed state of a user thread
 
1554
  @param session  user thread
 
1555
  @retval 0 the user thread is active
 
1556
  @retval 1 the user thread has been killed
 
1557
*/
 
1558
int session_killed(const Session *session)
 
1559
{
 
1560
  return(session->killed);
 
1561
}
 
1562
 
 
1563
 
 
1564
const struct charset_info_st *session_charset(Session *session)
 
1565
{
 
1566
  return(session->charset());
 
1567
}
1632
1568
 
1633
1569
/**
1634
1570
  Mark transaction to rollback and mark error as fatal to a sub-statement.
1651
1587
  plugin_sessionvar_cleanup(this);
1652
1588
 
1653
1589
  /* If necessary, log any aborted or unauthorized connections */
1654
 
  if (getKilled() || client->wasAborted())
 
1590
  if (killed || client->wasAborted())
1655
1591
  {
1656
1592
    status_var.aborted_threads++;
1657
1593
  }
1658
1594
 
1659
1595
  if (client->wasAborted())
1660
1596
  {
1661
 
    if (not getKilled() && variables.log_warnings > 1)
 
1597
    if (! killed && variables.log_warnings > 1)
1662
1598
    {
1663
1599
      SecurityContext *sctx= &security_ctx;
1664
1600
 
1665
1601
      errmsg_printf(ERRMSG_LVL_WARN, ER(ER_NEW_ABORTING_CONNECTION)
1666
1602
                  , thread_id
1667
 
                  , (_schema->empty() ? "unconnected" : _schema->c_str())
 
1603
                  , (db.empty() ? "unconnected" : db.c_str())
1668
1604
                  , sctx->getUser().empty() == false ? sctx->getUser().c_str() : "unauthenticated"
1669
1605
                  , sctx->getIp().c_str()
1670
1606
                  , (main_da.is_error() ? main_da.message() : ER(ER_UNKNOWN_ERROR)));
1673
1609
 
1674
1610
  /* Close out our connection to the client */
1675
1611
  if (should_lock)
1676
 
    session::Cache::singleton().mutex().lock();
1677
 
 
1678
 
  setKilled(Session::KILL_CONNECTION);
1679
 
 
 
1612
    LOCK_thread_count.lock();
 
1613
  killed= Session::KILL_CONNECTION;
1680
1614
  if (client->isConnected())
1681
1615
  {
1682
1616
    if (errcode)
1686
1620
    }
1687
1621
    client->close();
1688
1622
  }
1689
 
 
1690
1623
  if (should_lock)
1691
 
  {
1692
 
    session::Cache::singleton().mutex().unlock();
1693
 
  }
 
1624
    (void) LOCK_thread_count.unlock();
1694
1625
}
1695
1626
 
1696
1627
void Session::reset_for_next_command()
1718
1649
  Close all temporary tables created by 'CREATE TEMPORARY TABLE' for thread
1719
1650
*/
1720
1651
 
1721
 
void Open_tables_state::close_temporary_tables()
 
1652
void Session::close_temporary_tables()
1722
1653
{
1723
1654
  Table *table;
1724
1655
  Table *tmp_next;
1738
1669
  unlink from session->temporary tables and close temporary table
1739
1670
*/
1740
1671
 
1741
 
void Open_tables_state::close_temporary_table(Table *table)
 
1672
void Session::close_temporary_table(Table *table)
1742
1673
{
1743
1674
  if (table->getPrev())
1744
1675
  {
1774
1705
  If this is needed, use close_temporary_table()
1775
1706
*/
1776
1707
 
1777
 
void Open_tables_state::nukeTable(Table *table)
 
1708
void Session::nukeTable(Table *table)
1778
1709
{
1779
1710
  plugin::StorageEngine *table_type= table->getShare()->db_type();
1780
1711
 
1805
1736
 
1806
1737
user_var_entry *Session::getVariable(LEX_STRING &name, bool create_if_not_exists)
1807
1738
{
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);
 
1739
  user_var_entry *entry= NULL;
 
1740
  UserVarsRange ppp= user_vars.equal_range(std::string(name.str, name.length));
1814
1741
 
1815
1742
  for (UserVars::iterator iter= ppp.first;
1816
 
       iter != ppp.second; ++iter)
 
1743
         iter != ppp.second; ++iter)
1817
1744
  {
1818
 
    return (*iter).second;
 
1745
    entry= (*iter).second;
1819
1746
  }
1820
1747
 
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)
 
1748
  if ((entry == NULL) && create_if_not_exists)
1833
1749
  {
1834
 
    delete entry;
 
1750
    entry= new (nothrow) user_var_entry(name.str, query_id);
 
1751
 
 
1752
    if (entry == NULL)
 
1753
      return NULL;
 
1754
 
 
1755
    std::pair<UserVars::iterator, bool> returnable= user_vars.insert(make_pair(std::string(name.str, name.length), entry));
 
1756
 
 
1757
    if (not returnable.second)
 
1758
    {
 
1759
      delete entry;
 
1760
      return NULL;
 
1761
    }
1835
1762
  }
1836
1763
 
1837
1764
  return entry;
1838
1765
}
1839
1766
 
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()
 
1767
void Session::mark_temp_tables_as_free_for_reuse()
1852
1768
{
1853
1769
  for (Table *table= temporary_tables ; table ; table= table->getNext())
1854
1770
  {
1855
 
    if (table->query_id == getQueryId())
 
1771
    if (table->query_id == query_id)
1856
1772
    {
1857
1773
      table->query_id= 0;
1858
1774
      table->cursor->ha_reset();
1864
1780
{
1865
1781
  for (; table ; table= table->getNext())
1866
1782
  {
1867
 
    if (table->query_id == getQueryId())
 
1783
    if (table->query_id == query_id)
1868
1784
    {
1869
1785
      table->query_id= 0;
1870
1786
      table->cursor->ha_reset();
1883
1799
*/
1884
1800
void Session::close_thread_tables()
1885
1801
{
1886
 
  clearDerivedTables();
 
1802
  if (derived_tables)
 
1803
    derived_tables= NULL; // They should all be invalid by this point
1887
1804
 
1888
1805
  /*
1889
1806
    Mark all temporary tables used by this statement as free for reuse.
1916
1833
      handled either before writing a query log event (inside
1917
1834
      binlog_query()) or when preparing a pending event.
1918
1835
     */
1919
 
    unlockTables(lock);
 
1836
    mysql_unlock_tables(this, lock);
1920
1837
    lock= 0;
1921
1838
  }
1922
1839
  /*
1923
 
    Note that we need to hold table::Cache::singleton().mutex() while changing the
 
1840
    Note that we need to hold LOCK_open while changing the
1924
1841
    open_tables list. Another thread may work on it.
1925
 
    (See: table::Cache::singleton().removeTable(), mysql_wait_completed_table())
 
1842
    (See: remove_table_from_cache(), mysql_wait_completed_table())
1926
1843
    Closing a MERGE child before the parent would be fatal if the
1927
1844
    other thread tries to abort the MERGE lock in between.
1928
1845
  */
1961
1878
    close_tables_for_reopen(&tables);
1962
1879
  }
1963
1880
  if ((mysql_handle_derived(lex, &mysql_derived_prepare) ||
1964
 
       (
 
1881
       (fill_derived_tables() &&
1965
1882
        mysql_handle_derived(lex, &mysql_derived_filling))))
1966
1883
    return true;
1967
1884
 
1968
1885
  return false;
1969
1886
}
1970
1887
 
 
1888
bool Session::openTables(TableList *tables, uint32_t flags)
 
1889
{
 
1890
  uint32_t counter;
 
1891
  bool ret= fill_derived_tables();
 
1892
  assert(ret == false);
 
1893
  if (open_tables_from_list(&tables, &counter, flags) ||
 
1894
      mysql_handle_derived(lex, &mysql_derived_prepare))
 
1895
  {
 
1896
    return true;
 
1897
  }
 
1898
  return false;
 
1899
}
 
1900
 
1971
1901
/*
1972
1902
  @note "best_effort" is used in cases were if a failure occurred on this
1973
1903
  operation it would not be surprising because we are only removing because there
1974
1904
  might be an issue (lame engines).
1975
1905
*/
1976
1906
 
1977
 
bool Open_tables_state::rm_temporary_table(const TableIdentifier &identifier, bool best_effort)
 
1907
bool Session::rm_temporary_table(TableIdentifier &identifier, bool best_effort)
1978
1908
{
1979
 
  if (plugin::StorageEngine::dropTable(*static_cast<Session *>(this), identifier))
 
1909
  if (plugin::StorageEngine::dropTable(*this, identifier))
1980
1910
  {
1981
1911
    if (not best_effort)
1982
1912
    {
1983
 
      std::string path;
1984
 
      identifier.getSQLPath(path);
1985
1913
      errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
1986
 
                    path.c_str(), errno);
 
1914
                    identifier.getSQLPath().c_str(), errno);
1987
1915
    }
1988
1916
 
1989
1917
    return true;
1992
1920
  return false;
1993
1921
}
1994
1922
 
1995
 
bool Open_tables_state::rm_temporary_table(plugin::StorageEngine *base, const TableIdentifier &identifier)
 
1923
bool Session::rm_temporary_table(plugin::StorageEngine *base, TableIdentifier &identifier)
1996
1924
{
1997
1925
  assert(base);
1998
1926
 
1999
 
  if (plugin::StorageEngine::dropTable(*static_cast<Session *>(this), *base, identifier))
 
1927
  if (plugin::StorageEngine::dropTable(*this, *base, identifier))
2000
1928
  {
2001
 
    std::string path;
2002
 
    identifier.getSQLPath(path);
2003
1929
    errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
2004
 
                  path.c_str(), errno);
 
1930
                  identifier.getSQLPath().c_str(), errno);
2005
1931
 
2006
1932
    return true;
2007
1933
  }
2013
1939
  @note this will be removed, I am looking through Hudson to see if it is finding
2014
1940
  any tables that are missed during cleanup.
2015
1941
*/
2016
 
void Open_tables_state::dumpTemporaryTableNames(const char *foo)
 
1942
void Session::dumpTemporaryTableNames(const char *foo)
2017
1943
{
2018
1944
  Table *table;
2019
1945
 
2037
1963
      cerr << "\t\t Proto " << proto->schema() << " " << proto->name() << "\n";
2038
1964
    }
2039
1965
    else
2040
 
    {
2041
1966
      cerr << "\tTabl;e Name " << table->getShare()->getSchemaName() << "." << table->getShare()->getTableName() << " : " << answer << "\n";
2042
 
    }
2043
1967
  }
2044
1968
}
2045
1969
 
2046
 
bool Session::TableMessages::storeTableMessage(const TableIdentifier &identifier, message::Table &table_message)
 
1970
bool Session::storeTableMessage(const TableIdentifier &identifier, message::Table &table_message)
2047
1971
{
2048
1972
  table_message_cache.insert(make_pair(identifier.getPath(), table_message));
2049
1973
 
2050
1974
  return true;
2051
1975
}
2052
1976
 
2053
 
bool Session::TableMessages::removeTableMessage(const TableIdentifier &identifier)
 
1977
bool Session::removeTableMessage(const TableIdentifier &identifier)
2054
1978
{
2055
1979
  TableMessageCache::iterator iter;
2056
1980
 
2064
1988
  return true;
2065
1989
}
2066
1990
 
2067
 
bool Session::TableMessages::getTableMessage(const TableIdentifier &identifier, message::Table &table_message)
 
1991
bool Session::getTableMessage(const TableIdentifier &identifier, message::Table &table_message)
2068
1992
{
2069
1993
  TableMessageCache::iterator iter;
2070
1994
 
2078
2002
  return true;
2079
2003
}
2080
2004
 
2081
 
bool Session::TableMessages::doesTableMessageExist(const TableIdentifier &identifier)
 
2005
bool Session::doesTableMessageExist(const TableIdentifier &identifier)
2082
2006
{
2083
2007
  TableMessageCache::iterator iter;
2084
2008
 
2092
2016
  return true;
2093
2017
}
2094
2018
 
2095
 
bool Session::TableMessages::renameTableMessage(const TableIdentifier &from, const TableIdentifier &to)
 
2019
bool Session::renameTableMessage(const TableIdentifier &from, const TableIdentifier &to)
2096
2020
{
2097
2021
  TableMessageCache::iterator iter;
2098
2022
 
2111
2035
  return true;
2112
2036
}
2113
2037
 
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 */
 
2038
TableShareInstance *Session::getTemporaryShare(TableIdentifier::Type type_arg)
 
2039
{
 
2040
  temporary_shares.push_back(new TableShareInstance(type_arg)); // This will not go into the tableshare cache, so no key is used.
 
2041
 
 
2042
  TableShareInstance *tmp_share= temporary_shares.back();
 
2043
 
 
2044
  assert(tmp_share);
 
2045
 
 
2046
  return tmp_share;
 
2047
}
2180
2048
 
2181
2049
} /* namespace drizzled */