~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/session.cc

  • Committer: Brian Aker
  • Date: 2010-08-18 23:12:07 UTC
  • mto: This revision was merged to the branch mainline in revision 1719.
  • Revision ID: brian@tangent.org-20100818231207-2dgclr6o06q90np1
Test scoped ptr in the tree.

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_share_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 <fcntl.h>
71
59
#include <algorithm>
72
60
#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>
82
61
 
83
62
using namespace std;
84
 
 
85
 
namespace fs=boost::filesystem;
86
63
namespace drizzled
87
64
{
88
65
 
94
71
char empty_c_string[1]= {0};    /* used for not defined db */
95
72
 
96
73
const char * const Session::DEFAULT_WHERE= "field list";
 
74
extern pthread_key_t THR_Session;
 
75
extern pthread_key_t THR_Mem_root;
97
76
 
98
77
bool Key_part_spec::operator==(const Key_part_spec& other) const
99
78
{
100
79
  return length == other.length &&
101
80
         field_name.length == other.field_name.length &&
102
 
    !my_strcasecmp(system_charset_info, field_name.str, other.field_name.str);
 
81
         !strcmp(field_name.str, other.field_name.str);
103
82
}
104
83
 
105
84
Open_tables_state::Open_tables_state(uint64_t version_arg) :
112
91
/*
113
92
  The following functions form part of the C plugin API
114
93
*/
115
 
int tmpfile(const char *prefix)
 
94
int mysql_tmpfile(const char *prefix)
116
95
{
117
96
  char filename[FN_REFLEN];
118
97
  int fd = internal::create_temp_file(filename, drizzle_tmpdir.c_str(), prefix, MYF(MY_WME));
123
102
  return fd;
124
103
}
125
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
 
126
128
void **Session::getEngineData(const plugin::MonitoredInTransaction *monitored)
127
129
{
128
130
  return static_cast<void **>(&ha_data[monitored->getId()].ha_ptr);
139
141
  return session->options & test_options;
140
142
}
141
143
 
142
 
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) :
143
155
  Open_tables_state(refresh_version),
144
156
  mem_root(&main_mem_root),
145
 
  xa_id(0),
146
157
  lex(&main_lex),
147
 
  query(new std::string),
148
 
  _schema(new std::string("")),
 
158
  query(),
149
159
  client(client_arg),
150
160
  scheduler(NULL),
151
161
  scheduler_arg(NULL),
152
162
  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),
 
163
  user_time(0),
163
164
  ha_data(plugin::num_trx_monitored_objects),
164
 
  query_id(0),
165
 
  warn_query_id(0),
166
 
  concurrent_execute_allowed(true),
167
165
  arg_of_last_insert_id_function(false),
168
166
  first_successful_insert_id_in_prev_stmt(0),
169
167
  first_successful_insert_id_in_cur_stmt(0),
170
168
  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),
 
169
  global_read_lock(0),
185
170
  some_tables_deleted(false),
186
171
  no_errors(false),
187
172
  password(false),
188
173
  is_fatal_error(false),
189
174
  transaction_rollback_request(false),
190
175
  is_fatal_sub_stmt_error(0),
 
176
  derived_tables_processing(false),
191
177
  tablespace_op(false),
192
 
  derived_tables_processing(false),
193
178
  m_lip(NULL),
194
179
  cached_table(0),
195
180
  transaction_message(NULL),
196
181
  statement_message(NULL),
197
 
  session_event_observers(NULL),
198
 
  _catalog(catalog_arg),
199
 
  use_usage(false)
 
182
  session_event_observers(NULL)
200
183
{
 
184
  memset(process_list_info, 0, PROCESS_LIST_WIDTH);
201
185
  client->setSession(this);
202
186
 
203
187
  /*
206
190
    will be re-initialized in init_for_queries().
207
191
  */
208
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;
209
199
  cuted_fields= sent_row_count= row_count= 0L;
 
200
  row_count_func= -1;
 
201
  statement_id_counter= 0UL;
210
202
  // Must be reset to handle error with Session's created for init of mysqld
211
203
  lex->current_select= 0;
 
204
  start_time=(time_t) 0;
 
205
  start_utime= 0L;
 
206
  utime_after_lock= 0L;
212
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;
213
213
  scoreboard_index= -1;
214
 
  cleanup_done= abort_on_warning= no_warnings_for_error= false;  
215
 
 
216
 
  /* query_cache init */
217
 
  query_cache_key= "";
218
 
  resultset= NULL;
 
214
  dbug_sentry=Session_SENTRY_MAGIC;
 
215
  cleanup_done= abort_on_warning= no_warnings_for_error= false;
219
216
 
220
217
  /* Variables with default values */
221
218
  proc_info="login";
 
219
  where= Session::DEFAULT_WHERE;
 
220
  command= COM_CONNECT;
222
221
 
223
222
  plugin_sessionvar_init(this);
224
223
  /*
228
227
  */
229
228
  variables.pseudo_thread_id= thread_id;
230
229
  server_status= SERVER_STATUS_AUTOCOMMIT;
 
230
  options= session_startup_options;
231
231
 
232
232
  if (variables.max_join_size == HA_POS_ERROR)
233
233
    options |= OPTION_BIG_SELECTS;
237
237
  open_options=ha_open_options;
238
238
  update_lock_default= TL_WRITE;
239
239
  session_tx_isolation= (enum_tx_isolation) variables.tx_isolation;
240
 
  warn_list.clear();
 
240
  warn_list.empty();
241
241
  memset(warn_count, 0, sizeof(warn_count));
 
242
  total_warn_count= 0;
242
243
  memset(&status_var, 0, sizeof(status_var));
243
244
 
244
245
  /* Initialize sub structures */
274
275
  m_internal_handler= handler;
275
276
}
276
277
 
277
 
bool Session::handle_error(drizzled::error_t sql_errno, const char *message,
278
 
                           DRIZZLE_ERROR::enum_warning_level level)
 
278
bool Session::handle_error(uint32_t sql_errno, const char *message,
 
279
                       DRIZZLE_ERROR::enum_warning_level level)
279
280
{
280
281
  if (m_internal_handler)
281
282
  {
296
297
    return;
297
298
 
298
299
  setAbort(true);
299
 
  boost_unique_lock_t scopedLock(mysys_var->mutex);
 
300
  pthread_mutex_lock(&mysys_var->mutex);
300
301
  if (mysys_var->current_cond)
301
302
  {
302
 
    mysys_var->current_mutex->lock();
303
 
    mysys_var->current_cond->notify_all();
304
 
    mysys_var->current_mutex->unlock();
 
303
    pthread_mutex_lock(mysys_var->current_mutex);
 
304
    pthread_cond_broadcast(mysys_var->current_cond);
 
305
    pthread_mutex_unlock(mysys_var->current_mutex);
305
306
  }
 
307
  pthread_mutex_unlock(&mysys_var->mutex);
306
308
}
307
309
 
308
310
void Session::pop_internal_handler()
311
313
  m_internal_handler= NULL;
312
314
}
313
315
 
314
 
void Session::get_xid(DrizzleXid *xid)
 
316
void Session::get_xid(DRIZZLE_XID *xid)
315
317
{
316
 
  *xid = *(DrizzleXid *) &transaction.xid_state.xid;
 
318
  *xid = *(DRIZZLE_XID *) &transaction.xid_state.xid;
317
319
}
318
320
 
319
321
/* Do operations that may take a long time */
322
324
{
323
325
  assert(cleanup_done == false);
324
326
 
325
 
  setKilled(KILL_CONNECTION);
 
327
  killed= KILL_CONNECTION;
326
328
#ifdef ENABLE_WHEN_BINLOG_WILL_BE_ABLE_TO_PREPARE
327
329
  if (transaction.xid_state.xa_state == XA_PREPARED)
328
330
  {
331
333
#endif
332
334
  {
333
335
    TransactionServices &transaction_services= TransactionServices::singleton();
334
 
    transaction_services.rollbackTransaction(*this, true);
 
336
    transaction_services.rollbackTransaction(this, true);
335
337
    xid_cache_delete(&transaction.xid_state);
336
338
  }
337
339
 
340
342
       iter++)
341
343
  {
342
344
    user_var_entry *entry= (*iter).second;
343
 
    boost::checked_delete(entry);
 
345
    delete entry;
344
346
  }
345
347
  user_vars.clear();
346
348
 
348
350
  close_temporary_tables();
349
351
 
350
352
  if (global_read_lock)
351
 
  {
352
 
    unlockGlobalReadLock();
353
 
  }
 
353
    unlock_global_read_lock(this);
354
354
 
355
355
  cleanup_done= true;
356
356
}
359
359
{
360
360
  this->checkSentry();
361
361
 
362
 
  if (client and client->isConnected())
 
362
  if (client->isConnected())
363
363
  {
364
 
    assert(security_ctx);
365
364
    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();
 
365
        errmsg_printf(ERRMSG_LVL_WARN, ER(ER_FORCING_CLOSE),internal::my_progname,
 
366
                      thread_id,
 
367
                      (getSecurityContext().getUser().c_str() ?
 
368
                       getSecurityContext().getUser().c_str() : ""));
 
369
    disconnect(0, false);
374
370
  }
375
371
 
376
372
  /* Close connection */
377
 
  if (client)
378
 
  {
379
 
    client->close();
380
 
    boost::checked_delete(client);
381
 
    client= NULL;
382
 
  }
 
373
  client->close();
 
374
  delete client;
383
375
 
384
376
  if (cleanup_done == false)
385
377
    cleanup();
392
384
  dbug_sentry= Session_SENTRY_GONE;
393
385
 
394
386
  main_mem_root.free_root(MYF(0));
395
 
  currentMemRoot().release();
396
 
  currentSession().release();
 
387
  pthread_setspecific(THR_Session,  0);
397
388
 
398
389
  plugin::Logging::postEndDo(this);
399
390
  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
 
 
 
391
 
 
392
  /* Ensure that no one is using Session */
 
393
  LOCK_delete.unlock();
 
394
}
 
395
 
 
396
void Session::awake(Session::killed_state state_to_set)
 
397
{
413
398
  this->checkSentry();
414
 
 
415
 
  setKilled(state_to_set);
416
 
  scheduler->killSession(this);
417
 
 
 
399
  safe_mutex_assert_owner(&LOCK_delete);
 
400
 
 
401
  killed= state_to_set;
418
402
  if (state_to_set != Session::KILL_QUERY)
419
403
  {
 
404
    scheduler->killSession(this);
420
405
    DRIZZLE_CONNECTION_DONE(thread_id);
421
406
  }
422
 
 
423
407
  if (mysys_var)
424
408
  {
425
 
    boost_unique_lock_t scopedLock(mysys_var->mutex);
 
409
    pthread_mutex_lock(&mysys_var->mutex);
426
410
    /*
427
 
      "
428
411
      This broadcast could be up in the air if the victim thread
429
412
      exits the cond in the time between read and broadcast, but that is
430
413
      ok since all we want to do is to make the victim thread get out
445
428
    */
446
429
    if (mysys_var->current_cond && mysys_var->current_mutex)
447
430
    {
448
 
      mysys_var->current_mutex->lock();
449
 
      mysys_var->current_cond->notify_all();
450
 
      mysys_var->current_mutex->unlock();
 
431
      pthread_mutex_lock(mysys_var->current_mutex);
 
432
      pthread_cond_broadcast(mysys_var->current_cond);
 
433
      pthread_mutex_unlock(mysys_var->current_mutex);
451
434
    }
 
435
    pthread_mutex_unlock(&mysys_var->mutex);
452
436
  }
453
437
}
454
438
 
464
448
  */
465
449
  assert(thread_stack);
466
450
 
467
 
  currentSession().release();
468
 
  currentSession().reset(this);
469
 
 
470
 
  currentMemRoot().release();
471
 
  currentMemRoot().reset(&mem_root);
 
451
  if (pthread_setspecific(THR_Session,  this) ||
 
452
      pthread_setspecific(THR_Mem_root, &mem_root))
 
453
    return true;
472
454
 
473
455
  mysys_var=my_thread_var;
474
456
 
477
459
    This allows us to move Session to different threads if needed.
478
460
  */
479
461
  mysys_var->id= thread_id;
 
462
  real_id= pthread_self();                      // For debugging
480
463
 
481
464
  /*
482
465
    We have to call thr_lock_info_init() again here as Session may have been
507
490
                                variables.query_prealloc_size);
508
491
  transaction.xid_state.xid.null();
509
492
  transaction.xid_state.in_session=1;
510
 
  if (use_usage)
511
 
    resetUsage();
512
493
}
513
494
 
514
495
bool Session::initGlobals()
515
496
{
516
497
  if (storeGlobals())
517
498
  {
518
 
    disconnect(ER_OUT_OF_RESOURCES);
 
499
    disconnect(ER_OUT_OF_RESOURCES, true);
519
500
    status_var.aborted_connects++;
520
501
    return true;
521
502
  }
526
507
{
527
508
  if (initGlobals() || authenticate())
528
509
  {
529
 
    disconnect();
 
510
    disconnect(0, true);
530
511
    return;
531
512
  }
532
513
 
533
514
  prepareForQueries();
534
515
 
535
 
  while (not client->haveError() && getKilled() != KILL_CONNECTION)
 
516
  while (! client->haveError() && killed != KILL_CONNECTION)
536
517
  {
537
 
    if (not executeStatement())
 
518
    if (! executeStatement())
538
519
      break;
539
520
  }
540
521
 
541
 
  disconnect();
 
522
  disconnect(0, true);
542
523
}
543
524
 
544
 
bool Session::schedule(Session::shared_ptr &arg)
 
525
bool Session::schedule()
545
526
{
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)
554
 
  {
555
 
    current_global_counters.max_used_connections= static_cast<uint64_t>(connection_count);
556
 
  }
557
 
 
558
 
  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());
 
527
  scheduler= plugin::Scheduler::getScheduler();
 
528
  assert(scheduler);
 
529
 
 
530
  connection_count.increment();
 
531
 
 
532
  if (connection_count > current_global_counters.max_used_connections)
 
533
  {
 
534
    current_global_counters.max_used_connections= connection_count;
 
535
  }
 
536
 
 
537
  thread_id= variables.pseudo_thread_id= global_thread_id++;
 
538
 
 
539
  LOCK_thread_count.lock();
 
540
  getSessionList().push_back(this);
 
541
  LOCK_thread_count.unlock();
 
542
 
 
543
  if (scheduler->addSession(this))
 
544
  {
 
545
    DRIZZLE_CONNECTION_START(thread_id);
571
546
    char error_message_buff[DRIZZLE_ERRMSG_SIZE];
572
547
 
573
 
    arg->setKilled(Session::KILL_CONNECTION);
 
548
    killed= Session::KILL_CONNECTION;
574
549
 
575
 
    arg->status_var.aborted_connects++;
 
550
    status_var.aborted_connects++;
576
551
 
577
552
    /* Can't use my_error() since store_globals has not been called. */
578
553
    /* TODO replace will better error message */
579
554
    snprintf(error_message_buff, sizeof(error_message_buff),
580
555
             ER(ER_CANT_CREATE_THREAD), 1);
581
 
    arg->client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
582
 
 
 
556
    client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
583
557
    return true;
584
558
  }
585
559
 
587
561
}
588
562
 
589
563
 
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
 
const char* Session::enter_cond(boost::condition_variable_any &cond, boost::mutex &mutex, const char* msg)
 
564
const char* Session::enter_cond(boost::condition_variable &cond, boost::mutex &mutex, const char* msg)
600
565
{
601
566
  const char* old_msg = get_proc_info();
602
567
  safe_mutex_assert_owner(mutex);
603
 
  mysys_var->current_mutex = &mutex;
604
 
  mysys_var->current_cond = &cond;
 
568
  mysys_var->current_mutex = mutex.native_handle();
 
569
  mysys_var->current_cond = cond.native_handle();
605
570
  this->set_proc_info(msg);
606
571
  return old_msg;
607
572
}
614
579
    locked (if that would not be the case, you'll get a deadlock if someone
615
580
    does a Session::awake() on you).
616
581
  */
617
 
  mysys_var->current_mutex->unlock();
618
 
  boost_unique_lock_t scopedLock(mysys_var->mutex);
 
582
  pthread_mutex_unlock(mysys_var->current_mutex);
 
583
  pthread_mutex_lock(&mysys_var->mutex);
619
584
  mysys_var->current_mutex = 0;
620
585
  mysys_var->current_cond = 0;
621
586
  this->set_proc_info(old_msg);
 
587
  pthread_mutex_unlock(&mysys_var->mutex);
622
588
}
623
589
 
624
590
bool Session::authenticate()
625
591
{
 
592
  lex_start(this);
626
593
  if (client->authenticate())
627
594
    return false;
628
595
 
631
598
  return true;
632
599
}
633
600
 
634
 
bool Session::checkUser(const std::string &passwd_str,
635
 
                        const std::string &in_db)
 
601
bool Session::checkUser(const char *passwd, uint32_t passwd_len, const char *in_db)
636
602
{
 
603
  const string passwd_str(passwd, passwd_len);
637
604
  bool is_authenticated=
638
 
    plugin::Authentication::isAuthenticated(*user(), passwd_str);
 
605
    plugin::Authentication::isAuthenticated(getSecurityContext(),
 
606
                                            passwd_str);
639
607
 
640
608
  if (is_authenticated != true)
641
609
  {
645
613
  }
646
614
 
647
615
  /* Change database if necessary */
648
 
  if (not in_db.empty())
 
616
  if (in_db && in_db[0])
649
617
  {
650
 
    identifier::Schema identifier(in_db);
651
 
    if (schema::change(*this, identifier))
 
618
    SchemaIdentifier identifier(in_db);
 
619
    if (mysql_change_db(this, identifier))
652
620
    {
653
 
      /* change_db() has pushed the error message. */
 
621
      /* mysql_change_db() has pushed the error message. */
654
622
      return false;
655
623
    }
656
624
  }
657
625
  my_ok();
658
 
  password= not passwd_str.empty();
 
626
  password= test(passwd_len);          // remember for error messages
659
627
 
660
628
  /* Ready to handle queries */
661
629
  return true;
677
645
  main_da.reset_diagnostics_area();
678
646
 
679
647
  if (client->readCommand(&l_packet, &packet_length) == false)
680
 
  {
681
 
    return false;
682
 
  }
683
 
 
684
 
  if (getKilled() == KILL_CONNECTION)
685
648
    return false;
686
649
 
687
650
  if (packet_length == 0)
688
651
    return true;
689
652
 
690
 
  l_command= static_cast<enum_server_command>(l_packet[0]);
 
653
  l_command= (enum enum_server_command) (unsigned char) l_packet[0];
691
654
 
692
655
  if (command >= COM_END)
693
656
    command= COM_END;                           // Wrong command
694
657
 
695
658
  assert(packet_length);
696
 
  return not dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
 
659
  return ! dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
697
660
}
698
661
 
699
662
bool Session::readAndStoreQuery(const char *in_packet, uint32_t in_packet_length)
705
668
    in_packet_length--;
706
669
  }
707
670
  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])))
 
671
  while (in_packet_length > 0 &&
 
672
         (pos[-1] == ';' || my_isspace(charset() ,pos[-1])))
709
673
  {
710
674
    pos--;
711
675
    in_packet_length--;
712
676
  }
713
677
 
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));
 
678
  query.assign(in_packet, in_packet + in_packet_length);
722
679
 
723
680
  return true;
724
681
}
743
700
       * (Which of course should never happen...)
744
701
       */
745
702
      server_status&= ~SERVER_STATUS_IN_TRANS;
746
 
      if (transaction_services.commitTransaction(*this, true))
 
703
      if (transaction_services.commitTransaction(this, true))
747
704
        result= false;
748
705
      options&= ~(OPTION_BEGIN);
749
706
      break;
760
717
    case ROLLBACK_AND_CHAIN:
761
718
    {
762
719
      server_status&= ~SERVER_STATUS_IN_TRANS;
763
 
      if (transaction_services.rollbackTransaction(*this, true))
 
720
      if (transaction_services.rollbackTransaction(this, true))
764
721
        result= false;
765
722
      options&= ~(OPTION_BEGIN);
766
723
      if (result == true && (completion == ROLLBACK_AND_CHAIN))
773
730
  }
774
731
 
775
732
  if (result == false)
776
 
  {
777
 
    my_error(static_cast<drizzled::error_t>(killed_errno()), MYF(0));
778
 
  }
 
733
    my_error(killed_errno(), MYF(0));
779
734
  else if ((result == true) && do_release)
780
 
  {
781
 
    setKilled(Session::KILL_CONNECTION);
782
 
  }
 
735
    killed= Session::KILL_CONNECTION;
783
736
 
784
737
  return result;
785
738
}
797
750
  if (options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
798
751
  {
799
752
    server_status&= ~SERVER_STATUS_IN_TRANS;
800
 
    if (transaction_services.commitTransaction(*this, true))
 
753
    if (transaction_services.commitTransaction(this, true))
801
754
      result= false;
802
755
  }
803
756
  options&= ~(OPTION_BEGIN);
808
761
{
809
762
  bool result= true;
810
763
 
811
 
  assert(! inTransaction());
812
 
 
813
 
  options|= OPTION_BEGIN;
814
 
  server_status|= SERVER_STATUS_IN_TRANS;
815
 
 
816
 
  if (plugin::TransactionalStorageEngine::notifyStartTransaction(this, opt))
 
764
  if (! endActiveTransaction())
817
765
  {
818
766
    result= false;
819
767
  }
 
768
  else
 
769
  {
 
770
    options|= OPTION_BEGIN;
 
771
    server_status|= SERVER_STATUS_IN_TRANS;
 
772
 
 
773
    if (plugin::TransactionalStorageEngine::notifyStartTransaction(this, opt))
 
774
    {
 
775
      result= false;
 
776
    }
 
777
  }
820
778
 
821
779
  return result;
822
780
}
838
796
    first_successful_insert_id_in_cur_stmt= 0;
839
797
    substitute_null_with_insert_id= true;
840
798
  }
841
 
 
842
799
  arg_of_last_insert_id_function= false;
843
 
 
844
800
  /* Free Items that were created during this execution */
845
801
  free_items();
846
 
 
847
 
  /* Reset _where. */
848
 
  _where= Session::DEFAULT_WHERE;
 
802
  /* Reset where. */
 
803
  where= Session::DEFAULT_WHERE;
849
804
 
850
805
  /* Reset the temporary shares we built */
851
 
  for_each(temporary_shares.begin(),
852
 
           temporary_shares.end(),
853
 
           DeletePtr());
 
806
  for (std::vector<TableShareInstance *>::iterator iter= temporary_shares.begin();
 
807
       iter != temporary_shares.end(); iter++)
 
808
  {
 
809
    delete *iter;
 
810
  }
854
811
  temporary_shares.clear();
855
812
}
856
813
 
876
833
                                     bool allocate_lex_string)
877
834
{
878
835
  if (allocate_lex_string)
879
 
    if (!(lex_str= (LEX_STRING *)getMemRoot()->allocate(sizeof(LEX_STRING))))
 
836
    if (!(lex_str= (LEX_STRING *)alloc(sizeof(LEX_STRING))))
880
837
      return 0;
881
838
  if (!(lex_str->str= mem_root->strmake_root(str, length)))
882
839
    return 0;
922
879
  return (result->send_fields(field_list));
923
880
}
924
881
 
925
 
void select_result::send_error(drizzled::error_t errcode, const char *err)
 
882
void select_result::send_error(uint32_t errcode, const char *err)
926
883
{
927
884
  my_message(errcode, err, MYF(0));
928
885
}
931
888
  Handling writing to file
932
889
************************************************************************/
933
890
 
934
 
void select_to_file::send_error(drizzled::error_t errcode,const char *err)
 
891
void select_to_file::send_error(uint32_t errcode,const char *err)
935
892
{
936
893
  my_message(errcode, err, MYF(0));
937
894
  if (file > 0)
938
895
  {
939
 
    (void) cache->end_io_cache();
 
896
    (void) end_io_cache(cache);
940
897
    (void) internal::my_close(file, MYF(0));
941
 
    (void) internal::my_delete(path.file_string().c_str(), MYF(0));             // Delete file on error
 
898
    (void) internal::my_delete(path, MYF(0));           // Delete file on error
942
899
    file= -1;
943
900
  }
944
901
}
946
903
 
947
904
bool select_to_file::send_eof()
948
905
{
949
 
  int error= test(cache->end_io_cache());
 
906
  int error= test(end_io_cache(cache));
950
907
  if (internal::my_close(file, MYF(MY_WME)))
951
908
    error= 1;
952
909
  if (!error)
968
925
  /* In case of error send_eof() may be not called: close the file here. */
969
926
  if (file >= 0)
970
927
  {
971
 
    (void) cache->end_io_cache();
 
928
    (void) end_io_cache(cache);
972
929
    (void) internal::my_close(file, MYF(0));
973
930
    file= -1;
974
931
  }
975
 
  path= "";
 
932
  path[0]= '\0';
976
933
  row_count= 0;
977
934
}
978
935
 
982
939
    cache(static_cast<internal::IO_CACHE *>(memory::sql_calloc(sizeof(internal::IO_CACHE)))),
983
940
    row_count(0L)
984
941
{
985
 
  path= "";
 
942
  path[0]=0;
986
943
}
987
944
 
988
945
select_to_file::~select_to_file()
1016
973
*/
1017
974
 
1018
975
 
1019
 
static int create_file(Session *session,
1020
 
                       fs::path &target_path,
1021
 
                       file_exchange *exchange,
1022
 
                       internal::IO_CACHE *cache)
 
976
static int create_file(Session *session, char *path, file_exchange *exchange, internal::IO_CACHE *cache)
1023
977
{
1024
 
  fs::path to_file(exchange->file_name);
1025
978
  int file;
1026
 
 
1027
 
  if (not to_file.has_root_directory())
 
979
  uint32_t option= MY_UNPACK_FILENAME | MY_RELATIVE_PATH;
 
980
 
 
981
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
 
982
  option|= MY_REPLACE_DIR;                      // Force use of db directory
 
983
#endif
 
984
 
 
985
  if (!internal::dirname_length(exchange->file_name))
1028
986
  {
1029
 
    target_path= fs::system_complete(getDataHomeCatalog());
1030
 
    util::string::const_shared_ptr schema(session->schema());
1031
 
    if (schema and not schema->empty())
1032
 
    {
1033
 
      int count_elements= 0;
1034
 
      for (fs::path::iterator iter= to_file.begin();
1035
 
           iter != to_file.end();
1036
 
           ++iter, ++count_elements)
1037
 
      { }
1038
 
 
1039
 
      if (count_elements == 1)
1040
 
      {
1041
 
        target_path /= *schema;
1042
 
      }
1043
 
    }
1044
 
    target_path /= to_file;
 
987
    strcpy(path, data_home_real);
 
988
    if (! session->db.empty())
 
989
      strncat(path, session->db.c_str(), FN_REFLEN-strlen(data_home_real)-1);
 
990
    (void) internal::fn_format(path, exchange->file_name, path, "", option);
1045
991
  }
1046
992
  else
1047
 
  {
1048
 
    target_path = exchange->file_name;
1049
 
  }
1050
 
 
1051
 
  if (not secure_file_priv.string().empty())
1052
 
  {
1053
 
    if (target_path.file_string().substr(0, secure_file_priv.file_string().size()) != secure_file_priv.file_string())
1054
 
    {
1055
 
      /* Write only allowed to dir or subdir specified by secure_file_priv */
1056
 
      my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
1057
 
      return -1;
1058
 
    }
1059
 
  }
1060
 
 
1061
 
  if (!access(target_path.file_string().c_str(), F_OK))
 
993
    (void) internal::fn_format(path, exchange->file_name, data_home_real, "", option);
 
994
 
 
995
  if (opt_secure_file_priv &&
 
996
      strncmp(opt_secure_file_priv, path, strlen(opt_secure_file_priv)))
 
997
  {
 
998
    /* Write only allowed to dir or subdir specified by secure_file_priv */
 
999
    my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
 
1000
    return -1;
 
1001
  }
 
1002
 
 
1003
  if (!access(path, F_OK))
1062
1004
  {
1063
1005
    my_error(ER_FILE_EXISTS_ERROR, MYF(0), exchange->file_name);
1064
1006
    return -1;
1065
1007
  }
1066
1008
  /* Create the file world readable */
1067
 
  if ((file= internal::my_create(target_path.file_string().c_str(), 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
 
1009
  if ((file= internal::my_create(path, 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
1068
1010
    return file;
1069
1011
  (void) fchmod(file, 0666);                    // Because of umask()
1070
 
  if (cache->init_io_cache(file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
 
1012
  if (init_io_cache(cache, file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1071
1013
  {
1072
1014
    internal::my_close(file, MYF(0));
1073
 
    internal::my_delete(target_path.file_string().c_str(), MYF(0));  // Delete file on error, it was just created
 
1015
    internal::my_delete(path, MYF(0));  // Delete file on error, it was just created
1074
1016
    return -1;
1075
1017
  }
1076
1018
  return file;
1084
1026
  bool string_results= false, non_string_results= false;
1085
1027
  unit= u;
1086
1028
  if ((uint32_t) strlen(exchange->file_name) + NAME_LEN >= FN_REFLEN)
1087
 
  {
1088
 
    path= exchange->file_name;
1089
 
  }
 
1029
    strncpy(path,exchange->file_name,FN_REFLEN-1);
1090
1030
 
1091
1031
  /* Check if there is any blobs in data */
1092
1032
  {
1093
 
    List<Item>::iterator li(list.begin());
 
1033
    List_iterator_fast<Item> li(list);
1094
1034
    Item *item;
1095
1035
    while ((item=li++))
1096
1036
    {
1097
1037
      if (item->max_length >= MAX_BLOB_WIDTH)
1098
1038
      {
1099
 
        blob_flag=1;
1100
 
        break;
 
1039
        blob_flag=1;
 
1040
        break;
1101
1041
      }
1102
 
 
1103
1042
      if (item->result_type() == STRING_RESULT)
1104
1043
        string_results= true;
1105
1044
      else
1150
1089
  if (unit->offset_limit_cnt)
1151
1090
  {                                             // using limit offset,count
1152
1091
    unit->offset_limit_cnt--;
1153
 
    return false;
 
1092
    return(0);
1154
1093
  }
1155
1094
  row_count++;
1156
1095
  Item *item;
1157
1096
  uint32_t used_length=0,items_left=items.elements;
1158
 
  List<Item>::iterator li(items.begin());
 
1097
  List_iterator_fast<Item> li(items);
1159
1098
 
1160
1099
  if (my_b_write(cache,(unsigned char*) exchange->line_start->ptr(),
1161
1100
                 exchange->line_start->length()))
1162
 
    return true;
1163
 
 
 
1101
    goto err;
1164
1102
  while ((item=li++))
1165
1103
  {
1166
1104
    Item_result result_type=item->result_type();
1171
1109
    {
1172
1110
      if (my_b_write(cache,(unsigned char*) exchange->enclosed->ptr(),
1173
1111
                     exchange->enclosed->length()))
1174
 
        return true;
 
1112
        goto err;
1175
1113
    }
1176
1114
    if (!res)
1177
1115
    {                                           // NULL
1182
1120
          null_buff[0]=escape_char;
1183
1121
          null_buff[1]='N';
1184
1122
          if (my_b_write(cache,(unsigned char*) null_buff,2))
1185
 
            return true;
 
1123
            goto err;
1186
1124
        }
1187
1125
        else if (my_b_write(cache,(unsigned char*) "NULL",4))
1188
 
          return true;
 
1126
          goto err;
1189
1127
      }
1190
1128
      else
1191
1129
      {
1195
1133
    else
1196
1134
    {
1197
1135
      if (fixed_row_size)
1198
 
        used_length= min(res->length(), static_cast<size_t>(item->max_length));
 
1136
        used_length= min(res->length(),item->max_length);
1199
1137
      else
1200
1138
        used_length= res->length();
1201
1139
 
1276
1214
            tmp_buff[1]= *pos ? *pos : '0';
1277
1215
            if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)) ||
1278
1216
                my_b_write(cache,(unsigned char*) tmp_buff,2))
1279
 
              return true;
 
1217
              goto err;
1280
1218
            start=pos+1;
1281
1219
          }
1282
1220
        }
1283
1221
        if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)))
1284
 
          return true;
 
1222
          goto err;
1285
1223
      }
1286
1224
      else if (my_b_write(cache,(unsigned char*) res->ptr(),used_length))
1287
 
        return true;
 
1225
        goto err;
1288
1226
    }
1289
1227
    if (fixed_row_size)
1290
1228
    {                                           // Fill with space
1300
1238
        for (; length > sizeof(space) ; length-=sizeof(space))
1301
1239
        {
1302
1240
          if (my_b_write(cache,(unsigned char*) space,sizeof(space)))
1303
 
            return true;
 
1241
            goto err;
1304
1242
        }
1305
1243
        if (my_b_write(cache,(unsigned char*) space,length))
1306
 
          return true;
 
1244
          goto err;
1307
1245
      }
1308
1246
    }
1309
1247
    if (res && enclosed)
1310
1248
    {
1311
1249
      if (my_b_write(cache, (unsigned char*) exchange->enclosed->ptr(),
1312
1250
                     exchange->enclosed->length()))
1313
 
        return true;
 
1251
        goto err;
1314
1252
    }
1315
1253
    if (--items_left)
1316
1254
    {
1317
1255
      if (my_b_write(cache, (unsigned char*) exchange->field_term->ptr(),
1318
1256
                     field_term_length))
1319
 
        return true;
 
1257
        goto err;
1320
1258
    }
1321
1259
  }
1322
1260
  if (my_b_write(cache,(unsigned char*) exchange->line_term->ptr(),
1323
1261
                 exchange->line_term->length()))
1324
 
  {
1325
 
    return true;
1326
 
  }
1327
 
 
1328
 
  return false;
 
1262
    goto err;
 
1263
  return(0);
 
1264
err:
 
1265
  return(1);
1329
1266
}
1330
1267
 
1331
1268
 
1344
1281
 
1345
1282
bool select_dump::send_data(List<Item> &items)
1346
1283
{
1347
 
  List<Item>::iterator li(items.begin());
 
1284
  List_iterator_fast<Item> li(items);
1348
1285
  char buff[MAX_FIELD_WIDTH];
1349
1286
  String tmp(buff,sizeof(buff),&my_charset_bin),*res;
1350
1287
  tmp.length(0);
1358
1295
  if (row_count++ > 1)
1359
1296
  {
1360
1297
    my_message(ER_TOO_MANY_ROWS, ER(ER_TOO_MANY_ROWS), MYF(0));
1361
 
    return 1;
 
1298
    goto err;
1362
1299
  }
1363
1300
  while ((item=li++))
1364
1301
  {
1366
1303
    if (!res)                                   // If NULL
1367
1304
    {
1368
1305
      if (my_b_write(cache,(unsigned char*) "",1))
1369
 
        return 1;
 
1306
        goto err;
1370
1307
    }
1371
1308
    else if (my_b_write(cache,(unsigned char*) res->ptr(),res->length()))
1372
1309
    {
1373
 
      my_error(ER_ERROR_ON_WRITE, MYF(0), path.file_string().c_str(), errno);
1374
 
      return 1;
 
1310
      my_error(ER_ERROR_ON_WRITE, MYF(0), path, errno);
 
1311
      goto err;
1375
1312
    }
1376
1313
  }
1377
1314
  return(0);
 
1315
err:
 
1316
  return(1);
1378
1317
}
1379
1318
 
1380
1319
 
1397
1336
    unit->offset_limit_cnt--;
1398
1337
    return(0);
1399
1338
  }
1400
 
  List<Item>::iterator li(items.begin());
 
1339
  List_iterator_fast<Item> li(items);
1401
1340
  Item *val_item;
1402
1341
  for (uint32_t i= 0; (val_item= li++); i++)
1403
1342
    it->store(i, val_item);
1415
1354
bool select_max_min_finder_subselect::send_data(List<Item> &items)
1416
1355
{
1417
1356
  Item_maxmin_subselect *it= (Item_maxmin_subselect *)item;
1418
 
  List<Item>::iterator li(items.begin());
 
1357
  List_iterator_fast<Item> li(items);
1419
1358
  Item *val_item= li++;
1420
1359
  it->register_value();
1421
1360
  if (it->assigned())
1432
1371
      switch (val_item->result_type())
1433
1372
      {
1434
1373
      case REAL_RESULT:
1435
 
        op= &select_max_min_finder_subselect::cmp_real;
1436
 
        break;
 
1374
        op= &select_max_min_finder_subselect::cmp_real;
 
1375
        break;
1437
1376
      case INT_RESULT:
1438
 
        op= &select_max_min_finder_subselect::cmp_int;
1439
 
        break;
 
1377
        op= &select_max_min_finder_subselect::cmp_int;
 
1378
        break;
1440
1379
      case STRING_RESULT:
1441
 
        op= &select_max_min_finder_subselect::cmp_str;
1442
 
        break;
 
1380
        op= &select_max_min_finder_subselect::cmp_str;
 
1381
        break;
1443
1382
      case DECIMAL_RESULT:
1444
1383
        op= &select_max_min_finder_subselect::cmp_decimal;
1445
1384
        break;
1446
1385
      case ROW_RESULT:
1447
1386
        // This case should never be choosen
1448
 
        assert(0);
1449
 
        op= 0;
 
1387
        assert(0);
 
1388
        op= 0;
1450
1389
      }
1451
1390
    }
1452
1391
    cache->store(val_item);
1485
1424
bool select_max_min_finder_subselect::cmp_decimal()
1486
1425
{
1487
1426
  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);
 
1427
  my_decimal cval, *cvalue= cache->val_decimal(&cval);
 
1428
  my_decimal mval, *mvalue= maxmin->val_decimal(&mval);
1490
1429
  if (fmax)
1491
1430
    return (cache->null_value && !maxmin->null_value) ||
1492
1431
      (!cache->null_value && !maxmin->null_value &&
1493
 
       class_decimal_cmp(cvalue, mvalue) > 0) ;
 
1432
       my_decimal_cmp(cvalue, mvalue) > 0) ;
1494
1433
  return (maxmin->null_value && !cache->null_value) ||
1495
1434
    (!cache->null_value && !maxmin->null_value &&
1496
 
     class_decimal_cmp(cvalue,mvalue) < 0);
 
1435
     my_decimal_cmp(cvalue,mvalue) < 0);
1497
1436
}
1498
1437
 
1499
1438
bool select_max_min_finder_subselect::cmp_str()
1535
1474
void Session::end_statement()
1536
1475
{
1537
1476
  /* Cleanup SQL processing state to reuse this statement in next query. */
1538
 
  lex->end();
1539
 
  query_cache_key= ""; // reset the cache key
1540
 
  resetResultsetMessage();
 
1477
  lex_end(lex);
1541
1478
}
1542
1479
 
1543
1480
bool Session::copy_db_to(char **p_db, size_t *p_db_length)
1544
1481
{
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
 
 
 
1482
  if (db.empty())
 
1483
  {
 
1484
    my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
 
1485
    return true;
 
1486
  }
 
1487
  *p_db= strmake(db.c_str(), db.length());
 
1488
  *p_db_length= db.length();
1561
1489
  return false;
1562
1490
}
1563
1491
 
1579
1507
  /* Fix for Intel compiler */
1580
1508
  if (copy_field)
1581
1509
  {
1582
 
    boost::checked_array_delete(copy_field);
1583
 
    save_copy_field= save_copy_field_end= copy_field= copy_field_end= 0;
 
1510
    delete [] copy_field;
 
1511
    save_copy_field= copy_field= 0;
1584
1512
  }
1585
1513
}
1586
1514
 
1587
1515
void Session::send_kill_message() const
1588
1516
{
1589
 
  drizzled::error_t err= static_cast<drizzled::error_t>(killed_errno());
1590
 
  if (err != EE_OK)
 
1517
  int err= killed_errno();
 
1518
  if (err)
1591
1519
    my_message(err, ER(err), MYF(0));
1592
1520
}
1593
1521
 
1597
1525
}
1598
1526
 
1599
1527
 
1600
 
void Session::set_db(const std::string &new_db)
 
1528
bool Session::set_db(const std::string &new_db)
1601
1529
{
1602
1530
  /* Do not reallocate memory if current chunk is big enough. */
1603
1531
  if (new_db.length())
1604
 
  {
1605
 
    _schema.reset(new std::string(new_db));
1606
 
  }
 
1532
    db= new_db;
1607
1533
  else
1608
 
  {
1609
 
    _schema.reset(new std::string(""));
1610
 
  }
1611
 
}
1612
 
 
 
1534
    db.clear();
 
1535
 
 
1536
  return false;
 
1537
}
 
1538
 
 
1539
 
 
1540
 
 
1541
 
 
1542
/**
 
1543
  Check the killed state of a user thread
 
1544
  @param session  user thread
 
1545
  @retval 0 the user thread is active
 
1546
  @retval 1 the user thread has been killed
 
1547
*/
 
1548
int session_killed(const Session *session)
 
1549
{
 
1550
  return(session->killed);
 
1551
}
 
1552
 
 
1553
 
 
1554
const struct charset_info_st *session_charset(Session *session)
 
1555
{
 
1556
  return(session->charset());
 
1557
}
1613
1558
 
1614
1559
/**
1615
1560
  Mark transaction to rollback and mark error as fatal to a sub-statement.
1617
1562
  @param  session   Thread handle
1618
1563
  @param  all   true <=> rollback main transaction.
1619
1564
*/
1620
 
void Session::markTransactionForRollback(bool all)
 
1565
void mark_transaction_to_rollback(Session *session, bool all)
1621
1566
{
1622
 
  is_fatal_sub_stmt_error= true;
1623
 
  transaction_rollback_request= all;
 
1567
  if (session)
 
1568
  {
 
1569
    session->is_fatal_sub_stmt_error= true;
 
1570
    session->transaction_rollback_request= all;
 
1571
  }
1624
1572
}
1625
1573
 
1626
 
void Session::disconnect(enum error_t errcode)
 
1574
void Session::disconnect(uint32_t errcode, bool should_lock)
1627
1575
{
1628
1576
  /* Allow any plugins to cleanup their session variables */
1629
1577
  plugin_sessionvar_cleanup(this);
1630
1578
 
1631
1579
  /* If necessary, log any aborted or unauthorized connections */
1632
 
  if (getKilled() || client->wasAborted())
 
1580
  if (killed || client->wasAborted())
1633
1581
  {
1634
1582
    status_var.aborted_threads++;
1635
1583
  }
1636
1584
 
1637
1585
  if (client->wasAborted())
1638
1586
  {
1639
 
    if (not getKilled() && variables.log_warnings > 1)
 
1587
    if (! killed && variables.log_warnings > 1)
1640
1588
    {
1641
 
      errmsg_printf(error::WARN, ER(ER_NEW_ABORTING_CONNECTION)
 
1589
      SecurityContext *sctx= &security_ctx;
 
1590
 
 
1591
      errmsg_printf(ERRMSG_LVL_WARN, ER(ER_NEW_ABORTING_CONNECTION)
1642
1592
                  , 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()
 
1593
                  , (db.empty() ? "unconnected" : db.c_str())
 
1594
                  , sctx->getUser().empty() == false ? sctx->getUser().c_str() : "unauthenticated"
 
1595
                  , sctx->getIp().c_str()
1646
1596
                  , (main_da.is_error() ? main_da.message() : ER(ER_UNKNOWN_ERROR)));
1647
1597
    }
1648
1598
  }
1649
1599
 
1650
 
  setKilled(Session::KILL_CONNECTION);
1651
 
 
 
1600
  /* Close out our connection to the client */
 
1601
  if (should_lock)
 
1602
    LOCK_thread_count.lock();
 
1603
  killed= Session::KILL_CONNECTION;
1652
1604
  if (client->isConnected())
1653
1605
  {
1654
 
    if (errcode != EE_OK)
 
1606
    if (errcode)
1655
1607
    {
1656
1608
      /*my_error(errcode, ER(errcode));*/
1657
1609
      client->sendError(errcode, ER(errcode));
1658
1610
    }
1659
1611
    client->close();
1660
1612
  }
 
1613
  if (should_lock)
 
1614
    (void) LOCK_thread_count.unlock();
1661
1615
}
1662
1616
 
1663
1617
void Session::reset_for_next_command()
1685
1639
  Close all temporary tables created by 'CREATE TEMPORARY TABLE' for thread
1686
1640
*/
1687
1641
 
1688
 
void Open_tables_state::close_temporary_tables()
 
1642
void Session::close_temporary_tables()
1689
1643
{
1690
1644
  Table *table;
1691
1645
  Table *tmp_next;
1705
1659
  unlink from session->temporary tables and close temporary table
1706
1660
*/
1707
1661
 
1708
 
void Open_tables_state::close_temporary_table(Table *table)
 
1662
void Session::close_temporary_table(Table *table)
1709
1663
{
1710
1664
  if (table->getPrev())
1711
1665
  {
1741
1695
  If this is needed, use close_temporary_table()
1742
1696
*/
1743
1697
 
1744
 
void Open_tables_state::nukeTable(Table *table)
 
1698
void Session::nukeTable(Table *table)
1745
1699
{
1746
1700
  plugin::StorageEngine *table_type= table->getShare()->db_type();
1747
1701
 
1748
1702
  table->free_io_cache();
1749
1703
  table->delete_table();
1750
1704
 
1751
 
  identifier::Table identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName(), table->getShare()->getPath());
 
1705
  TableIdentifier identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName(), table->getShare()->getPath());
1752
1706
  rm_temporary_table(table_type, identifier);
1753
1707
 
1754
 
  boost::checked_delete(table->getMutableShare());
 
1708
  delete table->getMutableShare();
1755
1709
 
1756
 
  boost::checked_delete(table);
 
1710
  /* This makes me sad, but we're allocating it via malloc */
 
1711
  delete table;
1757
1712
}
1758
1713
 
1759
1714
/** Clear most status variables. */
1766
1721
 
1767
1722
  flush_status_time= time((time_t*) 0);
1768
1723
  current_global_counters.max_used_connections= 1; /* We set it to one, because we know we exist */
1769
 
  current_global_counters.connections= 0;
1770
1724
}
1771
1725
 
1772
1726
user_var_entry *Session::getVariable(LEX_STRING &name, bool create_if_not_exists)
1773
1727
{
1774
 
  return getVariable(std::string(name.str, name.length), create_if_not_exists);
1775
 
}
1776
 
 
1777
 
user_var_entry *Session::getVariable(const std::string  &name, bool create_if_not_exists)
1778
 
{
1779
 
  if (cleanup_done)
1780
 
    return NULL;
1781
 
 
1782
 
  UserVars::iterator iter= user_vars.find(name);
1783
 
  if (iter != user_vars.end())
1784
 
    return (*iter).second;
1785
 
 
1786
 
  if (not create_if_not_exists)
1787
 
    return NULL;
1788
 
 
1789
1728
  user_var_entry *entry= NULL;
1790
 
  entry= new (nothrow) user_var_entry(name.c_str(), query_id);
1791
 
 
1792
 
  if (entry == NULL)
1793
 
    return NULL;
1794
 
 
1795
 
  std::pair<UserVars::iterator, bool> returnable= user_vars.insert(make_pair(name, entry));
1796
 
 
1797
 
  if (not returnable.second)
1798
 
  {
1799
 
    boost::checked_delete(entry);
 
1729
  UserVarsRange ppp= user_vars.equal_range(std::string(name.str, name.length));
 
1730
 
 
1731
  for (UserVars::iterator iter= ppp.first;
 
1732
         iter != ppp.second; ++iter)
 
1733
  {
 
1734
    entry= (*iter).second;
 
1735
  }
 
1736
 
 
1737
  if ((entry == NULL) && create_if_not_exists)
 
1738
  {
 
1739
    entry= new (nothrow) user_var_entry(name.str, query_id);
 
1740
 
 
1741
    if (entry == NULL)
 
1742
      return NULL;
 
1743
 
 
1744
    std::pair<UserVars::iterator, bool> returnable= user_vars.insert(make_pair(std::string(name.str, name.length), entry));
 
1745
 
 
1746
    if (not returnable.second)
 
1747
    {
 
1748
      delete entry;
 
1749
      return NULL;
 
1750
    }
1800
1751
  }
1801
1752
 
1802
1753
  return entry;
1803
1754
}
1804
1755
 
1805
 
void Session::setVariable(const std::string &name, const std::string &value)
1806
 
{
1807
 
  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
 
  }
1816
 
}
1817
 
 
1818
 
void Open_tables_state::mark_temp_tables_as_free_for_reuse()
 
1756
void Session::mark_temp_tables_as_free_for_reuse()
1819
1757
{
1820
1758
  for (Table *table= temporary_tables ; table ; table= table->getNext())
1821
1759
  {
1822
 
    if (table->query_id == getQueryId())
 
1760
    if (table->query_id == query_id)
1823
1761
    {
1824
1762
      table->query_id= 0;
1825
1763
      table->cursor->ha_reset();
1831
1769
{
1832
1770
  for (; table ; table= table->getNext())
1833
1771
  {
1834
 
    if (table->query_id == getQueryId())
 
1772
    if (table->query_id == query_id)
1835
1773
    {
1836
1774
      table->query_id= 0;
1837
1775
      table->cursor->ha_reset();
1850
1788
*/
1851
1789
void Session::close_thread_tables()
1852
1790
{
1853
 
  clearDerivedTables();
 
1791
  if (derived_tables)
 
1792
    derived_tables= NULL; // They should all be invalid by this point
1854
1793
 
1855
1794
  /*
1856
1795
    Mark all temporary tables used by this statement as free for reuse.
1867
1806
  {
1868
1807
    TransactionServices &transaction_services= TransactionServices::singleton();
1869
1808
    main_da.can_overwrite_status= true;
1870
 
    transaction_services.autocommitOrRollback(*this, is_error());
 
1809
    transaction_services.autocommitOrRollback(this, is_error());
1871
1810
    main_da.can_overwrite_status= false;
1872
1811
    transaction.stmt.reset();
1873
1812
  }
1883
1822
      handled either before writing a query log event (inside
1884
1823
      binlog_query()) or when preparing a pending event.
1885
1824
     */
1886
 
    unlockTables(lock);
 
1825
    mysql_unlock_tables(this, lock);
1887
1826
    lock= 0;
1888
1827
  }
1889
1828
  /*
1890
 
    Note that we need to hold table::Cache::singleton().mutex() while changing the
 
1829
    Note that we need to hold LOCK_open while changing the
1891
1830
    open_tables list. Another thread may work on it.
1892
 
    (See: table::Cache::singleton().removeTable(), wait_completed_table())
 
1831
    (See: remove_table_from_cache(), mysql_wait_completed_table())
1893
1832
    Closing a MERGE child before the parent would be fatal if the
1894
1833
    other thread tries to abort the MERGE lock in between.
1895
1834
  */
1923
1862
 
1924
1863
    if (not lock_tables(tables, counter, &need_reopen))
1925
1864
      break;
1926
 
 
1927
1865
    if (not need_reopen)
1928
1866
      return true;
1929
 
 
1930
1867
    close_tables_for_reopen(&tables);
1931
1868
  }
1932
 
 
1933
 
  if ((handle_derived(lex, &derived_prepare) || (handle_derived(lex, &derived_filling))))
1934
 
    return true;
1935
 
 
 
1869
  if ((mysql_handle_derived(lex, &mysql_derived_prepare) ||
 
1870
       (fill_derived_tables() &&
 
1871
        mysql_handle_derived(lex, &mysql_derived_filling))))
 
1872
    return true;
 
1873
 
 
1874
  return false;
 
1875
}
 
1876
 
 
1877
bool Session::openTables(TableList *tables, uint32_t flags)
 
1878
{
 
1879
  uint32_t counter;
 
1880
  bool ret= fill_derived_tables();
 
1881
  assert(ret == false);
 
1882
  if (open_tables_from_list(&tables, &counter, flags) ||
 
1883
      mysql_handle_derived(lex, &mysql_derived_prepare))
 
1884
  {
 
1885
    return true;
 
1886
  }
1936
1887
  return false;
1937
1888
}
1938
1889
 
1942
1893
  might be an issue (lame engines).
1943
1894
*/
1944
1895
 
1945
 
bool Open_tables_state::rm_temporary_table(const identifier::Table &identifier, bool best_effort)
 
1896
bool Session::rm_temporary_table(TableIdentifier &identifier, bool best_effort)
1946
1897
{
1947
 
  if (not plugin::StorageEngine::dropTable(*static_cast<Session *>(this), identifier))
 
1898
  if (plugin::StorageEngine::dropTable(*this, identifier))
1948
1899
  {
1949
1900
    if (not best_effort)
1950
1901
    {
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);
 
1902
      errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
 
1903
                    identifier.getSQLPath().c_str(), errno);
1955
1904
    }
1956
1905
 
1957
1906
    return true;
1960
1909
  return false;
1961
1910
}
1962
1911
 
1963
 
bool Open_tables_state::rm_temporary_table(plugin::StorageEngine *base, const identifier::Table &identifier)
 
1912
bool Session::rm_temporary_table(plugin::StorageEngine *base, TableIdentifier &identifier)
1964
1913
{
1965
 
  drizzled::error_t error;
1966
1914
  assert(base);
1967
1915
 
1968
 
  if (not plugin::StorageEngine::dropTable(*static_cast<Session *>(this), *base, identifier, error))
 
1916
  if (plugin::StorageEngine::dropTable(*this, *base, identifier))
1969
1917
  {
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);
 
1918
    errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
 
1919
                  identifier.getSQLPath().c_str(), errno);
1974
1920
 
1975
1921
    return true;
1976
1922
  }
1982
1928
  @note this will be removed, I am looking through Hudson to see if it is finding
1983
1929
  any tables that are missed during cleanup.
1984
1930
*/
1985
 
void Open_tables_state::dumpTemporaryTableNames(const char *foo)
 
1931
void Session::dumpTemporaryTableNames(const char *foo)
1986
1932
{
1987
1933
  Table *table;
1988
1934
 
1994
1940
  {
1995
1941
    bool have_proto= false;
1996
1942
 
1997
 
    message::Table *proto= table->getShare()->getTableMessage();
1998
 
    if (table->getShare()->getTableMessage())
 
1943
    message::Table *proto= table->getShare()->getTableProto();
 
1944
    if (table->getShare()->getTableProto())
1999
1945
      have_proto= true;
2000
1946
 
2001
1947
    const char *answer= have_proto ? "true" : "false";
2006
1952
      cerr << "\t\t Proto " << proto->schema() << " " << proto->name() << "\n";
2007
1953
    }
2008
1954
    else
2009
 
    {
2010
1955
      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 */
 
1956
  }
 
1957
}
 
1958
 
 
1959
bool Session::storeTableMessage(const TableIdentifier &identifier, message::Table &table_message)
 
1960
{
 
1961
  table_message_cache.insert(make_pair(identifier.getPath(), table_message));
 
1962
 
 
1963
  return true;
 
1964
}
 
1965
 
 
1966
bool Session::removeTableMessage(const TableIdentifier &identifier)
 
1967
{
 
1968
  TableMessageCache::iterator iter;
 
1969
 
 
1970
  iter= table_message_cache.find(identifier.getPath());
 
1971
 
 
1972
  if (iter == table_message_cache.end())
 
1973
    return false;
 
1974
 
 
1975
  table_message_cache.erase(iter);
 
1976
 
 
1977
  return true;
 
1978
}
 
1979
 
 
1980
bool Session::getTableMessage(const TableIdentifier &identifier, message::Table &table_message)
 
1981
{
 
1982
  TableMessageCache::iterator iter;
 
1983
 
 
1984
  iter= table_message_cache.find(identifier.getPath());
 
1985
 
 
1986
  if (iter == table_message_cache.end())
 
1987
    return false;
 
1988
 
 
1989
  table_message.CopyFrom(((*iter).second));
 
1990
 
 
1991
  return true;
 
1992
}
 
1993
 
 
1994
bool Session::doesTableMessageExist(const TableIdentifier &identifier)
 
1995
{
 
1996
  TableMessageCache::iterator iter;
 
1997
 
 
1998
  iter= table_message_cache.find(identifier.getPath());
 
1999
 
 
2000
  if (iter == table_message_cache.end())
 
2001
  {
 
2002
    return false;
 
2003
  }
 
2004
 
 
2005
  return true;
 
2006
}
 
2007
 
 
2008
bool Session::renameTableMessage(const TableIdentifier &from, const TableIdentifier &to)
 
2009
{
 
2010
  TableMessageCache::iterator iter;
 
2011
 
 
2012
  table_message_cache[to.getPath()]= table_message_cache[from.getPath()];
 
2013
 
 
2014
  iter= table_message_cache.find(to.getPath());
 
2015
 
 
2016
  if (iter == table_message_cache.end())
 
2017
  {
 
2018
    return false;
 
2019
  }
 
2020
 
 
2021
  (*iter).second.set_schema(to.getSchemaName());
 
2022
  (*iter).second.set_name(to.getTableName());
 
2023
 
 
2024
  return true;
 
2025
}
 
2026
 
 
2027
TableShareInstance *Session::getTemporaryShare(TableIdentifier::Type type_arg)
 
2028
{
 
2029
  temporary_shares.push_back(new TableShareInstance(type_arg)); // This will not go into the tableshare cache, so no key is used.
 
2030
 
 
2031
  TableShareInstance *tmp_share= temporary_shares.back();
 
2032
 
 
2033
  assert(tmp_share);
 
2034
 
 
2035
  return tmp_share;
 
2036
}
2081
2037
 
2082
2038
} /* namespace drizzled */