~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/session.cc

  • Committer: Brian Aker
  • Date: 2010-09-13 21:43:18 UTC
  • mto: (1768.2.1 trunk)
  • mto: This revision was merged to the branch mainline in revision 1770.
  • Revision ID: brian@tangent.org-20100913214318-b5tdvn64qvtvybnj
Use full path for opening up directory files when checking for types.

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