~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/session.cc

  • Committer: lbieber
  • Date: 2010-09-11 16:33:45 UTC
  • mfrom: (1757.1.2 build)
  • Revision ID: lbieber@orisndriz03-20100911163345-na1t8m18at9thsjl
Merge Vijay - added utf 8 tamil test case suite and test case for creating a database in tamil
Merge Brian - Small set of refactoring (includes one case of memset on a table object).

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
22
22
 */
23
23
 
24
24
#include "config.h"
25
 
 
26
 
#include <drizzled/copy_field.h>
27
 
#include "drizzled/session.h"
28
 
#include "drizzled/session/cache.h"
29
 
#include "drizzled/error.h"
30
 
#include "drizzled/gettext.h"
31
 
#include "drizzled/query_id.h"
32
 
#include "drizzled/data_home.h"
33
 
#include "drizzled/sql_base.h"
34
 
#include "drizzled/lock.h"
35
 
#include "drizzled/item/cache.h"
36
 
#include "drizzled/item/float.h"
37
 
#include "drizzled/item/return_int.h"
38
 
#include "drizzled/item/empty_string.h"
39
 
#include "drizzled/show.h"
40
 
#include "drizzled/plugin/client.h"
 
25
#include <drizzled/session.h>
 
26
#include "drizzled/session_list.h"
 
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>
41
40
#include "drizzled/plugin/scheduler.h"
42
41
#include "drizzled/plugin/authentication.h"
43
42
#include "drizzled/plugin/logging.h"
44
43
#include "drizzled/plugin/transactional_storage_engine.h"
45
 
#include "drizzled/plugin/query_rewrite.h"
46
44
#include "drizzled/probes.h"
47
45
#include "drizzled/table_proto.h"
48
46
#include "drizzled/db.h"
50
48
#include "drizzled/transaction_services.h"
51
49
#include "drizzled/drizzled.h"
52
50
 
53
 
#include "drizzled/identifier.h"
54
 
 
55
 
#include <drizzled/refresh_version.h>
56
 
 
57
 
#include "drizzled/table/singular.h"
 
51
#include "drizzled/table_share_instance.h"
58
52
 
59
53
#include "plugin/myisam/myisam.h"
60
54
#include "drizzled/internal/iocache.h"
61
55
#include "drizzled/internal/thread_var.h"
62
56
#include "drizzled/plugin/event_observer.h"
63
57
 
64
 
#include "drizzled/util/functors.h"
65
 
 
66
 
#include "drizzled/display.h"
67
 
 
 
58
#include <fcntl.h>
68
59
#include <algorithm>
69
60
#include <climits>
70
 
#include <fcntl.h>
71
 
#include <sys/stat.h>
72
 
 
73
 
#include <boost/filesystem.hpp>
74
 
#include <boost/checked_delete.hpp>
75
 
 
76
 
#include "drizzled/util/backtrace.h"
77
61
 
78
62
using namespace std;
79
 
 
80
 
namespace fs=boost::filesystem;
81
63
namespace drizzled
82
64
{
83
65
 
89
71
char empty_c_string[1]= {0};    /* used for not defined db */
90
72
 
91
73
const char * const Session::DEFAULT_WHERE= "field list";
 
74
extern pthread_key_t THR_Session;
 
75
extern pthread_key_t THR_Mem_root;
92
76
 
93
77
bool Key_part_spec::operator==(const Key_part_spec& other) const
94
78
{
95
79
  return length == other.length &&
96
80
         field_name.length == other.field_name.length &&
97
 
    !my_strcasecmp(system_charset_info, field_name.str, other.field_name.str);
 
81
         !strcmp(field_name.str, other.field_name.str);
98
82
}
99
83
 
100
84
Open_tables_state::Open_tables_state(uint64_t version_arg) :
107
91
/*
108
92
  The following functions form part of the C plugin API
109
93
*/
110
 
int tmpfile(const char *prefix)
 
94
int mysql_tmpfile(const char *prefix)
111
95
{
112
96
  char filename[FN_REFLEN];
113
97
  int fd = internal::create_temp_file(filename, drizzle_tmpdir.c_str(), prefix, MYF(MY_WME));
118
102
  return fd;
119
103
}
120
104
 
 
105
int session_tablespace_op(const Session *session)
 
106
{
 
107
  return test(session->tablespace_op);
 
108
}
 
109
 
 
110
/**
 
111
   Set the process info field of the Session structure.
 
112
 
 
113
   This function is used by plug-ins. Internally, the
 
114
   Session::set_proc_info() function should be used.
 
115
 
 
116
   @see Session::set_proc_info
 
117
 */
 
118
void set_session_proc_info(Session *session, const char *info)
 
119
{
 
120
  session->set_proc_info(info);
 
121
}
 
122
 
 
123
const char *get_session_proc_info(Session *session)
 
124
{
 
125
  return session->get_proc_info();
 
126
}
 
127
 
121
128
void **Session::getEngineData(const plugin::MonitoredInTransaction *monitored)
122
129
{
123
130
  return static_cast<void **>(&ha_data[monitored->getId()].ha_ptr);
134
141
  return session->options & test_options;
135
142
}
136
143
 
137
 
Session::Session(plugin::Client *client_arg, catalog::Instance::shared_ptr catalog_arg) :
 
144
int session_sql_command(const Session *session)
 
145
{
 
146
  return (int) session->lex->sql_command;
 
147
}
 
148
 
 
149
enum_tx_isolation session_tx_isolation(const Session *session)
 
150
{
 
151
  return (enum_tx_isolation)session->variables.tx_isolation;
 
152
}
 
153
 
 
154
Session::Session(plugin::Client *client_arg) :
138
155
  Open_tables_state(refresh_version),
139
156
  mem_root(&main_mem_root),
140
 
  xa_id(0),
141
157
  lex(&main_lex),
142
 
  query(new std::string),
143
 
  _schema(new std::string("")),
 
158
  query(),
144
159
  client(client_arg),
145
160
  scheduler(NULL),
146
161
  scheduler_arg(NULL),
147
162
  lock_id(&main_lock_id),
148
 
  thread_stack(NULL),
149
 
  security_ctx(identifier::User::make_shared()),
150
 
  _where(Session::DEFAULT_WHERE),
151
 
  dbug_sentry(Session_SENTRY_MAGIC),
152
 
  mysys_var(0),
153
 
  command(COM_CONNECT),
154
 
  file_id(0),
155
 
  _epoch(boost::gregorian::date(1970,1,1)),
156
 
  _connect_time(boost::posix_time::microsec_clock::universal_time()),
157
 
  utime_after_lock(0),
 
163
  user_time(0),
158
164
  ha_data(plugin::num_trx_monitored_objects),
159
 
  query_id(0),
160
 
  warn_query_id(0),
161
 
  concurrent_execute_allowed(true),
162
165
  arg_of_last_insert_id_function(false),
163
166
  first_successful_insert_id_in_prev_stmt(0),
164
167
  first_successful_insert_id_in_cur_stmt(0),
165
168
  limit_found_rows(0),
166
 
  options(session_startup_options),
167
 
  row_count_func(-1),
168
 
  sent_row_count(0),
169
 
  examined_row_count(0),
170
 
  used_tables(0),
171
 
  total_warn_count(0),
172
 
  col_access(0),
173
 
  statement_id_counter(0),
174
 
  row_count(0),
175
 
  thread_id(0),
176
 
  tmp_table(0),
177
 
  _global_read_lock(NONE),
178
 
  count_cuted_fields(CHECK_FIELD_ERROR_FOR_NULL),
179
 
  _killed(NOT_KILLED),
 
169
  global_read_lock(0),
180
170
  some_tables_deleted(false),
181
171
  no_errors(false),
182
172
  password(false),
183
173
  is_fatal_error(false),
184
174
  transaction_rollback_request(false),
185
175
  is_fatal_sub_stmt_error(0),
 
176
  derived_tables_processing(false),
186
177
  tablespace_op(false),
187
 
  derived_tables_processing(false),
188
178
  m_lip(NULL),
189
179
  cached_table(0),
190
180
  transaction_message(NULL),
191
181
  statement_message(NULL),
192
 
  session_event_observers(NULL),
193
 
  _catalog(catalog_arg),
194
 
  use_usage(false)
 
182
  session_event_observers(NULL)
195
183
{
 
184
  memset(process_list_info, 0, PROCESS_LIST_WIDTH);
196
185
  client->setSession(this);
197
186
 
198
187
  /*
201
190
    will be re-initialized in init_for_queries().
202
191
  */
203
192
  memory::init_sql_alloc(&main_mem_root, memory::ROOT_MIN_BLOCK_SIZE, 0);
 
193
  thread_stack= NULL;
 
194
  count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
 
195
  killed= NOT_KILLED;
 
196
  col_access= 0;
 
197
  tmp_table= 0;
 
198
  used_tables= 0;
204
199
  cuted_fields= sent_row_count= row_count= 0L;
 
200
  row_count_func= -1;
 
201
  statement_id_counter= 0UL;
205
202
  // Must be reset to handle error with Session's created for init of mysqld
206
203
  lex->current_select= 0;
 
204
  start_time=(time_t) 0;
 
205
  start_utime= 0L;
 
206
  utime_after_lock= 0L;
207
207
  memset(&variables, 0, sizeof(variables));
 
208
  thread_id= 0;
 
209
  file_id = 0;
 
210
  query_id= 0;
 
211
  warn_query_id= 0;
 
212
  mysys_var= 0;
208
213
  scoreboard_index= -1;
 
214
  dbug_sentry=Session_SENTRY_MAGIC;
209
215
  cleanup_done= abort_on_warning= no_warnings_for_error= false;  
210
216
 
211
217
  /* query_cache init */
214
220
 
215
221
  /* Variables with default values */
216
222
  proc_info="login";
 
223
  where= Session::DEFAULT_WHERE;
 
224
  command= COM_CONNECT;
217
225
 
218
226
  plugin_sessionvar_init(this);
219
227
  /*
223
231
  */
224
232
  variables.pseudo_thread_id= thread_id;
225
233
  server_status= SERVER_STATUS_AUTOCOMMIT;
 
234
  options= session_startup_options;
226
235
 
227
236
  if (variables.max_join_size == HA_POS_ERROR)
228
237
    options |= OPTION_BIG_SELECTS;
234
243
  session_tx_isolation= (enum_tx_isolation) variables.tx_isolation;
235
244
  warn_list.empty();
236
245
  memset(warn_count, 0, sizeof(warn_count));
 
246
  total_warn_count= 0;
237
247
  memset(&status_var, 0, sizeof(status_var));
238
248
 
239
249
  /* Initialize sub structures */
269
279
  m_internal_handler= handler;
270
280
}
271
281
 
272
 
bool Session::handle_error(drizzled::error_t sql_errno, const char *message,
273
 
                           DRIZZLE_ERROR::enum_warning_level level)
 
282
bool Session::handle_error(uint32_t sql_errno, const char *message,
 
283
                       DRIZZLE_ERROR::enum_warning_level level)
274
284
{
275
285
  if (m_internal_handler)
276
286
  {
291
301
    return;
292
302
 
293
303
  setAbort(true);
294
 
  boost_unique_lock_t scopedLock(mysys_var->mutex);
 
304
  pthread_mutex_lock(&mysys_var->mutex);
295
305
  if (mysys_var->current_cond)
296
306
  {
297
 
    mysys_var->current_mutex->lock();
298
 
    mysys_var->current_cond->notify_all();
299
 
    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);
300
310
  }
 
311
  pthread_mutex_unlock(&mysys_var->mutex);
301
312
}
302
313
 
303
314
void Session::pop_internal_handler()
317
328
{
318
329
  assert(cleanup_done == false);
319
330
 
320
 
  setKilled(KILL_CONNECTION);
 
331
  killed= KILL_CONNECTION;
321
332
#ifdef ENABLE_WHEN_BINLOG_WILL_BE_ABLE_TO_PREPARE
322
333
  if (transaction.xid_state.xa_state == XA_PREPARED)
323
334
  {
326
337
#endif
327
338
  {
328
339
    TransactionServices &transaction_services= TransactionServices::singleton();
329
 
    transaction_services.rollbackTransaction(*this, true);
 
340
    transaction_services.rollbackTransaction(this, true);
330
341
    xid_cache_delete(&transaction.xid_state);
331
342
  }
332
343
 
335
346
       iter++)
336
347
  {
337
348
    user_var_entry *entry= (*iter).second;
338
 
    boost::checked_delete(entry);
 
349
    delete entry;
339
350
  }
340
351
  user_vars.clear();
341
352
 
343
354
  close_temporary_tables();
344
355
 
345
356
  if (global_read_lock)
346
 
  {
347
 
    unlockGlobalReadLock();
348
 
  }
 
357
    unlock_global_read_lock(this);
349
358
 
350
359
  cleanup_done= true;
351
360
}
354
363
{
355
364
  this->checkSentry();
356
365
 
357
 
  if (client and client->isConnected())
 
366
  if (client->isConnected())
358
367
  {
359
 
    assert(security_ctx);
360
368
    if (global_system_variables.log_warnings)
361
 
    {
362
 
      errmsg_printf(error::WARN, ER(ER_FORCING_CLOSE),
363
 
                    internal::my_progname,
364
 
                    thread_id,
365
 
                    security_ctx->username().c_str());
366
 
    }
367
 
 
368
 
    disconnect();
 
369
        errmsg_printf(ERRMSG_LVL_WARN, ER(ER_FORCING_CLOSE),internal::my_progname,
 
370
                      thread_id,
 
371
                      (getSecurityContext().getUser().c_str() ?
 
372
                       getSecurityContext().getUser().c_str() : ""));
 
373
    disconnect(0, false);
369
374
  }
370
375
 
371
376
  /* Close connection */
372
 
  if (client)
373
 
  {
374
 
    client->close();
375
 
    boost::checked_delete(client);
376
 
    client= NULL;
377
 
  }
 
377
  client->close();
 
378
  delete client;
378
379
 
379
380
  if (cleanup_done == false)
380
381
    cleanup();
387
388
  dbug_sentry= Session_SENTRY_GONE;
388
389
 
389
390
  main_mem_root.free_root(MYF(0));
390
 
  currentMemRoot().release();
391
 
  currentSession().release();
 
391
  pthread_setspecific(THR_Session,  0);
392
392
 
393
393
  plugin::Logging::postEndDo(this);
394
394
  plugin::EventObserver::deregisterSessionEvents(*this); 
395
 
}
396
 
 
397
 
void Session::setClient(plugin::Client *client_arg)
398
 
{
399
 
  client= client_arg;
400
 
  client->setSession(this);
401
 
}
402
 
 
403
 
void Session::awake(Session::killed_state_t state_to_set)
404
 
{
405
 
  if ((state_to_set == Session::KILL_QUERY) and (command == COM_SLEEP))
406
 
    return;
407
 
 
 
395
 
 
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
{
408
402
  this->checkSentry();
409
 
 
410
 
  setKilled(state_to_set);
411
 
  scheduler->killSession(this);
412
 
 
 
403
  safe_mutex_assert_owner(&LOCK_delete);
 
404
 
 
405
  killed= state_to_set;
413
406
  if (state_to_set != Session::KILL_QUERY)
414
407
  {
 
408
    scheduler->killSession(this);
415
409
    DRIZZLE_CONNECTION_DONE(thread_id);
416
410
  }
417
 
 
418
411
  if (mysys_var)
419
412
  {
420
 
    boost_unique_lock_t scopedLock(mysys_var->mutex);
 
413
    pthread_mutex_lock(&mysys_var->mutex);
421
414
    /*
422
 
      "
423
415
      This broadcast could be up in the air if the victim thread
424
416
      exits the cond in the time between read and broadcast, but that is
425
417
      ok since all we want to do is to make the victim thread get out
440
432
    */
441
433
    if (mysys_var->current_cond && mysys_var->current_mutex)
442
434
    {
443
 
      mysys_var->current_mutex->lock();
444
 
      mysys_var->current_cond->notify_all();
445
 
      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);
446
438
    }
 
439
    pthread_mutex_unlock(&mysys_var->mutex);
447
440
  }
448
441
}
449
442
 
459
452
  */
460
453
  assert(thread_stack);
461
454
 
462
 
  currentSession().release();
463
 
  currentSession().reset(this);
464
 
 
465
 
  currentMemRoot().release();
466
 
  currentMemRoot().reset(&mem_root);
 
455
  if (pthread_setspecific(THR_Session,  this) ||
 
456
      pthread_setspecific(THR_Mem_root, &mem_root))
 
457
    return true;
467
458
 
468
459
  mysys_var=my_thread_var;
469
460
 
472
463
    This allows us to move Session to different threads if needed.
473
464
  */
474
465
  mysys_var->id= thread_id;
 
466
  real_id= pthread_self();                      // For debugging
475
467
 
476
468
  /*
477
469
    We have to call thr_lock_info_init() again here as Session may have been
502
494
                                variables.query_prealloc_size);
503
495
  transaction.xid_state.xid.null();
504
496
  transaction.xid_state.in_session=1;
505
 
  if (use_usage)
506
 
    resetUsage();
507
497
}
508
498
 
509
499
bool Session::initGlobals()
510
500
{
511
501
  if (storeGlobals())
512
502
  {
513
 
    disconnect(ER_OUT_OF_RESOURCES);
 
503
    disconnect(ER_OUT_OF_RESOURCES, true);
514
504
    status_var.aborted_connects++;
515
505
    return true;
516
506
  }
521
511
{
522
512
  if (initGlobals() || authenticate())
523
513
  {
524
 
    disconnect();
 
514
    disconnect(0, true);
525
515
    return;
526
516
  }
527
517
 
528
518
  prepareForQueries();
529
519
 
530
 
  while (not client->haveError() && getKilled() != KILL_CONNECTION)
 
520
  while (! client->haveError() && killed != KILL_CONNECTION)
531
521
  {
532
 
    if (not executeStatement())
 
522
    if (! executeStatement())
533
523
      break;
534
524
  }
535
525
 
536
 
  disconnect();
 
526
  disconnect(0, true);
537
527
}
538
528
 
539
 
bool Session::schedule(Session::shared_ptr &arg)
 
529
bool Session::schedule()
540
530
{
541
 
  arg->scheduler= plugin::Scheduler::getScheduler();
542
 
  assert(arg->scheduler);
543
 
 
544
 
  ++connection_count;
545
 
 
546
 
  long current_connections= connection_count;
547
 
 
548
 
  if (current_connections > 0 and static_cast<uint64_t>(current_connections) > current_global_counters.max_used_connections)
 
531
  scheduler= plugin::Scheduler::getScheduler();
 
532
  assert(scheduler);
 
533
 
 
534
  connection_count.increment();
 
535
 
 
536
  if (connection_count > current_global_counters.max_used_connections)
549
537
  {
550
 
    current_global_counters.max_used_connections= static_cast<uint64_t>(connection_count);
 
538
    current_global_counters.max_used_connections= connection_count;
551
539
  }
552
540
 
553
541
  current_global_counters.connections++;
554
 
  arg->thread_id= arg->variables.pseudo_thread_id= global_thread_id++;
555
 
 
556
 
  session::Cache::singleton().insert(arg);
557
 
 
558
 
  if (unlikely(plugin::EventObserver::connectSession(*arg)))
559
 
  {
560
 
    // We should do something about an error...
561
 
  }
562
 
 
563
 
  if (plugin::Scheduler::getScheduler()->addSession(arg))
564
 
  {
565
 
    DRIZZLE_CONNECTION_START(arg->getSessionId());
 
542
  thread_id= variables.pseudo_thread_id= global_thread_id++;
 
543
 
 
544
  LOCK_thread_count.lock();
 
545
  getSessionList().push_back(this);
 
546
  LOCK_thread_count.unlock();
 
547
 
 
548
  if (scheduler->addSession(this))
 
549
  {
 
550
    DRIZZLE_CONNECTION_START(thread_id);
566
551
    char error_message_buff[DRIZZLE_ERRMSG_SIZE];
567
552
 
568
 
    arg->setKilled(Session::KILL_CONNECTION);
 
553
    killed= Session::KILL_CONNECTION;
569
554
 
570
 
    arg->status_var.aborted_connects++;
 
555
    status_var.aborted_connects++;
571
556
 
572
557
    /* Can't use my_error() since store_globals has not been called. */
573
558
    /* TODO replace will better error message */
574
559
    snprintf(error_message_buff, sizeof(error_message_buff),
575
560
             ER(ER_CANT_CREATE_THREAD), 1);
576
 
    arg->client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
577
 
 
 
561
    client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
578
562
    return true;
579
563
  }
580
564
 
582
566
}
583
567
 
584
568
 
585
 
/*
586
 
  Is this session viewable by the current user?
587
 
*/
588
 
bool Session::isViewable(identifier::User::const_reference user_arg) const
589
 
{
590
 
  return plugin::Authorization::isAuthorized(user_arg, this, false);
591
 
}
592
 
 
593
 
 
594
 
const char* Session::enter_cond(boost::condition_variable_any &cond, boost::mutex &mutex, const char* msg)
 
569
const char* Session::enter_cond(boost::condition_variable &cond, boost::mutex &mutex, const char* msg)
595
570
{
596
571
  const char* old_msg = get_proc_info();
597
572
  safe_mutex_assert_owner(mutex);
598
 
  mysys_var->current_mutex = &mutex;
599
 
  mysys_var->current_cond = &cond;
 
573
  mysys_var->current_mutex = mutex.native_handle();
 
574
  mysys_var->current_cond = cond.native_handle();
600
575
  this->set_proc_info(msg);
601
576
  return old_msg;
602
577
}
609
584
    locked (if that would not be the case, you'll get a deadlock if someone
610
585
    does a Session::awake() on you).
611
586
  */
612
 
  mysys_var->current_mutex->unlock();
613
 
  boost_unique_lock_t scopedLock(mysys_var->mutex);
 
587
  pthread_mutex_unlock(mysys_var->current_mutex);
 
588
  pthread_mutex_lock(&mysys_var->mutex);
614
589
  mysys_var->current_mutex = 0;
615
590
  mysys_var->current_cond = 0;
616
591
  this->set_proc_info(old_msg);
 
592
  pthread_mutex_unlock(&mysys_var->mutex);
617
593
}
618
594
 
619
595
bool Session::authenticate()
620
596
{
 
597
  lex_start(this);
621
598
  if (client->authenticate())
622
599
    return false;
623
600
 
626
603
  return true;
627
604
}
628
605
 
629
 
bool Session::checkUser(const std::string &passwd_str,
630
 
                        const std::string &in_db)
 
606
bool Session::checkUser(const char *passwd, uint32_t passwd_len, const char *in_db)
631
607
{
 
608
  const string passwd_str(passwd, passwd_len);
632
609
  bool is_authenticated=
633
 
    plugin::Authentication::isAuthenticated(user(), passwd_str);
 
610
    plugin::Authentication::isAuthenticated(getSecurityContext(),
 
611
                                            passwd_str);
634
612
 
635
613
  if (is_authenticated != true)
636
614
  {
640
618
  }
641
619
 
642
620
  /* Change database if necessary */
643
 
  if (not in_db.empty())
 
621
  if (in_db && in_db[0])
644
622
  {
645
 
    identifier::Schema identifier(in_db);
646
 
    if (change_db(this, identifier))
 
623
    SchemaIdentifier identifier(in_db);
 
624
    if (mysql_change_db(this, identifier))
647
625
    {
648
 
      /* change_db() has pushed the error message. */
 
626
      /* mysql_change_db() has pushed the error message. */
649
627
      return false;
650
628
    }
651
629
  }
652
630
  my_ok();
653
 
  password= not passwd_str.empty();
 
631
  password= test(passwd_len);          // remember for error messages
654
632
 
655
633
  /* Ready to handle queries */
656
634
  return true;
672
650
  main_da.reset_diagnostics_area();
673
651
 
674
652
  if (client->readCommand(&l_packet, &packet_length) == false)
675
 
  {
676
653
    return false;
677
 
  }
678
654
 
679
 
  if (getKilled() == KILL_CONNECTION)
 
655
  if (killed == KILL_CONNECTION)
680
656
    return false;
681
657
 
682
658
  if (packet_length == 0)
683
659
    return true;
684
660
 
685
 
  l_command= static_cast<enum_server_command>(l_packet[0]);
 
661
  l_command= (enum enum_server_command) (unsigned char) l_packet[0];
686
662
 
687
663
  if (command >= COM_END)
688
664
    command= COM_END;                           // Wrong command
689
665
 
690
666
  assert(packet_length);
691
 
  return not dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
 
667
  return ! dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
692
668
}
693
669
 
694
670
bool Session::readAndStoreQuery(const char *in_packet, uint32_t in_packet_length)
700
676
    in_packet_length--;
701
677
  }
702
678
  const char *pos= in_packet + in_packet_length; /* Point at end null */
703
 
  while (in_packet_length > 0 && (pos[-1] == ';' || my_isspace(charset() ,pos[-1])))
 
679
  while (in_packet_length > 0 &&
 
680
         (pos[-1] == ';' || my_isspace(charset() ,pos[-1])))
704
681
  {
705
682
    pos--;
706
683
    in_packet_length--;
707
684
  }
708
685
 
709
 
  std::string *new_query= new std::string(in_packet, in_packet + in_packet_length);
710
 
  // We can not be entirely sure _schema has a value
711
 
  if (_schema)
712
 
  {
713
 
    plugin::QueryRewriter::rewriteQuery(*_schema, *new_query);
714
 
  }
715
 
  query.reset(new_query);
716
 
  _state.reset(new session::State(in_packet, in_packet_length));
 
686
  query.assign(in_packet, in_packet + in_packet_length);
717
687
 
718
688
  return true;
719
689
}
738
708
       * (Which of course should never happen...)
739
709
       */
740
710
      server_status&= ~SERVER_STATUS_IN_TRANS;
741
 
      if (transaction_services.commitTransaction(*this, true))
 
711
      if (transaction_services.commitTransaction(this, true))
742
712
        result= false;
743
713
      options&= ~(OPTION_BEGIN);
744
714
      break;
755
725
    case ROLLBACK_AND_CHAIN:
756
726
    {
757
727
      server_status&= ~SERVER_STATUS_IN_TRANS;
758
 
      if (transaction_services.rollbackTransaction(*this, true))
 
728
      if (transaction_services.rollbackTransaction(this, true))
759
729
        result= false;
760
730
      options&= ~(OPTION_BEGIN);
761
731
      if (result == true && (completion == ROLLBACK_AND_CHAIN))
768
738
  }
769
739
 
770
740
  if (result == false)
771
 
  {
772
 
    my_error(static_cast<drizzled::error_t>(killed_errno()), MYF(0));
773
 
  }
 
741
    my_error(killed_errno(), MYF(0));
774
742
  else if ((result == true) && do_release)
775
 
  {
776
 
    setKilled(Session::KILL_CONNECTION);
777
 
  }
 
743
    killed= Session::KILL_CONNECTION;
778
744
 
779
745
  return result;
780
746
}
792
758
  if (options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
793
759
  {
794
760
    server_status&= ~SERVER_STATUS_IN_TRANS;
795
 
    if (transaction_services.commitTransaction(*this, true))
 
761
    if (transaction_services.commitTransaction(this, true))
796
762
      result= false;
797
763
  }
798
764
  options&= ~(OPTION_BEGIN);
803
769
{
804
770
  bool result= true;
805
771
 
806
 
  assert(! inTransaction());
807
 
 
808
 
  options|= OPTION_BEGIN;
809
 
  server_status|= SERVER_STATUS_IN_TRANS;
810
 
 
811
 
  if (plugin::TransactionalStorageEngine::notifyStartTransaction(this, opt))
 
772
  if (! endActiveTransaction())
812
773
  {
813
774
    result= false;
814
775
  }
 
776
  else
 
777
  {
 
778
    options|= OPTION_BEGIN;
 
779
    server_status|= SERVER_STATUS_IN_TRANS;
 
780
 
 
781
    if (plugin::TransactionalStorageEngine::notifyStartTransaction(this, opt))
 
782
    {
 
783
      result= false;
 
784
    }
 
785
  }
815
786
 
816
787
  return result;
817
788
}
833
804
    first_successful_insert_id_in_cur_stmt= 0;
834
805
    substitute_null_with_insert_id= true;
835
806
  }
836
 
 
837
807
  arg_of_last_insert_id_function= false;
838
 
 
839
808
  /* Free Items that were created during this execution */
840
809
  free_items();
841
 
 
842
 
  /* Reset _where. */
843
 
  _where= Session::DEFAULT_WHERE;
 
810
  /* Reset where. */
 
811
  where= Session::DEFAULT_WHERE;
844
812
 
845
813
  /* Reset the temporary shares we built */
846
 
  for_each(temporary_shares.begin(),
847
 
           temporary_shares.end(),
848
 
           DeletePtr());
 
814
  for (std::vector<TableShareInstance *>::iterator iter= temporary_shares.begin();
 
815
       iter != temporary_shares.end(); iter++)
 
816
  {
 
817
    delete *iter;
 
818
  }
849
819
  temporary_shares.clear();
850
820
}
851
821
 
871
841
                                     bool allocate_lex_string)
872
842
{
873
843
  if (allocate_lex_string)
874
 
    if (!(lex_str= (LEX_STRING *)getMemRoot()->allocate(sizeof(LEX_STRING))))
 
844
    if (!(lex_str= (LEX_STRING *)alloc(sizeof(LEX_STRING))))
875
845
      return 0;
876
846
  if (!(lex_str->str= mem_root->strmake_root(str, length)))
877
847
    return 0;
917
887
  return (result->send_fields(field_list));
918
888
}
919
889
 
920
 
void select_result::send_error(drizzled::error_t errcode, const char *err)
 
890
void select_result::send_error(uint32_t errcode, const char *err)
921
891
{
922
892
  my_message(errcode, err, MYF(0));
923
893
}
926
896
  Handling writing to file
927
897
************************************************************************/
928
898
 
929
 
void select_to_file::send_error(drizzled::error_t errcode,const char *err)
 
899
void select_to_file::send_error(uint32_t errcode,const char *err)
930
900
{
931
901
  my_message(errcode, err, MYF(0));
932
902
  if (file > 0)
933
903
  {
934
 
    (void) cache->end_io_cache();
 
904
    (void) end_io_cache(cache);
935
905
    (void) internal::my_close(file, MYF(0));
936
 
    (void) internal::my_delete(path.file_string().c_str(), MYF(0));             // Delete file on error
 
906
    (void) internal::my_delete(path, MYF(0));           // Delete file on error
937
907
    file= -1;
938
908
  }
939
909
}
941
911
 
942
912
bool select_to_file::send_eof()
943
913
{
944
 
  int error= test(cache->end_io_cache());
 
914
  int error= test(end_io_cache(cache));
945
915
  if (internal::my_close(file, MYF(MY_WME)))
946
916
    error= 1;
947
917
  if (!error)
963
933
  /* In case of error send_eof() may be not called: close the file here. */
964
934
  if (file >= 0)
965
935
  {
966
 
    (void) cache->end_io_cache();
 
936
    (void) end_io_cache(cache);
967
937
    (void) internal::my_close(file, MYF(0));
968
938
    file= -1;
969
939
  }
970
 
  path= "";
 
940
  path[0]= '\0';
971
941
  row_count= 0;
972
942
}
973
943
 
977
947
    cache(static_cast<internal::IO_CACHE *>(memory::sql_calloc(sizeof(internal::IO_CACHE)))),
978
948
    row_count(0L)
979
949
{
980
 
  path= "";
 
950
  path[0]=0;
981
951
}
982
952
 
983
953
select_to_file::~select_to_file()
1011
981
*/
1012
982
 
1013
983
 
1014
 
static int create_file(Session *session,
1015
 
                       fs::path &target_path,
1016
 
                       file_exchange *exchange,
1017
 
                       internal::IO_CACHE *cache)
 
984
static int create_file(Session *session, char *path, file_exchange *exchange, internal::IO_CACHE *cache)
1018
985
{
1019
 
  fs::path to_file(exchange->file_name);
1020
986
  int file;
1021
 
 
1022
 
  if (not to_file.has_root_directory())
 
987
  uint32_t option= MY_UNPACK_FILENAME | MY_RELATIVE_PATH;
 
988
 
 
989
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
 
990
  option|= MY_REPLACE_DIR;                      // Force use of db directory
 
991
#endif
 
992
 
 
993
  if (!internal::dirname_length(exchange->file_name))
1023
994
  {
1024
 
    target_path= fs::system_complete(getDataHomeCatalog());
1025
 
    util::string::const_shared_ptr schema(session->schema());
1026
 
    if (schema and not schema->empty())
1027
 
    {
1028
 
      int count_elements= 0;
1029
 
      for (fs::path::iterator iter= to_file.begin();
1030
 
           iter != to_file.end();
1031
 
           ++iter, ++count_elements)
1032
 
      { }
1033
 
 
1034
 
      if (count_elements == 1)
1035
 
      {
1036
 
        target_path /= *schema;
1037
 
      }
1038
 
    }
1039
 
    target_path /= to_file;
 
995
    strcpy(path, data_home_real);
 
996
    if (! session->db.empty())
 
997
      strncat(path, session->db.c_str(), FN_REFLEN-strlen(data_home_real)-1);
 
998
    (void) internal::fn_format(path, exchange->file_name, path, "", option);
1040
999
  }
1041
1000
  else
1042
 
  {
1043
 
    target_path = exchange->file_name;
1044
 
  }
1045
 
 
1046
 
  if (not secure_file_priv.string().empty())
1047
 
  {
1048
 
    if (target_path.file_string().substr(0, secure_file_priv.file_string().size()) != secure_file_priv.file_string())
1049
 
    {
1050
 
      /* Write only allowed to dir or subdir specified by secure_file_priv */
1051
 
      my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
1052
 
      return -1;
1053
 
    }
1054
 
  }
1055
 
 
1056
 
  if (!access(target_path.file_string().c_str(), F_OK))
 
1001
    (void) internal::fn_format(path, exchange->file_name, data_home_real, "", option);
 
1002
 
 
1003
  if (opt_secure_file_priv &&
 
1004
      strncmp(opt_secure_file_priv, path, strlen(opt_secure_file_priv)))
 
1005
  {
 
1006
    /* Write only allowed to dir or subdir specified by secure_file_priv */
 
1007
    my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
 
1008
    return -1;
 
1009
  }
 
1010
 
 
1011
  if (!access(path, F_OK))
1057
1012
  {
1058
1013
    my_error(ER_FILE_EXISTS_ERROR, MYF(0), exchange->file_name);
1059
1014
    return -1;
1060
1015
  }
1061
1016
  /* Create the file world readable */
1062
 
  if ((file= internal::my_create(target_path.file_string().c_str(), 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
 
1017
  if ((file= internal::my_create(path, 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
1063
1018
    return file;
1064
1019
  (void) fchmod(file, 0666);                    // Because of umask()
1065
 
  if (cache->init_io_cache(file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
 
1020
  if (init_io_cache(cache, file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1066
1021
  {
1067
1022
    internal::my_close(file, MYF(0));
1068
 
    internal::my_delete(target_path.file_string().c_str(), MYF(0));  // Delete file on error, it was just created
 
1023
    internal::my_delete(path, MYF(0));  // Delete file on error, it was just created
1069
1024
    return -1;
1070
1025
  }
1071
1026
  return file;
1079
1034
  bool string_results= false, non_string_results= false;
1080
1035
  unit= u;
1081
1036
  if ((uint32_t) strlen(exchange->file_name) + NAME_LEN >= FN_REFLEN)
1082
 
  {
1083
 
    path= exchange->file_name;
1084
 
  }
 
1037
    strncpy(path,exchange->file_name,FN_REFLEN-1);
1085
1038
 
1086
1039
  /* Check if there is any blobs in data */
1087
1040
  {
1091
1044
    {
1092
1045
      if (item->max_length >= MAX_BLOB_WIDTH)
1093
1046
      {
1094
 
        blob_flag=1;
1095
 
        break;
 
1047
        blob_flag=1;
 
1048
        break;
1096
1049
      }
1097
 
 
1098
1050
      if (item->result_type() == STRING_RESULT)
1099
1051
        string_results= true;
1100
1052
      else
1145
1097
  if (unit->offset_limit_cnt)
1146
1098
  {                                             // using limit offset,count
1147
1099
    unit->offset_limit_cnt--;
1148
 
    return false;
 
1100
    return(0);
1149
1101
  }
1150
1102
  row_count++;
1151
1103
  Item *item;
1154
1106
 
1155
1107
  if (my_b_write(cache,(unsigned char*) exchange->line_start->ptr(),
1156
1108
                 exchange->line_start->length()))
1157
 
    return true;
1158
 
 
 
1109
    goto err;
1159
1110
  while ((item=li++))
1160
1111
  {
1161
1112
    Item_result result_type=item->result_type();
1166
1117
    {
1167
1118
      if (my_b_write(cache,(unsigned char*) exchange->enclosed->ptr(),
1168
1119
                     exchange->enclosed->length()))
1169
 
        return true;
 
1120
        goto err;
1170
1121
    }
1171
1122
    if (!res)
1172
1123
    {                                           // NULL
1177
1128
          null_buff[0]=escape_char;
1178
1129
          null_buff[1]='N';
1179
1130
          if (my_b_write(cache,(unsigned char*) null_buff,2))
1180
 
            return true;
 
1131
            goto err;
1181
1132
        }
1182
1133
        else if (my_b_write(cache,(unsigned char*) "NULL",4))
1183
 
          return true;
 
1134
          goto err;
1184
1135
      }
1185
1136
      else
1186
1137
      {
1190
1141
    else
1191
1142
    {
1192
1143
      if (fixed_row_size)
1193
 
        used_length= min(res->length(), static_cast<size_t>(item->max_length));
 
1144
        used_length= min(res->length(),item->max_length);
1194
1145
      else
1195
1146
        used_length= res->length();
1196
1147
 
1271
1222
            tmp_buff[1]= *pos ? *pos : '0';
1272
1223
            if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)) ||
1273
1224
                my_b_write(cache,(unsigned char*) tmp_buff,2))
1274
 
              return true;
 
1225
              goto err;
1275
1226
            start=pos+1;
1276
1227
          }
1277
1228
        }
1278
1229
        if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)))
1279
 
          return true;
 
1230
          goto err;
1280
1231
      }
1281
1232
      else if (my_b_write(cache,(unsigned char*) res->ptr(),used_length))
1282
 
        return true;
 
1233
        goto err;
1283
1234
    }
1284
1235
    if (fixed_row_size)
1285
1236
    {                                           // Fill with space
1295
1246
        for (; length > sizeof(space) ; length-=sizeof(space))
1296
1247
        {
1297
1248
          if (my_b_write(cache,(unsigned char*) space,sizeof(space)))
1298
 
            return true;
 
1249
            goto err;
1299
1250
        }
1300
1251
        if (my_b_write(cache,(unsigned char*) space,length))
1301
 
          return true;
 
1252
          goto err;
1302
1253
      }
1303
1254
    }
1304
1255
    if (res && enclosed)
1305
1256
    {
1306
1257
      if (my_b_write(cache, (unsigned char*) exchange->enclosed->ptr(),
1307
1258
                     exchange->enclosed->length()))
1308
 
        return true;
 
1259
        goto err;
1309
1260
    }
1310
1261
    if (--items_left)
1311
1262
    {
1312
1263
      if (my_b_write(cache, (unsigned char*) exchange->field_term->ptr(),
1313
1264
                     field_term_length))
1314
 
        return true;
 
1265
        goto err;
1315
1266
    }
1316
1267
  }
1317
1268
  if (my_b_write(cache,(unsigned char*) exchange->line_term->ptr(),
1318
1269
                 exchange->line_term->length()))
1319
 
  {
1320
 
    return true;
1321
 
  }
1322
 
 
1323
 
  return false;
 
1270
    goto err;
 
1271
  return(0);
 
1272
err:
 
1273
  return(1);
1324
1274
}
1325
1275
 
1326
1276
 
1353
1303
  if (row_count++ > 1)
1354
1304
  {
1355
1305
    my_message(ER_TOO_MANY_ROWS, ER(ER_TOO_MANY_ROWS), MYF(0));
1356
 
    return 1;
 
1306
    goto err;
1357
1307
  }
1358
1308
  while ((item=li++))
1359
1309
  {
1361
1311
    if (!res)                                   // If NULL
1362
1312
    {
1363
1313
      if (my_b_write(cache,(unsigned char*) "",1))
1364
 
        return 1;
 
1314
        goto err;
1365
1315
    }
1366
1316
    else if (my_b_write(cache,(unsigned char*) res->ptr(),res->length()))
1367
1317
    {
1368
 
      my_error(ER_ERROR_ON_WRITE, MYF(0), path.file_string().c_str(), errno);
1369
 
      return 1;
 
1318
      my_error(ER_ERROR_ON_WRITE, MYF(0), path, errno);
 
1319
      goto err;
1370
1320
    }
1371
1321
  }
1372
1322
  return(0);
 
1323
err:
 
1324
  return(1);
1373
1325
}
1374
1326
 
1375
1327
 
1427
1379
      switch (val_item->result_type())
1428
1380
      {
1429
1381
      case REAL_RESULT:
1430
 
        op= &select_max_min_finder_subselect::cmp_real;
1431
 
        break;
 
1382
        op= &select_max_min_finder_subselect::cmp_real;
 
1383
        break;
1432
1384
      case INT_RESULT:
1433
 
        op= &select_max_min_finder_subselect::cmp_int;
1434
 
        break;
 
1385
        op= &select_max_min_finder_subselect::cmp_int;
 
1386
        break;
1435
1387
      case STRING_RESULT:
1436
 
        op= &select_max_min_finder_subselect::cmp_str;
1437
 
        break;
 
1388
        op= &select_max_min_finder_subselect::cmp_str;
 
1389
        break;
1438
1390
      case DECIMAL_RESULT:
1439
1391
        op= &select_max_min_finder_subselect::cmp_decimal;
1440
1392
        break;
1441
1393
      case ROW_RESULT:
1442
1394
        // This case should never be choosen
1443
 
        assert(0);
1444
 
        op= 0;
 
1395
        assert(0);
 
1396
        op= 0;
1445
1397
      }
1446
1398
    }
1447
1399
    cache->store(val_item);
1480
1432
bool select_max_min_finder_subselect::cmp_decimal()
1481
1433
{
1482
1434
  Item *maxmin= ((Item_singlerow_subselect *)item)->element_index(0);
1483
 
  type::Decimal cval, *cvalue= cache->val_decimal(&cval);
1484
 
  type::Decimal mval, *mvalue= maxmin->val_decimal(&mval);
 
1435
  my_decimal cval, *cvalue= cache->val_decimal(&cval);
 
1436
  my_decimal mval, *mvalue= maxmin->val_decimal(&mval);
1485
1437
  if (fmax)
1486
1438
    return (cache->null_value && !maxmin->null_value) ||
1487
1439
      (!cache->null_value && !maxmin->null_value &&
1488
 
       class_decimal_cmp(cvalue, mvalue) > 0) ;
 
1440
       my_decimal_cmp(cvalue, mvalue) > 0) ;
1489
1441
  return (maxmin->null_value && !cache->null_value) ||
1490
1442
    (!cache->null_value && !maxmin->null_value &&
1491
 
     class_decimal_cmp(cvalue,mvalue) < 0);
 
1443
     my_decimal_cmp(cvalue,mvalue) < 0);
1492
1444
}
1493
1445
 
1494
1446
bool select_max_min_finder_subselect::cmp_str()
1530
1482
void Session::end_statement()
1531
1483
{
1532
1484
  /* Cleanup SQL processing state to reuse this statement in next query. */
1533
 
  lex->end();
 
1485
  lex_end(lex);
1534
1486
  query_cache_key= ""; // reset the cache key
1535
1487
  resetResultsetMessage();
1536
1488
}
1537
1489
 
1538
1490
bool Session::copy_db_to(char **p_db, size_t *p_db_length)
1539
1491
{
1540
 
  assert(_schema);
1541
 
  if (_schema and _schema->empty())
1542
 
  {
1543
 
    my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
1544
 
    return true;
1545
 
  }
1546
 
  else if (not _schema)
1547
 
  {
1548
 
    my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
1549
 
    return true;
1550
 
  }
1551
 
  assert(_schema);
1552
 
 
1553
 
  *p_db= strmake(_schema->c_str(), _schema->size());
1554
 
  *p_db_length= _schema->size();
1555
 
 
 
1492
  if (db.empty())
 
1493
  {
 
1494
    my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
 
1495
    return true;
 
1496
  }
 
1497
  *p_db= strmake(db.c_str(), db.length());
 
1498
  *p_db_length= db.length();
1556
1499
  return false;
1557
1500
}
1558
1501
 
1574
1517
  /* Fix for Intel compiler */
1575
1518
  if (copy_field)
1576
1519
  {
1577
 
    boost::checked_array_delete(copy_field);
1578
 
    save_copy_field= save_copy_field_end= copy_field= copy_field_end= 0;
 
1520
    delete [] copy_field;
 
1521
    save_copy_field= copy_field= 0;
1579
1522
  }
1580
1523
}
1581
1524
 
1582
1525
void Session::send_kill_message() const
1583
1526
{
1584
 
  drizzled::error_t err= static_cast<drizzled::error_t>(killed_errno());
1585
 
  if (err != EE_OK)
 
1527
  int err= killed_errno();
 
1528
  if (err)
1586
1529
    my_message(err, ER(err), MYF(0));
1587
1530
}
1588
1531
 
1592
1535
}
1593
1536
 
1594
1537
 
1595
 
void Session::set_db(const std::string &new_db)
 
1538
bool Session::set_db(const std::string &new_db)
1596
1539
{
1597
1540
  /* Do not reallocate memory if current chunk is big enough. */
1598
1541
  if (new_db.length())
1599
 
  {
1600
 
    _schema.reset(new std::string(new_db));
1601
 
  }
 
1542
    db= new_db;
1602
1543
  else
1603
 
  {
1604
 
    _schema.reset(new std::string(""));
1605
 
  }
1606
 
}
1607
 
 
 
1544
    db.clear();
 
1545
 
 
1546
  return false;
 
1547
}
 
1548
 
 
1549
 
 
1550
 
 
1551
 
 
1552
/**
 
1553
  Check the killed state of a user thread
 
1554
  @param session  user thread
 
1555
  @retval 0 the user thread is active
 
1556
  @retval 1 the user thread has been killed
 
1557
*/
 
1558
int session_killed(const Session *session)
 
1559
{
 
1560
  return(session->killed);
 
1561
}
 
1562
 
 
1563
 
 
1564
const struct charset_info_st *session_charset(Session *session)
 
1565
{
 
1566
  return(session->charset());
 
1567
}
1608
1568
 
1609
1569
/**
1610
1570
  Mark transaction to rollback and mark error as fatal to a sub-statement.
1612
1572
  @param  session   Thread handle
1613
1573
  @param  all   true <=> rollback main transaction.
1614
1574
*/
1615
 
void Session::markTransactionForRollback(bool all)
 
1575
void mark_transaction_to_rollback(Session *session, bool all)
1616
1576
{
1617
 
  is_fatal_sub_stmt_error= true;
1618
 
  transaction_rollback_request= all;
 
1577
  if (session)
 
1578
  {
 
1579
    session->is_fatal_sub_stmt_error= true;
 
1580
    session->transaction_rollback_request= all;
 
1581
  }
1619
1582
}
1620
1583
 
1621
 
void Session::disconnect(enum error_t errcode)
 
1584
void Session::disconnect(uint32_t errcode, bool should_lock)
1622
1585
{
1623
1586
  /* Allow any plugins to cleanup their session variables */
1624
1587
  plugin_sessionvar_cleanup(this);
1625
1588
 
1626
1589
  /* If necessary, log any aborted or unauthorized connections */
1627
 
  if (getKilled() || client->wasAborted())
 
1590
  if (killed || client->wasAborted())
1628
1591
  {
1629
1592
    status_var.aborted_threads++;
1630
1593
  }
1631
1594
 
1632
1595
  if (client->wasAborted())
1633
1596
  {
1634
 
    if (not getKilled() && variables.log_warnings > 1)
 
1597
    if (! killed && variables.log_warnings > 1)
1635
1598
    {
1636
 
      errmsg_printf(error::WARN, ER(ER_NEW_ABORTING_CONNECTION)
 
1599
      SecurityContext *sctx= &security_ctx;
 
1600
 
 
1601
      errmsg_printf(ERRMSG_LVL_WARN, ER(ER_NEW_ABORTING_CONNECTION)
1637
1602
                  , thread_id
1638
 
                  , (_schema->empty() ? "unconnected" : _schema->c_str())
1639
 
                  , security_ctx->username().empty() == false ? security_ctx->username().c_str() : "unauthenticated"
1640
 
                  , security_ctx->address().c_str()
 
1603
                  , (db.empty() ? "unconnected" : db.c_str())
 
1604
                  , sctx->getUser().empty() == false ? sctx->getUser().c_str() : "unauthenticated"
 
1605
                  , sctx->getIp().c_str()
1641
1606
                  , (main_da.is_error() ? main_da.message() : ER(ER_UNKNOWN_ERROR)));
1642
1607
    }
1643
1608
  }
1644
1609
 
1645
 
  setKilled(Session::KILL_CONNECTION);
1646
 
 
 
1610
  /* Close out our connection to the client */
 
1611
  if (should_lock)
 
1612
    LOCK_thread_count.lock();
 
1613
  killed= Session::KILL_CONNECTION;
1647
1614
  if (client->isConnected())
1648
1615
  {
1649
 
    if (errcode != EE_OK)
 
1616
    if (errcode)
1650
1617
    {
1651
1618
      /*my_error(errcode, ER(errcode));*/
1652
1619
      client->sendError(errcode, ER(errcode));
1653
1620
    }
1654
1621
    client->close();
1655
1622
  }
 
1623
  if (should_lock)
 
1624
    (void) LOCK_thread_count.unlock();
1656
1625
}
1657
1626
 
1658
1627
void Session::reset_for_next_command()
1680
1649
  Close all temporary tables created by 'CREATE TEMPORARY TABLE' for thread
1681
1650
*/
1682
1651
 
1683
 
void Open_tables_state::close_temporary_tables()
 
1652
void Session::close_temporary_tables()
1684
1653
{
1685
1654
  Table *table;
1686
1655
  Table *tmp_next;
1700
1669
  unlink from session->temporary tables and close temporary table
1701
1670
*/
1702
1671
 
1703
 
void Open_tables_state::close_temporary_table(Table *table)
 
1672
void Session::close_temporary_table(Table *table)
1704
1673
{
1705
1674
  if (table->getPrev())
1706
1675
  {
1736
1705
  If this is needed, use close_temporary_table()
1737
1706
*/
1738
1707
 
1739
 
void Open_tables_state::nukeTable(Table *table)
 
1708
void Session::nukeTable(Table *table)
1740
1709
{
1741
1710
  plugin::StorageEngine *table_type= table->getShare()->db_type();
1742
1711
 
1743
1712
  table->free_io_cache();
1744
1713
  table->delete_table();
1745
1714
 
1746
 
  identifier::Table identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName(), table->getShare()->getPath());
 
1715
  TableIdentifier identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName(), table->getShare()->getPath());
1747
1716
  rm_temporary_table(table_type, identifier);
1748
1717
 
1749
 
  boost::checked_delete(table->getMutableShare());
 
1718
  delete table->getMutableShare();
1750
1719
 
1751
 
  boost::checked_delete(table);
 
1720
  /* This makes me sad, but we're allocating it via malloc */
 
1721
  delete table;
1752
1722
}
1753
1723
 
1754
1724
/** Clear most status variables. */
1766
1736
 
1767
1737
user_var_entry *Session::getVariable(LEX_STRING &name, bool create_if_not_exists)
1768
1738
{
1769
 
  return getVariable(std::string(name.str, name.length), create_if_not_exists);
1770
 
}
1771
 
 
1772
 
user_var_entry *Session::getVariable(const std::string  &name, bool create_if_not_exists)
1773
 
{
1774
 
  if (cleanup_done)
1775
 
    return NULL;
1776
 
 
1777
 
  UserVars::iterator iter= user_vars.find(name);
1778
 
  if (iter != user_vars.end())
1779
 
    return (*iter).second;
1780
 
 
1781
 
  if (not create_if_not_exists)
1782
 
    return NULL;
1783
 
 
1784
1739
  user_var_entry *entry= NULL;
1785
 
  entry= new (nothrow) user_var_entry(name.c_str(), query_id);
1786
 
 
1787
 
  if (entry == NULL)
1788
 
    return NULL;
1789
 
 
1790
 
  std::pair<UserVars::iterator, bool> returnable= user_vars.insert(make_pair(name, entry));
1791
 
 
1792
 
  if (not returnable.second)
1793
 
  {
1794
 
    boost::checked_delete(entry);
 
1740
  UserVarsRange ppp= user_vars.equal_range(std::string(name.str, name.length));
 
1741
 
 
1742
  for (UserVars::iterator iter= ppp.first;
 
1743
         iter != ppp.second; ++iter)
 
1744
  {
 
1745
    entry= (*iter).second;
 
1746
  }
 
1747
 
 
1748
  if ((entry == NULL) && create_if_not_exists)
 
1749
  {
 
1750
    entry= new (nothrow) user_var_entry(name.str, query_id);
 
1751
 
 
1752
    if (entry == NULL)
 
1753
      return NULL;
 
1754
 
 
1755
    std::pair<UserVars::iterator, bool> returnable= user_vars.insert(make_pair(std::string(name.str, name.length), entry));
 
1756
 
 
1757
    if (not returnable.second)
 
1758
    {
 
1759
      delete entry;
 
1760
      return NULL;
 
1761
    }
1795
1762
  }
1796
1763
 
1797
1764
  return entry;
1798
1765
}
1799
1766
 
1800
 
void Session::setVariable(const std::string &name, const std::string &value)
1801
 
{
1802
 
  user_var_entry *updateable_var= getVariable(name.c_str(), true);
1803
 
  if (updateable_var)
1804
 
  {
1805
 
    updateable_var->update_hash(false,
1806
 
                                (void*)value.c_str(),
1807
 
                                static_cast<uint32_t>(value.length()), STRING_RESULT,
1808
 
                                &my_charset_bin,
1809
 
                                DERIVATION_IMPLICIT, false);
1810
 
  }
1811
 
}
1812
 
 
1813
 
void Open_tables_state::mark_temp_tables_as_free_for_reuse()
 
1767
void Session::mark_temp_tables_as_free_for_reuse()
1814
1768
{
1815
1769
  for (Table *table= temporary_tables ; table ; table= table->getNext())
1816
1770
  {
1817
 
    if (table->query_id == getQueryId())
 
1771
    if (table->query_id == query_id)
1818
1772
    {
1819
1773
      table->query_id= 0;
1820
1774
      table->cursor->ha_reset();
1826
1780
{
1827
1781
  for (; table ; table= table->getNext())
1828
1782
  {
1829
 
    if (table->query_id == getQueryId())
 
1783
    if (table->query_id == query_id)
1830
1784
    {
1831
1785
      table->query_id= 0;
1832
1786
      table->cursor->ha_reset();
1845
1799
*/
1846
1800
void Session::close_thread_tables()
1847
1801
{
1848
 
  clearDerivedTables();
 
1802
  if (derived_tables)
 
1803
    derived_tables= NULL; // They should all be invalid by this point
1849
1804
 
1850
1805
  /*
1851
1806
    Mark all temporary tables used by this statement as free for reuse.
1862
1817
  {
1863
1818
    TransactionServices &transaction_services= TransactionServices::singleton();
1864
1819
    main_da.can_overwrite_status= true;
1865
 
    transaction_services.autocommitOrRollback(*this, is_error());
 
1820
    transaction_services.autocommitOrRollback(this, is_error());
1866
1821
    main_da.can_overwrite_status= false;
1867
1822
    transaction.stmt.reset();
1868
1823
  }
1878
1833
      handled either before writing a query log event (inside
1879
1834
      binlog_query()) or when preparing a pending event.
1880
1835
     */
1881
 
    unlockTables(lock);
 
1836
    mysql_unlock_tables(this, lock);
1882
1837
    lock= 0;
1883
1838
  }
1884
1839
  /*
1885
 
    Note that we need to hold table::Cache::singleton().mutex() while changing the
 
1840
    Note that we need to hold LOCK_open while changing the
1886
1841
    open_tables list. Another thread may work on it.
1887
 
    (See: table::Cache::singleton().removeTable(), wait_completed_table())
 
1842
    (See: remove_table_from_cache(), mysql_wait_completed_table())
1888
1843
    Closing a MERGE child before the parent would be fatal if the
1889
1844
    other thread tries to abort the MERGE lock in between.
1890
1845
  */
1918
1873
 
1919
1874
    if (not lock_tables(tables, counter, &need_reopen))
1920
1875
      break;
1921
 
 
1922
1876
    if (not need_reopen)
1923
1877
      return true;
1924
 
 
1925
1878
    close_tables_for_reopen(&tables);
1926
1879
  }
1927
 
 
1928
 
  if ((handle_derived(lex, &derived_prepare) || (handle_derived(lex, &derived_filling))))
1929
 
    return true;
1930
 
 
 
1880
  if ((mysql_handle_derived(lex, &mysql_derived_prepare) ||
 
1881
       (fill_derived_tables() &&
 
1882
        mysql_handle_derived(lex, &mysql_derived_filling))))
 
1883
    return true;
 
1884
 
 
1885
  return false;
 
1886
}
 
1887
 
 
1888
bool Session::openTables(TableList *tables, uint32_t flags)
 
1889
{
 
1890
  uint32_t counter;
 
1891
  bool ret= fill_derived_tables();
 
1892
  assert(ret == false);
 
1893
  if (open_tables_from_list(&tables, &counter, flags) ||
 
1894
      mysql_handle_derived(lex, &mysql_derived_prepare))
 
1895
  {
 
1896
    return true;
 
1897
  }
1931
1898
  return false;
1932
1899
}
1933
1900
 
1937
1904
  might be an issue (lame engines).
1938
1905
*/
1939
1906
 
1940
 
bool Open_tables_state::rm_temporary_table(const identifier::Table &identifier, bool best_effort)
 
1907
bool Session::rm_temporary_table(TableIdentifier &identifier, bool best_effort)
1941
1908
{
1942
 
  if (not plugin::StorageEngine::dropTable(*static_cast<Session *>(this), identifier))
 
1909
  if (plugin::StorageEngine::dropTable(*this, identifier))
1943
1910
  {
1944
1911
    if (not best_effort)
1945
1912
    {
1946
 
      std::string path;
1947
 
      identifier.getSQLPath(path);
1948
 
      errmsg_printf(error::WARN, _("Could not remove temporary table: '%s', error: %d"),
1949
 
                    path.c_str(), errno);
 
1913
      errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
 
1914
                    identifier.getSQLPath().c_str(), errno);
1950
1915
    }
1951
1916
 
1952
1917
    return true;
1955
1920
  return false;
1956
1921
}
1957
1922
 
1958
 
bool Open_tables_state::rm_temporary_table(plugin::StorageEngine *base, const identifier::Table &identifier)
 
1923
bool Session::rm_temporary_table(plugin::StorageEngine *base, TableIdentifier &identifier)
1959
1924
{
1960
 
  drizzled::error_t error;
1961
1925
  assert(base);
1962
1926
 
1963
 
  if (not plugin::StorageEngine::dropTable(*static_cast<Session *>(this), *base, identifier, error))
 
1927
  if (plugin::StorageEngine::dropTable(*this, *base, identifier))
1964
1928
  {
1965
 
    std::string path;
1966
 
    identifier.getSQLPath(path);
1967
 
    errmsg_printf(error::WARN, _("Could not remove temporary table: '%s', error: %d"),
1968
 
                  path.c_str(), error);
 
1929
    errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
 
1930
                  identifier.getSQLPath().c_str(), errno);
1969
1931
 
1970
1932
    return true;
1971
1933
  }
1977
1939
  @note this will be removed, I am looking through Hudson to see if it is finding
1978
1940
  any tables that are missed during cleanup.
1979
1941
*/
1980
 
void Open_tables_state::dumpTemporaryTableNames(const char *foo)
 
1942
void Session::dumpTemporaryTableNames(const char *foo)
1981
1943
{
1982
1944
  Table *table;
1983
1945
 
1989
1951
  {
1990
1952
    bool have_proto= false;
1991
1953
 
1992
 
    message::Table *proto= table->getShare()->getTableMessage();
1993
 
    if (table->getShare()->getTableMessage())
 
1954
    message::Table *proto= table->getShare()->getTableProto();
 
1955
    if (table->getShare()->getTableProto())
1994
1956
      have_proto= true;
1995
1957
 
1996
1958
    const char *answer= have_proto ? "true" : "false";
2001
1963
      cerr << "\t\t Proto " << proto->schema() << " " << proto->name() << "\n";
2002
1964
    }
2003
1965
    else
2004
 
    {
2005
1966
      cerr << "\tTabl;e Name " << table->getShare()->getSchemaName() << "." << table->getShare()->getTableName() << " : " << answer << "\n";
2006
 
    }
2007
 
  }
2008
 
}
2009
 
 
2010
 
table::Singular *Session::getInstanceTable()
2011
 
{
2012
 
  temporary_shares.push_back(new table::Singular()); // This will not go into the tableshare cache, so no key is used.
2013
 
 
2014
 
  table::Singular *tmp_share= temporary_shares.back();
2015
 
 
2016
 
  assert(tmp_share);
2017
 
 
2018
 
  return tmp_share;
2019
 
}
2020
 
 
2021
 
 
2022
 
/**
2023
 
  Create a reduced Table object with properly set up Field list from a
2024
 
  list of field definitions.
2025
 
 
2026
 
    The created table doesn't have a table Cursor associated with
2027
 
    it, has no keys, no group/distinct, no copy_funcs array.
2028
 
    The sole purpose of this Table object is to use the power of Field
2029
 
    class to read/write data to/from table->getInsertRecord(). Then one can store
2030
 
    the record in any container (RB tree, hash, etc).
2031
 
    The table is created in Session mem_root, so are the table's fields.
2032
 
    Consequently, if you don't BLOB fields, you don't need to free it.
2033
 
 
2034
 
  @param session         connection handle
2035
 
  @param field_list  list of column definitions
2036
 
 
2037
 
  @return
2038
 
    0 if out of memory, Table object in case of success
2039
 
*/
2040
 
table::Singular *Session::getInstanceTable(List<CreateField> &field_list)
2041
 
{
2042
 
  temporary_shares.push_back(new table::Singular(this, field_list)); // This will not go into the tableshare cache, so no key is used.
2043
 
 
2044
 
  table::Singular *tmp_share= temporary_shares.back();
2045
 
 
2046
 
  assert(tmp_share);
2047
 
 
2048
 
  return tmp_share;
2049
 
}
2050
 
 
2051
 
namespace display  {
2052
 
 
2053
 
static const std::string NONE= "NONE";
2054
 
static const std::string GOT_GLOBAL_READ_LOCK= "HAS GLOBAL READ LOCK";
2055
 
static const std::string MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT= "HAS GLOBAL READ LOCK WITH BLOCKING COMMIT";
2056
 
 
2057
 
const std::string &type(drizzled::Session::global_read_lock_t type)
2058
 
{
2059
 
  switch (type) {
2060
 
    default:
2061
 
    case Session::NONE:
2062
 
      return NONE;
2063
 
    case Session::GOT_GLOBAL_READ_LOCK:
2064
 
      return GOT_GLOBAL_READ_LOCK;
2065
 
    case Session::MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT:
2066
 
      return MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT;
2067
 
  }
2068
 
}
2069
 
 
2070
 
size_t max_string_length(drizzled::Session::global_read_lock_t)
2071
 
{
2072
 
  return MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT.size();
2073
 
}
2074
 
 
2075
 
} /* namespace display */
 
1967
  }
 
1968
}
 
1969
 
 
1970
bool Session::storeTableMessage(const TableIdentifier &identifier, message::Table &table_message)
 
1971
{
 
1972
  table_message_cache.insert(make_pair(identifier.getPath(), table_message));
 
1973
 
 
1974
  return true;
 
1975
}
 
1976
 
 
1977
bool Session::removeTableMessage(const TableIdentifier &identifier)
 
1978
{
 
1979
  TableMessageCache::iterator iter;
 
1980
 
 
1981
  iter= table_message_cache.find(identifier.getPath());
 
1982
 
 
1983
  if (iter == table_message_cache.end())
 
1984
    return false;
 
1985
 
 
1986
  table_message_cache.erase(iter);
 
1987
 
 
1988
  return true;
 
1989
}
 
1990
 
 
1991
bool Session::getTableMessage(const TableIdentifier &identifier, message::Table &table_message)
 
1992
{
 
1993
  TableMessageCache::iterator iter;
 
1994
 
 
1995
  iter= table_message_cache.find(identifier.getPath());
 
1996
 
 
1997
  if (iter == table_message_cache.end())
 
1998
    return false;
 
1999
 
 
2000
  table_message.CopyFrom(((*iter).second));
 
2001
 
 
2002
  return true;
 
2003
}
 
2004
 
 
2005
bool Session::doesTableMessageExist(const TableIdentifier &identifier)
 
2006
{
 
2007
  TableMessageCache::iterator iter;
 
2008
 
 
2009
  iter= table_message_cache.find(identifier.getPath());
 
2010
 
 
2011
  if (iter == table_message_cache.end())
 
2012
  {
 
2013
    return false;
 
2014
  }
 
2015
 
 
2016
  return true;
 
2017
}
 
2018
 
 
2019
bool Session::renameTableMessage(const TableIdentifier &from, const TableIdentifier &to)
 
2020
{
 
2021
  TableMessageCache::iterator iter;
 
2022
 
 
2023
  table_message_cache[to.getPath()]= table_message_cache[from.getPath()];
 
2024
 
 
2025
  iter= table_message_cache.find(to.getPath());
 
2026
 
 
2027
  if (iter == table_message_cache.end())
 
2028
  {
 
2029
    return false;
 
2030
  }
 
2031
 
 
2032
  (*iter).second.set_schema(to.getSchemaName());
 
2033
  (*iter).second.set_name(to.getTableName());
 
2034
 
 
2035
  return true;
 
2036
}
 
2037
 
 
2038
TableShareInstance *Session::getTemporaryShare(TableIdentifier::Type type_arg)
 
2039
{
 
2040
  temporary_shares.push_back(new TableShareInstance(type_arg)); // This will not go into the tableshare cache, so no key is used.
 
2041
 
 
2042
  TableShareInstance *tmp_share= temporary_shares.back();
 
2043
 
 
2044
  assert(tmp_share);
 
2045
 
 
2046
  return tmp_share;
 
2047
}
2076
2048
 
2077
2049
} /* namespace drizzled */