~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/session.cc

  • Committer: Barry.Leslie at PrimeBase
  • Date: 2010-10-20 20:41:00 UTC
  • mfrom: (1863 staging)
  • mto: This revision was merged to the branch mainline in revision 1871.
  • Revision ID: barry.leslie@primebase.com-20101020204100-oyj6p5cfssjw3p62
Merged with trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
3
 *
4
 
 *  Copyright (C) 2008 Sun Microsystems, Inc.
 
4
 *  Copyright (C) 2008 Sun Microsystems
5
5
 *
6
6
 *  This program is free software; you can redistribute it and/or modify
7
7
 *  it under the terms of the GNU General Public License as published by
21
21
 * @file Implementation of the Session class and API
22
22
 */
23
23
 
24
 
#include <config.h>
25
 
 
26
 
#include <drizzled/copy_field.h>
27
 
#include <drizzled/data_home.h>
28
 
#include <drizzled/display.h>
29
 
#include <drizzled/drizzled.h>
 
24
#include "config.h"
 
25
#include <drizzled/session.h>
 
26
#include "drizzled/session_list.h"
 
27
#include <sys/stat.h>
30
28
#include <drizzled/error.h>
31
29
#include <drizzled/gettext.h>
32
 
#include <drizzled/identifier.h>
33
 
#include <drizzled/internal/iocache.h>
34
 
#include <drizzled/internal/thread_var.h>
35
 
#include <drizzled/internal_error_handler.h>
 
30
#include <drizzled/query_id.h>
 
31
#include <drizzled/data_home.h>
 
32
#include <drizzled/sql_base.h>
 
33
#include <drizzled/lock.h>
36
34
#include <drizzled/item/cache.h>
37
 
#include <drizzled/item/empty_string.h>
38
35
#include <drizzled/item/float.h>
39
36
#include <drizzled/item/return_int.h>
40
 
#include <drizzled/lock.h>
41
 
#include <drizzled/plugin/authentication.h>
 
37
#include <drizzled/item/empty_string.h>
 
38
#include <drizzled/show.h>
42
39
#include <drizzled/plugin/client.h>
43
 
#include <drizzled/plugin/event_observer.h>
44
 
#include <drizzled/plugin/logging.h>
45
 
#include <drizzled/plugin/query_rewrite.h>
46
 
#include <drizzled/plugin/scheduler.h>
47
 
#include <drizzled/plugin/transactional_storage_engine.h>
48
 
#include <drizzled/probes.h>
49
 
#include <drizzled/pthread_globals.h>
50
 
#include <drizzled/query_id.h>
51
 
#include <drizzled/refresh_version.h>
52
 
#include <drizzled/select_dump.h>
53
 
#include <drizzled/select_exists_subselect.h>
54
 
#include <drizzled/select_export.h>
55
 
#include <drizzled/select_max_min_finder_subselect.h>
56
 
#include <drizzled/select_singlerow_subselect.h>
57
 
#include <drizzled/select_subselect.h>
58
 
#include <drizzled/select_to_file.h>
59
 
#include <drizzled/session.h>
60
 
#include <drizzled/session/cache.h>
61
 
#include <drizzled/show.h>
62
 
#include <drizzled/sql_base.h>
63
 
#include <drizzled/table/singular.h>
64
 
#include <drizzled/table_proto.h>
65
 
#include <drizzled/tmp_table_param.h>
66
 
#include <drizzled/transaction_services.h>
67
 
#include <drizzled/user_var_entry.h>
68
 
#include <drizzled/util/functors.h>
69
 
#include <plugin/myisam/myisam.h>
70
 
 
 
40
#include "drizzled/plugin/scheduler.h"
 
41
#include "drizzled/plugin/authentication.h"
 
42
#include "drizzled/plugin/logging.h"
 
43
#include "drizzled/plugin/transactional_storage_engine.h"
 
44
#include "drizzled/probes.h"
 
45
#include "drizzled/table_proto.h"
 
46
#include "drizzled/db.h"
 
47
#include "drizzled/pthread_globals.h"
 
48
#include "drizzled/transaction_services.h"
 
49
#include "drizzled/drizzled.h"
 
50
 
 
51
#include "drizzled/table/instance.h"
 
52
 
 
53
#include "plugin/myisam/myisam.h"
 
54
#include "drizzled/internal/iocache.h"
 
55
#include "drizzled/internal/thread_var.h"
 
56
#include "drizzled/plugin/event_observer.h"
 
57
 
 
58
#include "drizzled/util/functors.h"
 
59
 
 
60
#include <fcntl.h>
71
61
#include <algorithm>
72
62
#include <climits>
73
 
#include <fcntl.h>
74
 
#include <sys/stat.h>
75
 
 
76
 
#include <boost/filesystem.hpp>
77
 
#include <boost/checked_delete.hpp>
78
 
 
79
 
#include <drizzled/util/backtrace.h>
80
 
 
81
 
#include <drizzled/schema.h>
 
63
#include "boost/filesystem.hpp" 
82
64
 
83
65
using namespace std;
84
66
 
99
81
{
100
82
  return length == other.length &&
101
83
         field_name.length == other.field_name.length &&
102
 
    !my_strcasecmp(system_charset_info, field_name.str, other.field_name.str);
 
84
         !strcmp(field_name.str, other.field_name.str);
103
85
}
104
86
 
105
87
Open_tables_state::Open_tables_state(uint64_t version_arg) :
112
94
/*
113
95
  The following functions form part of the C plugin API
114
96
*/
115
 
int tmpfile(const char *prefix)
 
97
int mysql_tmpfile(const char *prefix)
116
98
{
117
99
  char filename[FN_REFLEN];
118
100
  int fd = internal::create_temp_file(filename, drizzle_tmpdir.c_str(), prefix, MYF(MY_WME));
123
105
  return fd;
124
106
}
125
107
 
 
108
int session_tablespace_op(const Session *session)
 
109
{
 
110
  return test(session->tablespace_op);
 
111
}
 
112
 
 
113
/**
 
114
   Set the process info field of the Session structure.
 
115
 
 
116
   This function is used by plug-ins. Internally, the
 
117
   Session::set_proc_info() function should be used.
 
118
 
 
119
   @see Session::set_proc_info
 
120
 */
 
121
void set_session_proc_info(Session *session, const char *info)
 
122
{
 
123
  session->set_proc_info(info);
 
124
}
 
125
 
 
126
const char *get_session_proc_info(Session *session)
 
127
{
 
128
  return session->get_proc_info();
 
129
}
 
130
 
126
131
void **Session::getEngineData(const plugin::MonitoredInTransaction *monitored)
127
132
{
128
133
  return static_cast<void **>(&ha_data[monitored->getId()].ha_ptr);
139
144
  return session->options & test_options;
140
145
}
141
146
 
142
 
Session::Session(plugin::Client *client_arg, catalog::Instance::shared_ptr catalog_arg) :
 
147
int session_sql_command(const Session *session)
 
148
{
 
149
  return (int) session->lex->sql_command;
 
150
}
 
151
 
 
152
enum_tx_isolation session_tx_isolation(const Session *session)
 
153
{
 
154
  return (enum_tx_isolation)session->variables.tx_isolation;
 
155
}
 
156
 
 
157
Session::Session(plugin::Client *client_arg) :
143
158
  Open_tables_state(refresh_version),
144
159
  mem_root(&main_mem_root),
145
 
  xa_id(0),
146
160
  lex(&main_lex),
147
 
  query(new std::string),
148
 
  _schema(new std::string("")),
 
161
  query(),
149
162
  client(client_arg),
150
163
  scheduler(NULL),
151
164
  scheduler_arg(NULL),
152
165
  lock_id(&main_lock_id),
153
 
  thread_stack(NULL),
154
 
  security_ctx(identifier::User::make_shared()),
155
 
  _where(Session::DEFAULT_WHERE),
156
 
  dbug_sentry(Session_SENTRY_MAGIC),
157
 
  mysys_var(0),
158
 
  command(COM_CONNECT),
159
 
  file_id(0),
160
 
  _epoch(boost::gregorian::date(1970,1,1)),
161
 
  _connect_time(boost::posix_time::microsec_clock::universal_time()),
162
 
  utime_after_lock(0),
 
166
  user_time(0),
163
167
  ha_data(plugin::num_trx_monitored_objects),
164
 
  query_id(0),
165
 
  warn_query_id(0),
166
 
  concurrent_execute_allowed(true),
167
168
  arg_of_last_insert_id_function(false),
168
169
  first_successful_insert_id_in_prev_stmt(0),
169
170
  first_successful_insert_id_in_cur_stmt(0),
170
171
  limit_found_rows(0),
171
 
  options(session_startup_options),
172
 
  row_count_func(-1),
173
 
  sent_row_count(0),
174
 
  examined_row_count(0),
175
 
  used_tables(0),
176
 
  total_warn_count(0),
177
 
  col_access(0),
178
 
  statement_id_counter(0),
179
 
  row_count(0),
180
 
  thread_id(0),
181
 
  tmp_table(0),
182
 
  _global_read_lock(NONE),
183
 
  count_cuted_fields(CHECK_FIELD_ERROR_FOR_NULL),
184
 
  _killed(NOT_KILLED),
 
172
  global_read_lock(0),
185
173
  some_tables_deleted(false),
186
174
  no_errors(false),
187
175
  password(false),
188
176
  is_fatal_error(false),
189
177
  transaction_rollback_request(false),
190
178
  is_fatal_sub_stmt_error(0),
 
179
  derived_tables_processing(false),
191
180
  tablespace_op(false),
192
 
  derived_tables_processing(false),
193
181
  m_lip(NULL),
194
182
  cached_table(0),
195
183
  transaction_message(NULL),
196
184
  statement_message(NULL),
197
185
  session_event_observers(NULL),
198
 
  _catalog(catalog_arg),
199
186
  use_usage(false)
200
187
{
 
188
  memset(process_list_info, 0, PROCESS_LIST_WIDTH);
201
189
  client->setSession(this);
202
190
 
203
191
  /*
206
194
    will be re-initialized in init_for_queries().
207
195
  */
208
196
  memory::init_sql_alloc(&main_mem_root, memory::ROOT_MIN_BLOCK_SIZE, 0);
 
197
  thread_stack= NULL;
 
198
  count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
 
199
  killed= NOT_KILLED;
 
200
  col_access= 0;
 
201
  tmp_table= 0;
 
202
  used_tables= 0;
209
203
  cuted_fields= sent_row_count= row_count= 0L;
 
204
  row_count_func= -1;
 
205
  statement_id_counter= 0UL;
210
206
  // Must be reset to handle error with Session's created for init of mysqld
211
207
  lex->current_select= 0;
 
208
  start_time=(time_t) 0;
 
209
  start_utime= 0L;
 
210
  utime_after_lock= 0L;
212
211
  memset(&variables, 0, sizeof(variables));
 
212
  thread_id= 0;
 
213
  file_id = 0;
 
214
  query_id= 0;
 
215
  warn_query_id= 0;
 
216
  mysys_var= 0;
213
217
  scoreboard_index= -1;
 
218
  dbug_sentry=Session_SENTRY_MAGIC;
214
219
  cleanup_done= abort_on_warning= no_warnings_for_error= false;  
215
220
 
216
221
  /* query_cache init */
219
224
 
220
225
  /* Variables with default values */
221
226
  proc_info="login";
 
227
  where= Session::DEFAULT_WHERE;
 
228
  command= COM_CONNECT;
222
229
 
223
230
  plugin_sessionvar_init(this);
224
231
  /*
228
235
  */
229
236
  variables.pseudo_thread_id= thread_id;
230
237
  server_status= SERVER_STATUS_AUTOCOMMIT;
 
238
  options= session_startup_options;
231
239
 
232
240
  if (variables.max_join_size == HA_POS_ERROR)
233
241
    options |= OPTION_BIG_SELECTS;
237
245
  open_options=ha_open_options;
238
246
  update_lock_default= TL_WRITE;
239
247
  session_tx_isolation= (enum_tx_isolation) variables.tx_isolation;
240
 
  warn_list.clear();
 
248
  warn_list.empty();
241
249
  memset(warn_count, 0, sizeof(warn_count));
 
250
  total_warn_count= 0;
242
251
  memset(&status_var, 0, sizeof(status_var));
243
252
 
244
253
  /* Initialize sub structures */
274
283
  m_internal_handler= handler;
275
284
}
276
285
 
277
 
bool Session::handle_error(drizzled::error_t sql_errno, const char *message,
278
 
                           DRIZZLE_ERROR::enum_warning_level level)
 
286
bool Session::handle_error(uint32_t sql_errno, const char *message,
 
287
                       DRIZZLE_ERROR::enum_warning_level level)
279
288
{
280
289
  if (m_internal_handler)
281
290
  {
311
320
  m_internal_handler= NULL;
312
321
}
313
322
 
314
 
void Session::get_xid(DrizzleXid *xid)
 
323
void Session::get_xid(DRIZZLE_XID *xid)
315
324
{
316
 
  *xid = *(DrizzleXid *) &transaction.xid_state.xid;
 
325
  *xid = *(DRIZZLE_XID *) &transaction.xid_state.xid;
317
326
}
318
327
 
319
328
/* Do operations that may take a long time */
322
331
{
323
332
  assert(cleanup_done == false);
324
333
 
325
 
  setKilled(KILL_CONNECTION);
 
334
  killed= KILL_CONNECTION;
326
335
#ifdef ENABLE_WHEN_BINLOG_WILL_BE_ABLE_TO_PREPARE
327
336
  if (transaction.xid_state.xa_state == XA_PREPARED)
328
337
  {
331
340
#endif
332
341
  {
333
342
    TransactionServices &transaction_services= TransactionServices::singleton();
334
 
    transaction_services.rollbackTransaction(*this, true);
 
343
    transaction_services.rollbackTransaction(this, true);
335
344
    xid_cache_delete(&transaction.xid_state);
336
345
  }
337
346
 
340
349
       iter++)
341
350
  {
342
351
    user_var_entry *entry= (*iter).second;
343
 
    boost::checked_delete(entry);
 
352
    delete entry;
344
353
  }
345
354
  user_vars.clear();
346
355
 
348
357
  close_temporary_tables();
349
358
 
350
359
  if (global_read_lock)
351
 
  {
352
 
    unlockGlobalReadLock();
353
 
  }
 
360
    unlock_global_read_lock(this);
354
361
 
355
362
  cleanup_done= true;
356
363
}
359
366
{
360
367
  this->checkSentry();
361
368
 
362
 
  if (client and client->isConnected())
 
369
  if (client->isConnected())
363
370
  {
364
 
    assert(security_ctx);
365
371
    if (global_system_variables.log_warnings)
366
 
    {
367
 
      errmsg_printf(error::WARN, ER(ER_FORCING_CLOSE),
368
 
                    internal::my_progname,
369
 
                    thread_id,
370
 
                    security_ctx->username().c_str());
371
 
    }
372
 
 
373
 
    disconnect();
 
372
        errmsg_printf(ERRMSG_LVL_WARN, ER(ER_FORCING_CLOSE),internal::my_progname,
 
373
                      thread_id,
 
374
                      (getSecurityContext().getUser().c_str() ?
 
375
                       getSecurityContext().getUser().c_str() : ""));
 
376
    disconnect(0, false);
374
377
  }
375
378
 
376
379
  /* Close connection */
377
 
  if (client)
378
 
  {
379
 
    client->close();
380
 
    boost::checked_delete(client);
381
 
    client= NULL;
382
 
  }
 
380
  client->close();
 
381
  delete client;
383
382
 
384
383
  if (cleanup_done == false)
385
384
    cleanup();
397
396
 
398
397
  plugin::Logging::postEndDo(this);
399
398
  plugin::EventObserver::deregisterSessionEvents(*this); 
400
 
}
401
 
 
402
 
void Session::setClient(plugin::Client *client_arg)
403
 
{
404
 
  client= client_arg;
405
 
  client->setSession(this);
406
 
}
407
 
 
408
 
void Session::awake(Session::killed_state_t state_to_set)
409
 
{
410
 
  if ((state_to_set == Session::KILL_QUERY) and (command == COM_SLEEP))
411
 
    return;
412
 
 
 
399
 
 
400
  for (PropertyMap::iterator iter= life_properties.begin(); iter != life_properties.end(); iter++)
 
401
  {
 
402
    delete (*iter).second;
 
403
  }
 
404
  life_properties.clear();
 
405
 
 
406
  /* Ensure that no one is using Session */
 
407
  LOCK_delete.unlock();
 
408
}
 
409
 
 
410
void Session::awake(Session::killed_state state_to_set)
 
411
{
413
412
  this->checkSentry();
414
 
 
415
 
  setKilled(state_to_set);
416
 
  scheduler->killSession(this);
417
 
 
 
413
  safe_mutex_assert_owner(&LOCK_delete);
 
414
 
 
415
  killed= state_to_set;
418
416
  if (state_to_set != Session::KILL_QUERY)
419
417
  {
 
418
    scheduler->killSession(this);
420
419
    DRIZZLE_CONNECTION_DONE(thread_id);
421
420
  }
422
 
 
423
421
  if (mysys_var)
424
422
  {
425
423
    boost_unique_lock_t scopedLock(mysys_var->mutex);
515
513
{
516
514
  if (storeGlobals())
517
515
  {
518
 
    disconnect(ER_OUT_OF_RESOURCES);
 
516
    disconnect(ER_OUT_OF_RESOURCES, true);
519
517
    status_var.aborted_connects++;
520
518
    return true;
521
519
  }
526
524
{
527
525
  if (initGlobals() || authenticate())
528
526
  {
529
 
    disconnect();
 
527
    disconnect(0, true);
530
528
    return;
531
529
  }
532
530
 
533
531
  prepareForQueries();
534
532
 
535
 
  while (not client->haveError() && getKilled() != KILL_CONNECTION)
 
533
  while (! client->haveError() && killed != KILL_CONNECTION)
536
534
  {
537
 
    if (not executeStatement())
 
535
    if (! executeStatement())
538
536
      break;
539
537
  }
540
538
 
541
 
  disconnect();
 
539
  disconnect(0, true);
542
540
}
543
541
 
544
 
bool Session::schedule(Session::shared_ptr &arg)
 
542
bool Session::schedule()
545
543
{
546
 
  arg->scheduler= plugin::Scheduler::getScheduler();
547
 
  assert(arg->scheduler);
548
 
 
549
 
  ++connection_count;
550
 
 
551
 
  long current_connections= connection_count;
552
 
 
553
 
  if (current_connections > 0 and static_cast<uint64_t>(current_connections) > current_global_counters.max_used_connections)
 
544
  scheduler= plugin::Scheduler::getScheduler();
 
545
  assert(scheduler);
 
546
 
 
547
  connection_count.increment();
 
548
 
 
549
  if (connection_count > current_global_counters.max_used_connections)
554
550
  {
555
 
    current_global_counters.max_used_connections= static_cast<uint64_t>(connection_count);
 
551
    current_global_counters.max_used_connections= connection_count;
556
552
  }
557
553
 
558
554
  current_global_counters.connections++;
559
 
  arg->thread_id= arg->variables.pseudo_thread_id= global_thread_id++;
560
 
 
561
 
  session::Cache::singleton().insert(arg);
562
 
 
563
 
  if (unlikely(plugin::EventObserver::connectSession(*arg)))
564
 
  {
565
 
    // We should do something about an error...
566
 
  }
567
 
 
568
 
  if (plugin::Scheduler::getScheduler()->addSession(arg))
569
 
  {
570
 
    DRIZZLE_CONNECTION_START(arg->getSessionId());
 
555
  thread_id= variables.pseudo_thread_id= global_thread_id++;
 
556
 
 
557
  {
 
558
    boost::mutex::scoped_lock scoped(LOCK_thread_count);
 
559
    getSessionList().push_back(this);
 
560
  }
 
561
 
 
562
  if (unlikely(plugin::EventObserver::connectSession(*this)))
 
563
  {
 
564
    // We should do something about an error...
 
565
  }
 
566
 
 
567
  if (unlikely(plugin::EventObserver::connectSession(*this)))
 
568
  {
 
569
    // We should do something about an error...
 
570
  }
 
571
 
 
572
  if (scheduler->addSession(this))
 
573
  {
 
574
    DRIZZLE_CONNECTION_START(thread_id);
571
575
    char error_message_buff[DRIZZLE_ERRMSG_SIZE];
572
576
 
573
 
    arg->setKilled(Session::KILL_CONNECTION);
 
577
    killed= Session::KILL_CONNECTION;
574
578
 
575
 
    arg->status_var.aborted_connects++;
 
579
    status_var.aborted_connects++;
576
580
 
577
581
    /* Can't use my_error() since store_globals has not been called. */
578
582
    /* TODO replace will better error message */
579
583
    snprintf(error_message_buff, sizeof(error_message_buff),
580
584
             ER(ER_CANT_CREATE_THREAD), 1);
581
 
    arg->client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
582
 
 
 
585
    client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
583
586
    return true;
584
587
  }
585
588
 
587
590
}
588
591
 
589
592
 
590
 
/*
591
 
  Is this session viewable by the current user?
592
 
*/
593
 
bool Session::isViewable(identifier::User::const_reference user_arg) const
594
 
{
595
 
  return plugin::Authorization::isAuthorized(user_arg, *this, false);
596
 
}
597
 
 
598
 
 
599
593
const char* Session::enter_cond(boost::condition_variable_any &cond, boost::mutex &mutex, const char* msg)
600
594
{
601
595
  const char* old_msg = get_proc_info();
623
617
 
624
618
bool Session::authenticate()
625
619
{
 
620
  lex_start(this);
626
621
  if (client->authenticate())
627
622
    return false;
628
623
 
635
630
                        const std::string &in_db)
636
631
{
637
632
  bool is_authenticated=
638
 
    plugin::Authentication::isAuthenticated(*user(), passwd_str);
 
633
    plugin::Authentication::isAuthenticated(getSecurityContext(),
 
634
                                            passwd_str);
639
635
 
640
636
  if (is_authenticated != true)
641
637
  {
647
643
  /* Change database if necessary */
648
644
  if (not in_db.empty())
649
645
  {
650
 
    identifier::Schema identifier(in_db);
651
 
    if (schema::change(*this, identifier))
 
646
    SchemaIdentifier identifier(in_db);
 
647
    if (mysql_change_db(this, identifier))
652
648
    {
653
 
      /* change_db() has pushed the error message. */
 
649
      /* mysql_change_db() has pushed the error message. */
654
650
      return false;
655
651
    }
656
652
  }
677
673
  main_da.reset_diagnostics_area();
678
674
 
679
675
  if (client->readCommand(&l_packet, &packet_length) == false)
680
 
  {
681
676
    return false;
682
 
  }
683
677
 
684
 
  if (getKilled() == KILL_CONNECTION)
 
678
  if (killed == KILL_CONNECTION)
685
679
    return false;
686
680
 
687
681
  if (packet_length == 0)
688
682
    return true;
689
683
 
690
 
  l_command= static_cast<enum_server_command>(l_packet[0]);
 
684
  l_command= (enum enum_server_command) (unsigned char) l_packet[0];
691
685
 
692
686
  if (command >= COM_END)
693
687
    command= COM_END;                           // Wrong command
694
688
 
695
689
  assert(packet_length);
696
 
  return not dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
 
690
  return ! dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
697
691
}
698
692
 
699
693
bool Session::readAndStoreQuery(const char *in_packet, uint32_t in_packet_length)
705
699
    in_packet_length--;
706
700
  }
707
701
  const char *pos= in_packet + in_packet_length; /* Point at end null */
708
 
  while (in_packet_length > 0 && (pos[-1] == ';' || my_isspace(charset() ,pos[-1])))
 
702
  while (in_packet_length > 0 &&
 
703
         (pos[-1] == ';' || my_isspace(charset() ,pos[-1])))
709
704
  {
710
705
    pos--;
711
706
    in_packet_length--;
712
707
  }
713
708
 
714
 
  std::string *new_query= new std::string(in_packet, in_packet + in_packet_length);
715
 
  // We can not be entirely sure _schema has a value
716
 
  if (_schema)
717
 
  {
718
 
    plugin::QueryRewriter::rewriteQuery(*_schema, *new_query);
719
 
  }
720
 
  query.reset(new_query);
721
 
  _state.reset(new session::State(in_packet, in_packet_length));
 
709
  query.assign(in_packet, in_packet + in_packet_length);
722
710
 
723
711
  return true;
724
712
}
743
731
       * (Which of course should never happen...)
744
732
       */
745
733
      server_status&= ~SERVER_STATUS_IN_TRANS;
746
 
      if (transaction_services.commitTransaction(*this, true))
 
734
      if (transaction_services.commitTransaction(this, true))
747
735
        result= false;
748
736
      options&= ~(OPTION_BEGIN);
749
737
      break;
760
748
    case ROLLBACK_AND_CHAIN:
761
749
    {
762
750
      server_status&= ~SERVER_STATUS_IN_TRANS;
763
 
      if (transaction_services.rollbackTransaction(*this, true))
 
751
      if (transaction_services.rollbackTransaction(this, true))
764
752
        result= false;
765
753
      options&= ~(OPTION_BEGIN);
766
754
      if (result == true && (completion == ROLLBACK_AND_CHAIN))
773
761
  }
774
762
 
775
763
  if (result == false)
776
 
  {
777
 
    my_error(static_cast<drizzled::error_t>(killed_errno()), MYF(0));
778
 
  }
 
764
    my_error(killed_errno(), MYF(0));
779
765
  else if ((result == true) && do_release)
780
 
  {
781
 
    setKilled(Session::KILL_CONNECTION);
782
 
  }
 
766
    killed= Session::KILL_CONNECTION;
783
767
 
784
768
  return result;
785
769
}
797
781
  if (options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
798
782
  {
799
783
    server_status&= ~SERVER_STATUS_IN_TRANS;
800
 
    if (transaction_services.commitTransaction(*this, true))
 
784
    if (transaction_services.commitTransaction(this, true))
801
785
      result= false;
802
786
  }
803
787
  options&= ~(OPTION_BEGIN);
808
792
{
809
793
  bool result= true;
810
794
 
811
 
  assert(! inTransaction());
812
 
 
813
 
  options|= OPTION_BEGIN;
814
 
  server_status|= SERVER_STATUS_IN_TRANS;
815
 
 
816
 
  if (plugin::TransactionalStorageEngine::notifyStartTransaction(this, opt))
 
795
  if (! endActiveTransaction())
817
796
  {
818
797
    result= false;
819
798
  }
 
799
  else
 
800
  {
 
801
    options|= OPTION_BEGIN;
 
802
    server_status|= SERVER_STATUS_IN_TRANS;
 
803
 
 
804
    if (plugin::TransactionalStorageEngine::notifyStartTransaction(this, opt))
 
805
    {
 
806
      result= false;
 
807
    }
 
808
  }
820
809
 
821
810
  return result;
822
811
}
838
827
    first_successful_insert_id_in_cur_stmt= 0;
839
828
    substitute_null_with_insert_id= true;
840
829
  }
841
 
 
842
830
  arg_of_last_insert_id_function= false;
843
 
 
844
831
  /* Free Items that were created during this execution */
845
832
  free_items();
846
 
 
847
 
  /* Reset _where. */
848
 
  _where= Session::DEFAULT_WHERE;
 
833
  /* Reset where. */
 
834
  where= Session::DEFAULT_WHERE;
849
835
 
850
836
  /* Reset the temporary shares we built */
851
837
  for_each(temporary_shares.begin(),
876
862
                                     bool allocate_lex_string)
877
863
{
878
864
  if (allocate_lex_string)
879
 
    if (!(lex_str= (LEX_STRING *)getMemRoot()->allocate(sizeof(LEX_STRING))))
 
865
    if (!(lex_str= (LEX_STRING *)alloc(sizeof(LEX_STRING))))
880
866
      return 0;
881
867
  if (!(lex_str->str= mem_root->strmake_root(str, length)))
882
868
    return 0;
922
908
  return (result->send_fields(field_list));
923
909
}
924
910
 
925
 
void select_result::send_error(drizzled::error_t errcode, const char *err)
 
911
void select_result::send_error(uint32_t errcode, const char *err)
926
912
{
927
913
  my_message(errcode, err, MYF(0));
928
914
}
931
917
  Handling writing to file
932
918
************************************************************************/
933
919
 
934
 
void select_to_file::send_error(drizzled::error_t errcode,const char *err)
 
920
void select_to_file::send_error(uint32_t errcode,const char *err)
935
921
{
936
922
  my_message(errcode, err, MYF(0));
937
923
  if (file > 0)
938
924
  {
939
 
    (void) cache->end_io_cache();
 
925
    (void) end_io_cache(cache);
940
926
    (void) internal::my_close(file, MYF(0));
941
927
    (void) internal::my_delete(path.file_string().c_str(), MYF(0));             // Delete file on error
942
928
    file= -1;
946
932
 
947
933
bool select_to_file::send_eof()
948
934
{
949
 
  int error= test(cache->end_io_cache());
 
935
  int error= test(end_io_cache(cache));
950
936
  if (internal::my_close(file, MYF(MY_WME)))
951
937
    error= 1;
952
938
  if (!error)
968
954
  /* In case of error send_eof() may be not called: close the file here. */
969
955
  if (file >= 0)
970
956
  {
971
 
    (void) cache->end_io_cache();
 
957
    (void) end_io_cache(cache);
972
958
    (void) internal::my_close(file, MYF(0));
973
959
    file= -1;
974
960
  }
1027
1013
  if (not to_file.has_root_directory())
1028
1014
  {
1029
1015
    target_path= fs::system_complete(getDataHomeCatalog());
1030
 
    util::string::const_shared_ptr schema(session->schema());
1031
 
    if (schema and not schema->empty())
 
1016
    if (not session->db.empty())
1032
1017
    {
1033
1018
      int count_elements= 0;
1034
1019
      for (fs::path::iterator iter= to_file.begin();
1038
1023
 
1039
1024
      if (count_elements == 1)
1040
1025
      {
1041
 
        target_path /= *schema;
 
1026
        target_path /= session->db;
1042
1027
      }
1043
1028
    }
1044
1029
    target_path /= to_file;
1067
1052
  if ((file= internal::my_create(target_path.file_string().c_str(), 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
1068
1053
    return file;
1069
1054
  (void) fchmod(file, 0666);                    // Because of umask()
1070
 
  if (cache->init_io_cache(file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
 
1055
  if (init_io_cache(cache, file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1071
1056
  {
1072
1057
    internal::my_close(file, MYF(0));
1073
1058
    internal::my_delete(target_path.file_string().c_str(), MYF(0));  // Delete file on error, it was just created
1090
1075
 
1091
1076
  /* Check if there is any blobs in data */
1092
1077
  {
1093
 
    List<Item>::iterator li(list.begin());
 
1078
    List_iterator_fast<Item> li(list);
1094
1079
    Item *item;
1095
1080
    while ((item=li++))
1096
1081
    {
1097
1082
      if (item->max_length >= MAX_BLOB_WIDTH)
1098
1083
      {
1099
 
        blob_flag=1;
1100
 
        break;
 
1084
        blob_flag=1;
 
1085
        break;
1101
1086
      }
1102
 
 
1103
1087
      if (item->result_type() == STRING_RESULT)
1104
1088
        string_results= true;
1105
1089
      else
1150
1134
  if (unit->offset_limit_cnt)
1151
1135
  {                                             // using limit offset,count
1152
1136
    unit->offset_limit_cnt--;
1153
 
    return false;
 
1137
    return(0);
1154
1138
  }
1155
1139
  row_count++;
1156
1140
  Item *item;
1157
1141
  uint32_t used_length=0,items_left=items.elements;
1158
 
  List<Item>::iterator li(items.begin());
 
1142
  List_iterator_fast<Item> li(items);
1159
1143
 
1160
1144
  if (my_b_write(cache,(unsigned char*) exchange->line_start->ptr(),
1161
1145
                 exchange->line_start->length()))
1162
 
    return true;
1163
 
 
 
1146
    goto err;
1164
1147
  while ((item=li++))
1165
1148
  {
1166
1149
    Item_result result_type=item->result_type();
1171
1154
    {
1172
1155
      if (my_b_write(cache,(unsigned char*) exchange->enclosed->ptr(),
1173
1156
                     exchange->enclosed->length()))
1174
 
        return true;
 
1157
        goto err;
1175
1158
    }
1176
1159
    if (!res)
1177
1160
    {                                           // NULL
1182
1165
          null_buff[0]=escape_char;
1183
1166
          null_buff[1]='N';
1184
1167
          if (my_b_write(cache,(unsigned char*) null_buff,2))
1185
 
            return true;
 
1168
            goto err;
1186
1169
        }
1187
1170
        else if (my_b_write(cache,(unsigned char*) "NULL",4))
1188
 
          return true;
 
1171
          goto err;
1189
1172
      }
1190
1173
      else
1191
1174
      {
1276
1259
            tmp_buff[1]= *pos ? *pos : '0';
1277
1260
            if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)) ||
1278
1261
                my_b_write(cache,(unsigned char*) tmp_buff,2))
1279
 
              return true;
 
1262
              goto err;
1280
1263
            start=pos+1;
1281
1264
          }
1282
1265
        }
1283
1266
        if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)))
1284
 
          return true;
 
1267
          goto err;
1285
1268
      }
1286
1269
      else if (my_b_write(cache,(unsigned char*) res->ptr(),used_length))
1287
 
        return true;
 
1270
        goto err;
1288
1271
    }
1289
1272
    if (fixed_row_size)
1290
1273
    {                                           // Fill with space
1300
1283
        for (; length > sizeof(space) ; length-=sizeof(space))
1301
1284
        {
1302
1285
          if (my_b_write(cache,(unsigned char*) space,sizeof(space)))
1303
 
            return true;
 
1286
            goto err;
1304
1287
        }
1305
1288
        if (my_b_write(cache,(unsigned char*) space,length))
1306
 
          return true;
 
1289
          goto err;
1307
1290
      }
1308
1291
    }
1309
1292
    if (res && enclosed)
1310
1293
    {
1311
1294
      if (my_b_write(cache, (unsigned char*) exchange->enclosed->ptr(),
1312
1295
                     exchange->enclosed->length()))
1313
 
        return true;
 
1296
        goto err;
1314
1297
    }
1315
1298
    if (--items_left)
1316
1299
    {
1317
1300
      if (my_b_write(cache, (unsigned char*) exchange->field_term->ptr(),
1318
1301
                     field_term_length))
1319
 
        return true;
 
1302
        goto err;
1320
1303
    }
1321
1304
  }
1322
1305
  if (my_b_write(cache,(unsigned char*) exchange->line_term->ptr(),
1323
1306
                 exchange->line_term->length()))
1324
 
  {
1325
 
    return true;
1326
 
  }
1327
 
 
1328
 
  return false;
 
1307
    goto err;
 
1308
  return(0);
 
1309
err:
 
1310
  return(1);
1329
1311
}
1330
1312
 
1331
1313
 
1344
1326
 
1345
1327
bool select_dump::send_data(List<Item> &items)
1346
1328
{
1347
 
  List<Item>::iterator li(items.begin());
 
1329
  List_iterator_fast<Item> li(items);
1348
1330
  char buff[MAX_FIELD_WIDTH];
1349
1331
  String tmp(buff,sizeof(buff),&my_charset_bin),*res;
1350
1332
  tmp.length(0);
1397
1379
    unit->offset_limit_cnt--;
1398
1380
    return(0);
1399
1381
  }
1400
 
  List<Item>::iterator li(items.begin());
 
1382
  List_iterator_fast<Item> li(items);
1401
1383
  Item *val_item;
1402
1384
  for (uint32_t i= 0; (val_item= li++); i++)
1403
1385
    it->store(i, val_item);
1415
1397
bool select_max_min_finder_subselect::send_data(List<Item> &items)
1416
1398
{
1417
1399
  Item_maxmin_subselect *it= (Item_maxmin_subselect *)item;
1418
 
  List<Item>::iterator li(items.begin());
 
1400
  List_iterator_fast<Item> li(items);
1419
1401
  Item *val_item= li++;
1420
1402
  it->register_value();
1421
1403
  if (it->assigned())
1485
1467
bool select_max_min_finder_subselect::cmp_decimal()
1486
1468
{
1487
1469
  Item *maxmin= ((Item_singlerow_subselect *)item)->element_index(0);
1488
 
  type::Decimal cval, *cvalue= cache->val_decimal(&cval);
1489
 
  type::Decimal mval, *mvalue= maxmin->val_decimal(&mval);
 
1470
  my_decimal cval, *cvalue= cache->val_decimal(&cval);
 
1471
  my_decimal mval, *mvalue= maxmin->val_decimal(&mval);
1490
1472
  if (fmax)
1491
1473
    return (cache->null_value && !maxmin->null_value) ||
1492
1474
      (!cache->null_value && !maxmin->null_value &&
1493
 
       class_decimal_cmp(cvalue, mvalue) > 0) ;
 
1475
       my_decimal_cmp(cvalue, mvalue) > 0) ;
1494
1476
  return (maxmin->null_value && !cache->null_value) ||
1495
1477
    (!cache->null_value && !maxmin->null_value &&
1496
 
     class_decimal_cmp(cvalue,mvalue) < 0);
 
1478
     my_decimal_cmp(cvalue,mvalue) < 0);
1497
1479
}
1498
1480
 
1499
1481
bool select_max_min_finder_subselect::cmp_str()
1535
1517
void Session::end_statement()
1536
1518
{
1537
1519
  /* Cleanup SQL processing state to reuse this statement in next query. */
1538
 
  lex->end();
 
1520
  lex_end(lex);
1539
1521
  query_cache_key= ""; // reset the cache key
1540
1522
  resetResultsetMessage();
1541
1523
}
1542
1524
 
1543
1525
bool Session::copy_db_to(char **p_db, size_t *p_db_length)
1544
1526
{
1545
 
  assert(_schema);
1546
 
  if (_schema and _schema->empty())
1547
 
  {
1548
 
    my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
1549
 
    return true;
1550
 
  }
1551
 
  else if (not _schema)
1552
 
  {
1553
 
    my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
1554
 
    return true;
1555
 
  }
1556
 
  assert(_schema);
1557
 
 
1558
 
  *p_db= strmake(_schema->c_str(), _schema->size());
1559
 
  *p_db_length= _schema->size();
1560
 
 
 
1527
  if (db.empty())
 
1528
  {
 
1529
    my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
 
1530
    return true;
 
1531
  }
 
1532
  *p_db= strmake(db.c_str(), db.length());
 
1533
  *p_db_length= db.length();
1561
1534
  return false;
1562
1535
}
1563
1536
 
1579
1552
  /* Fix for Intel compiler */
1580
1553
  if (copy_field)
1581
1554
  {
1582
 
    boost::checked_array_delete(copy_field);
1583
 
    save_copy_field= save_copy_field_end= copy_field= copy_field_end= 0;
 
1555
    delete [] copy_field;
 
1556
    save_copy_field= copy_field= 0;
1584
1557
  }
1585
1558
}
1586
1559
 
1587
1560
void Session::send_kill_message() const
1588
1561
{
1589
 
  drizzled::error_t err= static_cast<drizzled::error_t>(killed_errno());
1590
 
  if (err != EE_OK)
 
1562
  int err= killed_errno();
 
1563
  if (err)
1591
1564
    my_message(err, ER(err), MYF(0));
1592
1565
}
1593
1566
 
1597
1570
}
1598
1571
 
1599
1572
 
1600
 
void Session::set_db(const std::string &new_db)
 
1573
bool Session::set_db(const std::string &new_db)
1601
1574
{
1602
1575
  /* Do not reallocate memory if current chunk is big enough. */
1603
1576
  if (new_db.length())
1604
 
  {
1605
 
    _schema.reset(new std::string(new_db));
1606
 
  }
 
1577
    db= new_db;
1607
1578
  else
1608
 
  {
1609
 
    _schema.reset(new std::string(""));
1610
 
  }
1611
 
}
1612
 
 
 
1579
    db.clear();
 
1580
 
 
1581
  return false;
 
1582
}
 
1583
 
 
1584
 
 
1585
 
 
1586
 
 
1587
/**
 
1588
  Check the killed state of a user thread
 
1589
  @param session  user thread
 
1590
  @retval 0 the user thread is active
 
1591
  @retval 1 the user thread has been killed
 
1592
*/
 
1593
int session_killed(const Session *session)
 
1594
{
 
1595
  return(session->killed);
 
1596
}
 
1597
 
 
1598
 
 
1599
const struct charset_info_st *session_charset(Session *session)
 
1600
{
 
1601
  return(session->charset());
 
1602
}
1613
1603
 
1614
1604
/**
1615
1605
  Mark transaction to rollback and mark error as fatal to a sub-statement.
1617
1607
  @param  session   Thread handle
1618
1608
  @param  all   true <=> rollback main transaction.
1619
1609
*/
1620
 
void Session::markTransactionForRollback(bool all)
 
1610
void mark_transaction_to_rollback(Session *session, bool all)
1621
1611
{
1622
 
  is_fatal_sub_stmt_error= true;
1623
 
  transaction_rollback_request= all;
 
1612
  if (session)
 
1613
  {
 
1614
    session->is_fatal_sub_stmt_error= true;
 
1615
    session->transaction_rollback_request= all;
 
1616
  }
1624
1617
}
1625
1618
 
1626
 
void Session::disconnect(enum error_t errcode)
 
1619
void Session::disconnect(uint32_t errcode, bool should_lock)
1627
1620
{
1628
1621
  /* Allow any plugins to cleanup their session variables */
1629
1622
  plugin_sessionvar_cleanup(this);
1630
1623
 
1631
1624
  /* If necessary, log any aborted or unauthorized connections */
1632
 
  if (getKilled() || client->wasAborted())
 
1625
  if (killed || client->wasAborted())
1633
1626
  {
1634
1627
    status_var.aborted_threads++;
1635
1628
  }
1636
1629
 
1637
1630
  if (client->wasAborted())
1638
1631
  {
1639
 
    if (not getKilled() && variables.log_warnings > 1)
 
1632
    if (! killed && variables.log_warnings > 1)
1640
1633
    {
1641
 
      errmsg_printf(error::WARN, ER(ER_NEW_ABORTING_CONNECTION)
 
1634
      SecurityContext *sctx= &security_ctx;
 
1635
 
 
1636
      errmsg_printf(ERRMSG_LVL_WARN, ER(ER_NEW_ABORTING_CONNECTION)
1642
1637
                  , thread_id
1643
 
                  , (_schema->empty() ? "unconnected" : _schema->c_str())
1644
 
                  , security_ctx->username().empty() == false ? security_ctx->username().c_str() : "unauthenticated"
1645
 
                  , security_ctx->address().c_str()
 
1638
                  , (db.empty() ? "unconnected" : db.c_str())
 
1639
                  , sctx->getUser().empty() == false ? sctx->getUser().c_str() : "unauthenticated"
 
1640
                  , sctx->getIp().c_str()
1646
1641
                  , (main_da.is_error() ? main_da.message() : ER(ER_UNKNOWN_ERROR)));
1647
1642
    }
1648
1643
  }
1649
1644
 
1650
 
  setKilled(Session::KILL_CONNECTION);
1651
 
 
 
1645
  /* Close out our connection to the client */
 
1646
  if (should_lock)
 
1647
    LOCK_thread_count.lock();
 
1648
  killed= Session::KILL_CONNECTION;
1652
1649
  if (client->isConnected())
1653
1650
  {
1654
 
    if (errcode != EE_OK)
 
1651
    if (errcode)
1655
1652
    {
1656
1653
      /*my_error(errcode, ER(errcode));*/
1657
1654
      client->sendError(errcode, ER(errcode));
1658
1655
    }
1659
1656
    client->close();
1660
1657
  }
 
1658
  if (should_lock)
 
1659
    (void) LOCK_thread_count.unlock();
1661
1660
}
1662
1661
 
1663
1662
void Session::reset_for_next_command()
1685
1684
  Close all temporary tables created by 'CREATE TEMPORARY TABLE' for thread
1686
1685
*/
1687
1686
 
1688
 
void Open_tables_state::close_temporary_tables()
 
1687
void Session::close_temporary_tables()
1689
1688
{
1690
1689
  Table *table;
1691
1690
  Table *tmp_next;
1705
1704
  unlink from session->temporary tables and close temporary table
1706
1705
*/
1707
1706
 
1708
 
void Open_tables_state::close_temporary_table(Table *table)
 
1707
void Session::close_temporary_table(Table *table)
1709
1708
{
1710
1709
  if (table->getPrev())
1711
1710
  {
1741
1740
  If this is needed, use close_temporary_table()
1742
1741
*/
1743
1742
 
1744
 
void Open_tables_state::nukeTable(Table *table)
 
1743
void Session::nukeTable(Table *table)
1745
1744
{
1746
1745
  plugin::StorageEngine *table_type= table->getShare()->db_type();
1747
1746
 
1748
1747
  table->free_io_cache();
1749
1748
  table->delete_table();
1750
1749
 
1751
 
  identifier::Table identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName(), table->getShare()->getPath());
 
1750
  TableIdentifier identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName(), table->getShare()->getPath());
1752
1751
  rm_temporary_table(table_type, identifier);
1753
1752
 
1754
 
  boost::checked_delete(table->getMutableShare());
 
1753
  delete table->getMutableShare();
1755
1754
 
1756
 
  boost::checked_delete(table);
 
1755
  /* This makes me sad, but we're allocating it via malloc */
 
1756
  delete table;
1757
1757
}
1758
1758
 
1759
1759
/** Clear most status variables. */
1776
1776
 
1777
1777
user_var_entry *Session::getVariable(const std::string  &name, bool create_if_not_exists)
1778
1778
{
1779
 
  if (cleanup_done)
1780
 
    return NULL;
 
1779
  UserVarsRange ppp= user_vars.equal_range(name);
1781
1780
 
1782
 
  UserVars::iterator iter= user_vars.find(name);
1783
 
  if (iter != user_vars.end())
 
1781
  for (UserVars::iterator iter= ppp.first;
 
1782
       iter != ppp.second; ++iter)
 
1783
  {
1784
1784
    return (*iter).second;
 
1785
  }
1785
1786
 
1786
1787
  if (not create_if_not_exists)
1787
1788
    return NULL;
1796
1797
 
1797
1798
  if (not returnable.second)
1798
1799
  {
1799
 
    boost::checked_delete(entry);
 
1800
    delete entry;
1800
1801
  }
1801
1802
 
1802
1803
  return entry;
1805
1806
void Session::setVariable(const std::string &name, const std::string &value)
1806
1807
{
1807
1808
  user_var_entry *updateable_var= getVariable(name.c_str(), true);
1808
 
  if (updateable_var)
1809
 
  {
1810
 
    updateable_var->update_hash(false,
1811
 
                                (void*)value.c_str(),
1812
 
                                static_cast<uint32_t>(value.length()), STRING_RESULT,
1813
 
                                &my_charset_bin,
1814
 
                                DERIVATION_IMPLICIT, false);
1815
 
  }
 
1809
 
 
1810
  updateable_var->update_hash(false,
 
1811
                              (void*)value.c_str(),
 
1812
                              static_cast<uint32_t>(value.length()), STRING_RESULT,
 
1813
                              &my_charset_bin,
 
1814
                              DERIVATION_IMPLICIT, false);
1816
1815
}
1817
1816
 
1818
 
void Open_tables_state::mark_temp_tables_as_free_for_reuse()
 
1817
void Session::mark_temp_tables_as_free_for_reuse()
1819
1818
{
1820
1819
  for (Table *table= temporary_tables ; table ; table= table->getNext())
1821
1820
  {
1822
 
    if (table->query_id == getQueryId())
 
1821
    if (table->query_id == query_id)
1823
1822
    {
1824
1823
      table->query_id= 0;
1825
1824
      table->cursor->ha_reset();
1831
1830
{
1832
1831
  for (; table ; table= table->getNext())
1833
1832
  {
1834
 
    if (table->query_id == getQueryId())
 
1833
    if (table->query_id == query_id)
1835
1834
    {
1836
1835
      table->query_id= 0;
1837
1836
      table->cursor->ha_reset();
1850
1849
*/
1851
1850
void Session::close_thread_tables()
1852
1851
{
1853
 
  clearDerivedTables();
 
1852
  if (derived_tables)
 
1853
    derived_tables= NULL; // They should all be invalid by this point
1854
1854
 
1855
1855
  /*
1856
1856
    Mark all temporary tables used by this statement as free for reuse.
1867
1867
  {
1868
1868
    TransactionServices &transaction_services= TransactionServices::singleton();
1869
1869
    main_da.can_overwrite_status= true;
1870
 
    transaction_services.autocommitOrRollback(*this, is_error());
 
1870
    transaction_services.autocommitOrRollback(this, is_error());
1871
1871
    main_da.can_overwrite_status= false;
1872
1872
    transaction.stmt.reset();
1873
1873
  }
1883
1883
      handled either before writing a query log event (inside
1884
1884
      binlog_query()) or when preparing a pending event.
1885
1885
     */
1886
 
    unlockTables(lock);
 
1886
    mysql_unlock_tables(this, lock);
1887
1887
    lock= 0;
1888
1888
  }
1889
1889
  /*
1890
 
    Note that we need to hold table::Cache::singleton().mutex() while changing the
 
1890
    Note that we need to hold LOCK_open while changing the
1891
1891
    open_tables list. Another thread may work on it.
1892
 
    (See: table::Cache::singleton().removeTable(), wait_completed_table())
 
1892
    (See: remove_table_from_cache(), mysql_wait_completed_table())
1893
1893
    Closing a MERGE child before the parent would be fatal if the
1894
1894
    other thread tries to abort the MERGE lock in between.
1895
1895
  */
1923
1923
 
1924
1924
    if (not lock_tables(tables, counter, &need_reopen))
1925
1925
      break;
1926
 
 
1927
1926
    if (not need_reopen)
1928
1927
      return true;
1929
 
 
1930
1928
    close_tables_for_reopen(&tables);
1931
1929
  }
1932
 
 
1933
 
  if ((handle_derived(lex, &derived_prepare) || (handle_derived(lex, &derived_filling))))
 
1930
  if ((mysql_handle_derived(lex, &mysql_derived_prepare) ||
 
1931
       (
 
1932
        mysql_handle_derived(lex, &mysql_derived_filling))))
1934
1933
    return true;
1935
1934
 
1936
1935
  return false;
1942
1941
  might be an issue (lame engines).
1943
1942
*/
1944
1943
 
1945
 
bool Open_tables_state::rm_temporary_table(const identifier::Table &identifier, bool best_effort)
 
1944
bool Session::rm_temporary_table(TableIdentifier &identifier, bool best_effort)
1946
1945
{
1947
 
  if (not plugin::StorageEngine::dropTable(*static_cast<Session *>(this), identifier))
 
1946
  if (plugin::StorageEngine::dropTable(*this, identifier))
1948
1947
  {
1949
1948
    if (not best_effort)
1950
1949
    {
1951
 
      std::string path;
1952
 
      identifier.getSQLPath(path);
1953
 
      errmsg_printf(error::WARN, _("Could not remove temporary table: '%s', error: %d"),
1954
 
                    path.c_str(), errno);
 
1950
      errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
 
1951
                    identifier.getSQLPath().c_str(), errno);
1955
1952
    }
1956
1953
 
1957
1954
    return true;
1960
1957
  return false;
1961
1958
}
1962
1959
 
1963
 
bool Open_tables_state::rm_temporary_table(plugin::StorageEngine *base, const identifier::Table &identifier)
 
1960
bool Session::rm_temporary_table(plugin::StorageEngine *base, TableIdentifier &identifier)
1964
1961
{
1965
 
  drizzled::error_t error;
1966
1962
  assert(base);
1967
1963
 
1968
 
  if (not plugin::StorageEngine::dropTable(*static_cast<Session *>(this), *base, identifier, error))
 
1964
  if (plugin::StorageEngine::dropTable(*this, *base, identifier))
1969
1965
  {
1970
 
    std::string path;
1971
 
    identifier.getSQLPath(path);
1972
 
    errmsg_printf(error::WARN, _("Could not remove temporary table: '%s', error: %d"),
1973
 
                  path.c_str(), error);
 
1966
    errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
 
1967
                  identifier.getSQLPath().c_str(), errno);
1974
1968
 
1975
1969
    return true;
1976
1970
  }
1982
1976
  @note this will be removed, I am looking through Hudson to see if it is finding
1983
1977
  any tables that are missed during cleanup.
1984
1978
*/
1985
 
void Open_tables_state::dumpTemporaryTableNames(const char *foo)
 
1979
void Session::dumpTemporaryTableNames(const char *foo)
1986
1980
{
1987
1981
  Table *table;
1988
1982
 
1994
1988
  {
1995
1989
    bool have_proto= false;
1996
1990
 
1997
 
    message::Table *proto= table->getShare()->getTableMessage();
1998
 
    if (table->getShare()->getTableMessage())
 
1991
    message::Table *proto= table->getShare()->getTableProto();
 
1992
    if (table->getShare()->getTableProto())
1999
1993
      have_proto= true;
2000
1994
 
2001
1995
    const char *answer= have_proto ? "true" : "false";
2006
2000
      cerr << "\t\t Proto " << proto->schema() << " " << proto->name() << "\n";
2007
2001
    }
2008
2002
    else
2009
 
    {
2010
2003
      cerr << "\tTabl;e Name " << table->getShare()->getSchemaName() << "." << table->getShare()->getTableName() << " : " << answer << "\n";
2011
 
    }
2012
 
  }
2013
 
}
2014
 
 
2015
 
table::Singular *Session::getInstanceTable()
2016
 
{
2017
 
  temporary_shares.push_back(new table::Singular()); // This will not go into the tableshare cache, so no key is used.
2018
 
 
2019
 
  table::Singular *tmp_share= temporary_shares.back();
2020
 
 
2021
 
  assert(tmp_share);
2022
 
 
2023
 
  return tmp_share;
2024
 
}
2025
 
 
2026
 
 
2027
 
/**
2028
 
  Create a reduced Table object with properly set up Field list from a
2029
 
  list of field definitions.
2030
 
 
2031
 
    The created table doesn't have a table Cursor associated with
2032
 
    it, has no keys, no group/distinct, no copy_funcs array.
2033
 
    The sole purpose of this Table object is to use the power of Field
2034
 
    class to read/write data to/from table->getInsertRecord(). Then one can store
2035
 
    the record in any container (RB tree, hash, etc).
2036
 
    The table is created in Session mem_root, so are the table's fields.
2037
 
    Consequently, if you don't BLOB fields, you don't need to free it.
2038
 
 
2039
 
  @param session         connection handle
2040
 
  @param field_list  list of column definitions
2041
 
 
2042
 
  @return
2043
 
    0 if out of memory, Table object in case of success
2044
 
*/
2045
 
table::Singular *Session::getInstanceTable(List<CreateField> &field_list)
2046
 
{
2047
 
  temporary_shares.push_back(new table::Singular(this, field_list)); // This will not go into the tableshare cache, so no key is used.
2048
 
 
2049
 
  table::Singular *tmp_share= temporary_shares.back();
2050
 
 
2051
 
  assert(tmp_share);
2052
 
 
2053
 
  return tmp_share;
2054
 
}
2055
 
 
2056
 
namespace display  {
2057
 
 
2058
 
static const std::string NONE= "NONE";
2059
 
static const std::string GOT_GLOBAL_READ_LOCK= "HAS GLOBAL READ LOCK";
2060
 
static const std::string MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT= "HAS GLOBAL READ LOCK WITH BLOCKING COMMIT";
2061
 
 
2062
 
const std::string &type(drizzled::Session::global_read_lock_t type)
2063
 
{
2064
 
  switch (type) {
2065
 
    default:
2066
 
    case Session::NONE:
2067
 
      return NONE;
2068
 
    case Session::GOT_GLOBAL_READ_LOCK:
2069
 
      return GOT_GLOBAL_READ_LOCK;
2070
 
    case Session::MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT:
2071
 
      return MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT;
2072
 
  }
2073
 
}
2074
 
 
2075
 
size_t max_string_length(drizzled::Session::global_read_lock_t)
2076
 
{
2077
 
  return MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT.size();
2078
 
}
2079
 
 
2080
 
} /* namespace display */
 
2004
  }
 
2005
}
 
2006
 
 
2007
bool Session::storeTableMessage(const TableIdentifier &identifier, message::Table &table_message)
 
2008
{
 
2009
  table_message_cache.insert(make_pair(identifier.getPath(), table_message));
 
2010
 
 
2011
  return true;
 
2012
}
 
2013
 
 
2014
bool Session::removeTableMessage(const TableIdentifier &identifier)
 
2015
{
 
2016
  TableMessageCache::iterator iter;
 
2017
 
 
2018
  iter= table_message_cache.find(identifier.getPath());
 
2019
 
 
2020
  if (iter == table_message_cache.end())
 
2021
    return false;
 
2022
 
 
2023
  table_message_cache.erase(iter);
 
2024
 
 
2025
  return true;
 
2026
}
 
2027
 
 
2028
bool Session::getTableMessage(const TableIdentifier &identifier, message::Table &table_message)
 
2029
{
 
2030
  TableMessageCache::iterator iter;
 
2031
 
 
2032
  iter= table_message_cache.find(identifier.getPath());
 
2033
 
 
2034
  if (iter == table_message_cache.end())
 
2035
    return false;
 
2036
 
 
2037
  table_message.CopyFrom(((*iter).second));
 
2038
 
 
2039
  return true;
 
2040
}
 
2041
 
 
2042
bool Session::doesTableMessageExist(const TableIdentifier &identifier)
 
2043
{
 
2044
  TableMessageCache::iterator iter;
 
2045
 
 
2046
  iter= table_message_cache.find(identifier.getPath());
 
2047
 
 
2048
  if (iter == table_message_cache.end())
 
2049
  {
 
2050
    return false;
 
2051
  }
 
2052
 
 
2053
  return true;
 
2054
}
 
2055
 
 
2056
bool Session::renameTableMessage(const TableIdentifier &from, const TableIdentifier &to)
 
2057
{
 
2058
  TableMessageCache::iterator iter;
 
2059
 
 
2060
  table_message_cache[to.getPath()]= table_message_cache[from.getPath()];
 
2061
 
 
2062
  iter= table_message_cache.find(to.getPath());
 
2063
 
 
2064
  if (iter == table_message_cache.end())
 
2065
  {
 
2066
    return false;
 
2067
  }
 
2068
 
 
2069
  (*iter).second.set_schema(to.getSchemaName());
 
2070
  (*iter).second.set_name(to.getTableName());
 
2071
 
 
2072
  return true;
 
2073
}
 
2074
 
 
2075
table::Instance *Session::getInstanceTable()
 
2076
{
 
2077
  temporary_shares.push_back(new table::Instance()); // This will not go into the tableshare cache, so no key is used.
 
2078
 
 
2079
  table::Instance *tmp_share= temporary_shares.back();
 
2080
 
 
2081
  assert(tmp_share);
 
2082
 
 
2083
  return tmp_share;
 
2084
}
2081
2085
 
2082
2086
} /* namespace drizzled */