~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/session.cc

move POW() and POWER() function into math_functions plugin

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
  dbug_sentry=Session_SENTRY_MAGIC;
214
215
  cleanup_done= abort_on_warning= no_warnings_for_error= false;  
215
216
 
216
217
  /* query_cache init */
219
220
 
220
221
  /* Variables with default values */
221
222
  proc_info="login";
 
223
  where= Session::DEFAULT_WHERE;
 
224
  command= COM_CONNECT;
222
225
 
223
226
  plugin_sessionvar_init(this);
224
227
  /*
228
231
  */
229
232
  variables.pseudo_thread_id= thread_id;
230
233
  server_status= SERVER_STATUS_AUTOCOMMIT;
 
234
  options= session_startup_options;
231
235
 
232
236
  if (variables.max_join_size == HA_POS_ERROR)
233
237
    options |= OPTION_BIG_SELECTS;
237
241
  open_options=ha_open_options;
238
242
  update_lock_default= TL_WRITE;
239
243
  session_tx_isolation= (enum_tx_isolation) variables.tx_isolation;
240
 
  warn_list.clear();
 
244
  warn_list.empty();
241
245
  memset(warn_count, 0, sizeof(warn_count));
 
246
  total_warn_count= 0;
242
247
  memset(&status_var, 0, sizeof(status_var));
243
248
 
244
249
  /* Initialize sub structures */
274
279
  m_internal_handler= handler;
275
280
}
276
281
 
277
 
bool Session::handle_error(drizzled::error_t sql_errno, const char *message,
278
 
                           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)
279
284
{
280
285
  if (m_internal_handler)
281
286
  {
296
301
    return;
297
302
 
298
303
  setAbort(true);
299
 
  boost_unique_lock_t scopedLock(mysys_var->mutex);
 
304
  pthread_mutex_lock(&mysys_var->mutex);
300
305
  if (mysys_var->current_cond)
301
306
  {
302
 
    mysys_var->current_mutex->lock();
303
 
    mysys_var->current_cond->notify_all();
304
 
    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);
305
310
  }
 
311
  pthread_mutex_unlock(&mysys_var->mutex);
306
312
}
307
313
 
308
314
void Session::pop_internal_handler()
311
317
  m_internal_handler= NULL;
312
318
}
313
319
 
314
 
void Session::get_xid(DrizzleXid *xid)
 
320
void Session::get_xid(DRIZZLE_XID *xid)
315
321
{
316
 
  *xid = *(DrizzleXid *) &transaction.xid_state.xid;
 
322
  *xid = *(DRIZZLE_XID *) &transaction.xid_state.xid;
317
323
}
318
324
 
319
325
/* Do operations that may take a long time */
322
328
{
323
329
  assert(cleanup_done == false);
324
330
 
325
 
  setKilled(KILL_CONNECTION);
 
331
  killed= KILL_CONNECTION;
326
332
#ifdef ENABLE_WHEN_BINLOG_WILL_BE_ABLE_TO_PREPARE
327
333
  if (transaction.xid_state.xa_state == XA_PREPARED)
328
334
  {
331
337
#endif
332
338
  {
333
339
    TransactionServices &transaction_services= TransactionServices::singleton();
334
 
    transaction_services.rollbackTransaction(*this, true);
 
340
    transaction_services.rollbackTransaction(this, true);
335
341
    xid_cache_delete(&transaction.xid_state);
336
342
  }
337
343
 
340
346
       iter++)
341
347
  {
342
348
    user_var_entry *entry= (*iter).second;
343
 
    boost::checked_delete(entry);
 
349
    delete entry;
344
350
  }
345
351
  user_vars.clear();
346
352
 
348
354
  close_temporary_tables();
349
355
 
350
356
  if (global_read_lock)
351
 
  {
352
 
    unlockGlobalReadLock();
353
 
  }
 
357
    unlock_global_read_lock(this);
354
358
 
355
359
  cleanup_done= true;
356
360
}
359
363
{
360
364
  this->checkSentry();
361
365
 
362
 
  if (client and client->isConnected())
 
366
  if (client->isConnected())
363
367
  {
364
 
    assert(security_ctx);
365
368
    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();
 
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);
374
374
  }
375
375
 
376
376
  /* Close connection */
377
 
  if (client)
378
 
  {
379
 
    client->close();
380
 
    boost::checked_delete(client);
381
 
    client= NULL;
382
 
  }
 
377
  client->close();
 
378
  delete client;
383
379
 
384
380
  if (cleanup_done == false)
385
381
    cleanup();
392
388
  dbug_sentry= Session_SENTRY_GONE;
393
389
 
394
390
  main_mem_root.free_root(MYF(0));
395
 
  currentMemRoot().release();
396
 
  currentSession().release();
 
391
  pthread_setspecific(THR_Session,  0);
397
392
 
398
393
  plugin::Logging::postEndDo(this);
399
394
  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
 
 
 
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
{
413
402
  this->checkSentry();
414
 
 
415
 
  setKilled(state_to_set);
416
 
  scheduler->killSession(this);
417
 
 
 
403
  safe_mutex_assert_owner(&LOCK_delete);
 
404
 
 
405
  killed= state_to_set;
418
406
  if (state_to_set != Session::KILL_QUERY)
419
407
  {
 
408
    scheduler->killSession(this);
420
409
    DRIZZLE_CONNECTION_DONE(thread_id);
421
410
  }
422
 
 
423
411
  if (mysys_var)
424
412
  {
425
 
    boost_unique_lock_t scopedLock(mysys_var->mutex);
 
413
    pthread_mutex_lock(&mysys_var->mutex);
426
414
    /*
427
 
      "
428
415
      This broadcast could be up in the air if the victim thread
429
416
      exits the cond in the time between read and broadcast, but that is
430
417
      ok since all we want to do is to make the victim thread get out
445
432
    */
446
433
    if (mysys_var->current_cond && mysys_var->current_mutex)
447
434
    {
448
 
      mysys_var->current_mutex->lock();
449
 
      mysys_var->current_cond->notify_all();
450
 
      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);
451
438
    }
 
439
    pthread_mutex_unlock(&mysys_var->mutex);
452
440
  }
453
441
}
454
442
 
464
452
  */
465
453
  assert(thread_stack);
466
454
 
467
 
  currentSession().release();
468
 
  currentSession().reset(this);
469
 
 
470
 
  currentMemRoot().release();
471
 
  currentMemRoot().reset(&mem_root);
 
455
  if (pthread_setspecific(THR_Session,  this) ||
 
456
      pthread_setspecific(THR_Mem_root, &mem_root))
 
457
    return true;
472
458
 
473
459
  mysys_var=my_thread_var;
474
460
 
477
463
    This allows us to move Session to different threads if needed.
478
464
  */
479
465
  mysys_var->id= thread_id;
 
466
  real_id= pthread_self();                      // For debugging
480
467
 
481
468
  /*
482
469
    We have to call thr_lock_info_init() again here as Session may have been
507
494
                                variables.query_prealloc_size);
508
495
  transaction.xid_state.xid.null();
509
496
  transaction.xid_state.in_session=1;
510
 
  if (use_usage)
511
 
    resetUsage();
512
497
}
513
498
 
514
499
bool Session::initGlobals()
515
500
{
516
501
  if (storeGlobals())
517
502
  {
518
 
    disconnect(ER_OUT_OF_RESOURCES);
 
503
    disconnect(ER_OUT_OF_RESOURCES, true);
519
504
    status_var.aborted_connects++;
520
505
    return true;
521
506
  }
526
511
{
527
512
  if (initGlobals() || authenticate())
528
513
  {
529
 
    disconnect();
 
514
    disconnect(0, true);
530
515
    return;
531
516
  }
532
517
 
533
518
  prepareForQueries();
534
519
 
535
 
  while (not client->haveError() && getKilled() != KILL_CONNECTION)
 
520
  while (! client->haveError() && killed != KILL_CONNECTION)
536
521
  {
537
 
    if (not executeStatement())
 
522
    if (! executeStatement())
538
523
      break;
539
524
  }
540
525
 
541
 
  disconnect();
 
526
  disconnect(0, true);
542
527
}
543
528
 
544
 
bool Session::schedule(Session::shared_ptr &arg)
 
529
bool Session::schedule()
545
530
{
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)
 
531
  scheduler= plugin::Scheduler::getScheduler();
 
532
  assert(scheduler);
 
533
 
 
534
  connection_count.increment();
 
535
 
 
536
  if (connection_count > current_global_counters.max_used_connections)
554
537
  {
555
 
    current_global_counters.max_used_connections= static_cast<uint64_t>(connection_count);
 
538
    current_global_counters.max_used_connections= connection_count;
556
539
  }
557
540
 
558
541
  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());
 
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);
571
551
    char error_message_buff[DRIZZLE_ERRMSG_SIZE];
572
552
 
573
 
    arg->setKilled(Session::KILL_CONNECTION);
 
553
    killed= Session::KILL_CONNECTION;
574
554
 
575
 
    arg->status_var.aborted_connects++;
 
555
    status_var.aborted_connects++;
576
556
 
577
557
    /* Can't use my_error() since store_globals has not been called. */
578
558
    /* TODO replace will better error message */
579
559
    snprintf(error_message_buff, sizeof(error_message_buff),
580
560
             ER(ER_CANT_CREATE_THREAD), 1);
581
 
    arg->client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
582
 
 
 
561
    client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
583
562
    return true;
584
563
  }
585
564
 
587
566
}
588
567
 
589
568
 
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)
 
569
const char* Session::enter_cond(boost::condition_variable &cond, boost::mutex &mutex, const char* msg)
600
570
{
601
571
  const char* old_msg = get_proc_info();
602
572
  safe_mutex_assert_owner(mutex);
603
 
  mysys_var->current_mutex = &mutex;
604
 
  mysys_var->current_cond = &cond;
 
573
  mysys_var->current_mutex = mutex.native_handle();
 
574
  mysys_var->current_cond = cond.native_handle();
605
575
  this->set_proc_info(msg);
606
576
  return old_msg;
607
577
}
614
584
    locked (if that would not be the case, you'll get a deadlock if someone
615
585
    does a Session::awake() on you).
616
586
  */
617
 
  mysys_var->current_mutex->unlock();
618
 
  boost_unique_lock_t scopedLock(mysys_var->mutex);
 
587
  pthread_mutex_unlock(mysys_var->current_mutex);
 
588
  pthread_mutex_lock(&mysys_var->mutex);
619
589
  mysys_var->current_mutex = 0;
620
590
  mysys_var->current_cond = 0;
621
591
  this->set_proc_info(old_msg);
 
592
  pthread_mutex_unlock(&mysys_var->mutex);
622
593
}
623
594
 
624
595
bool Session::authenticate()
625
596
{
 
597
  lex_start(this);
626
598
  if (client->authenticate())
627
599
    return false;
628
600
 
631
603
  return true;
632
604
}
633
605
 
634
 
bool Session::checkUser(const std::string &passwd_str,
635
 
                        const std::string &in_db)
 
606
bool Session::checkUser(const char *passwd, uint32_t passwd_len, const char *in_db)
636
607
{
 
608
  const string passwd_str(passwd, passwd_len);
637
609
  bool is_authenticated=
638
 
    plugin::Authentication::isAuthenticated(*user(), passwd_str);
 
610
    plugin::Authentication::isAuthenticated(getSecurityContext(),
 
611
                                            passwd_str);
639
612
 
640
613
  if (is_authenticated != true)
641
614
  {
645
618
  }
646
619
 
647
620
  /* Change database if necessary */
648
 
  if (not in_db.empty())
 
621
  if (in_db && in_db[0])
649
622
  {
650
 
    identifier::Schema identifier(in_db);
651
 
    if (schema::change(*this, identifier))
 
623
    SchemaIdentifier identifier(in_db);
 
624
    if (mysql_change_db(this, identifier))
652
625
    {
653
 
      /* change_db() has pushed the error message. */
 
626
      /* mysql_change_db() has pushed the error message. */
654
627
      return false;
655
628
    }
656
629
  }
657
630
  my_ok();
658
 
  password= not passwd_str.empty();
 
631
  password= test(passwd_len);          // remember for error messages
659
632
 
660
633
  /* Ready to handle queries */
661
634
  return true;
677
650
  main_da.reset_diagnostics_area();
678
651
 
679
652
  if (client->readCommand(&l_packet, &packet_length) == false)
680
 
  {
681
653
    return false;
682
 
  }
683
654
 
684
 
  if (getKilled() == KILL_CONNECTION)
 
655
  if (killed == KILL_CONNECTION)
685
656
    return false;
686
657
 
687
658
  if (packet_length == 0)
688
659
    return true;
689
660
 
690
 
  l_command= static_cast<enum_server_command>(l_packet[0]);
 
661
  l_command= (enum enum_server_command) (unsigned char) l_packet[0];
691
662
 
692
663
  if (command >= COM_END)
693
664
    command= COM_END;                           // Wrong command
694
665
 
695
666
  assert(packet_length);
696
 
  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));
697
668
}
698
669
 
699
670
bool Session::readAndStoreQuery(const char *in_packet, uint32_t in_packet_length)
705
676
    in_packet_length--;
706
677
  }
707
678
  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])))
 
679
  while (in_packet_length > 0 &&
 
680
         (pos[-1] == ';' || my_isspace(charset() ,pos[-1])))
709
681
  {
710
682
    pos--;
711
683
    in_packet_length--;
712
684
  }
713
685
 
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));
 
686
  query.assign(in_packet, in_packet + in_packet_length);
722
687
 
723
688
  return true;
724
689
}
743
708
       * (Which of course should never happen...)
744
709
       */
745
710
      server_status&= ~SERVER_STATUS_IN_TRANS;
746
 
      if (transaction_services.commitTransaction(*this, true))
 
711
      if (transaction_services.commitTransaction(this, true))
747
712
        result= false;
748
713
      options&= ~(OPTION_BEGIN);
749
714
      break;
760
725
    case ROLLBACK_AND_CHAIN:
761
726
    {
762
727
      server_status&= ~SERVER_STATUS_IN_TRANS;
763
 
      if (transaction_services.rollbackTransaction(*this, true))
 
728
      if (transaction_services.rollbackTransaction(this, true))
764
729
        result= false;
765
730
      options&= ~(OPTION_BEGIN);
766
731
      if (result == true && (completion == ROLLBACK_AND_CHAIN))
773
738
  }
774
739
 
775
740
  if (result == false)
776
 
  {
777
 
    my_error(static_cast<drizzled::error_t>(killed_errno()), MYF(0));
778
 
  }
 
741
    my_error(killed_errno(), MYF(0));
779
742
  else if ((result == true) && do_release)
780
 
  {
781
 
    setKilled(Session::KILL_CONNECTION);
782
 
  }
 
743
    killed= Session::KILL_CONNECTION;
783
744
 
784
745
  return result;
785
746
}
797
758
  if (options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
798
759
  {
799
760
    server_status&= ~SERVER_STATUS_IN_TRANS;
800
 
    if (transaction_services.commitTransaction(*this, true))
 
761
    if (transaction_services.commitTransaction(this, true))
801
762
      result= false;
802
763
  }
803
764
  options&= ~(OPTION_BEGIN);
808
769
{
809
770
  bool result= true;
810
771
 
811
 
  assert(! inTransaction());
812
 
 
813
 
  options|= OPTION_BEGIN;
814
 
  server_status|= SERVER_STATUS_IN_TRANS;
815
 
 
816
 
  if (plugin::TransactionalStorageEngine::notifyStartTransaction(this, opt))
 
772
  if (! endActiveTransaction())
817
773
  {
818
774
    result= false;
819
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
  }
820
786
 
821
787
  return result;
822
788
}
838
804
    first_successful_insert_id_in_cur_stmt= 0;
839
805
    substitute_null_with_insert_id= true;
840
806
  }
841
 
 
842
807
  arg_of_last_insert_id_function= false;
843
 
 
844
808
  /* Free Items that were created during this execution */
845
809
  free_items();
846
 
 
847
 
  /* Reset _where. */
848
 
  _where= Session::DEFAULT_WHERE;
 
810
  /* Reset where. */
 
811
  where= Session::DEFAULT_WHERE;
849
812
 
850
813
  /* Reset the temporary shares we built */
851
 
  for_each(temporary_shares.begin(),
852
 
           temporary_shares.end(),
853
 
           DeletePtr());
 
814
  for (std::vector<TableShareInstance *>::iterator iter= temporary_shares.begin();
 
815
       iter != temporary_shares.end(); iter++)
 
816
  {
 
817
    delete *iter;
 
818
  }
854
819
  temporary_shares.clear();
855
820
}
856
821
 
876
841
                                     bool allocate_lex_string)
877
842
{
878
843
  if (allocate_lex_string)
879
 
    if (!(lex_str= (LEX_STRING *)getMemRoot()->allocate(sizeof(LEX_STRING))))
 
844
    if (!(lex_str= (LEX_STRING *)alloc(sizeof(LEX_STRING))))
880
845
      return 0;
881
846
  if (!(lex_str->str= mem_root->strmake_root(str, length)))
882
847
    return 0;
922
887
  return (result->send_fields(field_list));
923
888
}
924
889
 
925
 
void select_result::send_error(drizzled::error_t errcode, const char *err)
 
890
void select_result::send_error(uint32_t errcode, const char *err)
926
891
{
927
892
  my_message(errcode, err, MYF(0));
928
893
}
931
896
  Handling writing to file
932
897
************************************************************************/
933
898
 
934
 
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)
935
900
{
936
901
  my_message(errcode, err, MYF(0));
937
902
  if (file > 0)
938
903
  {
939
 
    (void) cache->end_io_cache();
 
904
    (void) end_io_cache(cache);
940
905
    (void) internal::my_close(file, MYF(0));
941
 
    (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
942
907
    file= -1;
943
908
  }
944
909
}
946
911
 
947
912
bool select_to_file::send_eof()
948
913
{
949
 
  int error= test(cache->end_io_cache());
 
914
  int error= test(end_io_cache(cache));
950
915
  if (internal::my_close(file, MYF(MY_WME)))
951
916
    error= 1;
952
917
  if (!error)
968
933
  /* In case of error send_eof() may be not called: close the file here. */
969
934
  if (file >= 0)
970
935
  {
971
 
    (void) cache->end_io_cache();
 
936
    (void) end_io_cache(cache);
972
937
    (void) internal::my_close(file, MYF(0));
973
938
    file= -1;
974
939
  }
975
 
  path= "";
 
940
  path[0]= '\0';
976
941
  row_count= 0;
977
942
}
978
943
 
982
947
    cache(static_cast<internal::IO_CACHE *>(memory::sql_calloc(sizeof(internal::IO_CACHE)))),
983
948
    row_count(0L)
984
949
{
985
 
  path= "";
 
950
  path[0]=0;
986
951
}
987
952
 
988
953
select_to_file::~select_to_file()
1016
981
*/
1017
982
 
1018
983
 
1019
 
static int create_file(Session *session,
1020
 
                       fs::path &target_path,
1021
 
                       file_exchange *exchange,
1022
 
                       internal::IO_CACHE *cache)
 
984
static int create_file(Session *session, char *path, file_exchange *exchange, internal::IO_CACHE *cache)
1023
985
{
1024
 
  fs::path to_file(exchange->file_name);
1025
986
  int file;
1026
 
 
1027
 
  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))
1028
994
  {
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;
 
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);
1045
999
  }
1046
1000
  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))
 
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))
1062
1012
  {
1063
1013
    my_error(ER_FILE_EXISTS_ERROR, MYF(0), exchange->file_name);
1064
1014
    return -1;
1065
1015
  }
1066
1016
  /* 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)
 
1017
  if ((file= internal::my_create(path, 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
1068
1018
    return file;
1069
1019
  (void) fchmod(file, 0666);                    // Because of umask()
1070
 
  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)))
1071
1021
  {
1072
1022
    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
 
1023
    internal::my_delete(path, MYF(0));  // Delete file on error, it was just created
1074
1024
    return -1;
1075
1025
  }
1076
1026
  return file;
1084
1034
  bool string_results= false, non_string_results= false;
1085
1035
  unit= u;
1086
1036
  if ((uint32_t) strlen(exchange->file_name) + NAME_LEN >= FN_REFLEN)
1087
 
  {
1088
 
    path= exchange->file_name;
1089
 
  }
 
1037
    strncpy(path,exchange->file_name,FN_REFLEN-1);
1090
1038
 
1091
1039
  /* Check if there is any blobs in data */
1092
1040
  {
1093
 
    List<Item>::iterator li(list.begin());
 
1041
    List_iterator_fast<Item> li(list);
1094
1042
    Item *item;
1095
1043
    while ((item=li++))
1096
1044
    {
1097
1045
      if (item->max_length >= MAX_BLOB_WIDTH)
1098
1046
      {
1099
 
        blob_flag=1;
1100
 
        break;
 
1047
        blob_flag=1;
 
1048
        break;
1101
1049
      }
1102
 
 
1103
1050
      if (item->result_type() == STRING_RESULT)
1104
1051
        string_results= true;
1105
1052
      else
1150
1097
  if (unit->offset_limit_cnt)
1151
1098
  {                                             // using limit offset,count
1152
1099
    unit->offset_limit_cnt--;
1153
 
    return false;
 
1100
    return(0);
1154
1101
  }
1155
1102
  row_count++;
1156
1103
  Item *item;
1157
1104
  uint32_t used_length=0,items_left=items.elements;
1158
 
  List<Item>::iterator li(items.begin());
 
1105
  List_iterator_fast<Item> li(items);
1159
1106
 
1160
1107
  if (my_b_write(cache,(unsigned char*) exchange->line_start->ptr(),
1161
1108
                 exchange->line_start->length()))
1162
 
    return true;
1163
 
 
 
1109
    goto err;
1164
1110
  while ((item=li++))
1165
1111
  {
1166
1112
    Item_result result_type=item->result_type();
1171
1117
    {
1172
1118
      if (my_b_write(cache,(unsigned char*) exchange->enclosed->ptr(),
1173
1119
                     exchange->enclosed->length()))
1174
 
        return true;
 
1120
        goto err;
1175
1121
    }
1176
1122
    if (!res)
1177
1123
    {                                           // NULL
1182
1128
          null_buff[0]=escape_char;
1183
1129
          null_buff[1]='N';
1184
1130
          if (my_b_write(cache,(unsigned char*) null_buff,2))
1185
 
            return true;
 
1131
            goto err;
1186
1132
        }
1187
1133
        else if (my_b_write(cache,(unsigned char*) "NULL",4))
1188
 
          return true;
 
1134
          goto err;
1189
1135
      }
1190
1136
      else
1191
1137
      {
1195
1141
    else
1196
1142
    {
1197
1143
      if (fixed_row_size)
1198
 
        used_length= min(res->length(), static_cast<size_t>(item->max_length));
 
1144
        used_length= min(res->length(),item->max_length);
1199
1145
      else
1200
1146
        used_length= res->length();
1201
1147
 
1276
1222
            tmp_buff[1]= *pos ? *pos : '0';
1277
1223
            if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)) ||
1278
1224
                my_b_write(cache,(unsigned char*) tmp_buff,2))
1279
 
              return true;
 
1225
              goto err;
1280
1226
            start=pos+1;
1281
1227
          }
1282
1228
        }
1283
1229
        if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)))
1284
 
          return true;
 
1230
          goto err;
1285
1231
      }
1286
1232
      else if (my_b_write(cache,(unsigned char*) res->ptr(),used_length))
1287
 
        return true;
 
1233
        goto err;
1288
1234
    }
1289
1235
    if (fixed_row_size)
1290
1236
    {                                           // Fill with space
1300
1246
        for (; length > sizeof(space) ; length-=sizeof(space))
1301
1247
        {
1302
1248
          if (my_b_write(cache,(unsigned char*) space,sizeof(space)))
1303
 
            return true;
 
1249
            goto err;
1304
1250
        }
1305
1251
        if (my_b_write(cache,(unsigned char*) space,length))
1306
 
          return true;
 
1252
          goto err;
1307
1253
      }
1308
1254
    }
1309
1255
    if (res && enclosed)
1310
1256
    {
1311
1257
      if (my_b_write(cache, (unsigned char*) exchange->enclosed->ptr(),
1312
1258
                     exchange->enclosed->length()))
1313
 
        return true;
 
1259
        goto err;
1314
1260
    }
1315
1261
    if (--items_left)
1316
1262
    {
1317
1263
      if (my_b_write(cache, (unsigned char*) exchange->field_term->ptr(),
1318
1264
                     field_term_length))
1319
 
        return true;
 
1265
        goto err;
1320
1266
    }
1321
1267
  }
1322
1268
  if (my_b_write(cache,(unsigned char*) exchange->line_term->ptr(),
1323
1269
                 exchange->line_term->length()))
1324
 
  {
1325
 
    return true;
1326
 
  }
1327
 
 
1328
 
  return false;
 
1270
    goto err;
 
1271
  return(0);
 
1272
err:
 
1273
  return(1);
1329
1274
}
1330
1275
 
1331
1276
 
1344
1289
 
1345
1290
bool select_dump::send_data(List<Item> &items)
1346
1291
{
1347
 
  List<Item>::iterator li(items.begin());
 
1292
  List_iterator_fast<Item> li(items);
1348
1293
  char buff[MAX_FIELD_WIDTH];
1349
1294
  String tmp(buff,sizeof(buff),&my_charset_bin),*res;
1350
1295
  tmp.length(0);
1358
1303
  if (row_count++ > 1)
1359
1304
  {
1360
1305
    my_message(ER_TOO_MANY_ROWS, ER(ER_TOO_MANY_ROWS), MYF(0));
1361
 
    return 1;
 
1306
    goto err;
1362
1307
  }
1363
1308
  while ((item=li++))
1364
1309
  {
1366
1311
    if (!res)                                   // If NULL
1367
1312
    {
1368
1313
      if (my_b_write(cache,(unsigned char*) "",1))
1369
 
        return 1;
 
1314
        goto err;
1370
1315
    }
1371
1316
    else if (my_b_write(cache,(unsigned char*) res->ptr(),res->length()))
1372
1317
    {
1373
 
      my_error(ER_ERROR_ON_WRITE, MYF(0), path.file_string().c_str(), errno);
1374
 
      return 1;
 
1318
      my_error(ER_ERROR_ON_WRITE, MYF(0), path, errno);
 
1319
      goto err;
1375
1320
    }
1376
1321
  }
1377
1322
  return(0);
 
1323
err:
 
1324
  return(1);
1378
1325
}
1379
1326
 
1380
1327
 
1397
1344
    unit->offset_limit_cnt--;
1398
1345
    return(0);
1399
1346
  }
1400
 
  List<Item>::iterator li(items.begin());
 
1347
  List_iterator_fast<Item> li(items);
1401
1348
  Item *val_item;
1402
1349
  for (uint32_t i= 0; (val_item= li++); i++)
1403
1350
    it->store(i, val_item);
1415
1362
bool select_max_min_finder_subselect::send_data(List<Item> &items)
1416
1363
{
1417
1364
  Item_maxmin_subselect *it= (Item_maxmin_subselect *)item;
1418
 
  List<Item>::iterator li(items.begin());
 
1365
  List_iterator_fast<Item> li(items);
1419
1366
  Item *val_item= li++;
1420
1367
  it->register_value();
1421
1368
  if (it->assigned())
1432
1379
      switch (val_item->result_type())
1433
1380
      {
1434
1381
      case REAL_RESULT:
1435
 
        op= &select_max_min_finder_subselect::cmp_real;
1436
 
        break;
 
1382
        op= &select_max_min_finder_subselect::cmp_real;
 
1383
        break;
1437
1384
      case INT_RESULT:
1438
 
        op= &select_max_min_finder_subselect::cmp_int;
1439
 
        break;
 
1385
        op= &select_max_min_finder_subselect::cmp_int;
 
1386
        break;
1440
1387
      case STRING_RESULT:
1441
 
        op= &select_max_min_finder_subselect::cmp_str;
1442
 
        break;
 
1388
        op= &select_max_min_finder_subselect::cmp_str;
 
1389
        break;
1443
1390
      case DECIMAL_RESULT:
1444
1391
        op= &select_max_min_finder_subselect::cmp_decimal;
1445
1392
        break;
1446
1393
      case ROW_RESULT:
1447
1394
        // This case should never be choosen
1448
 
        assert(0);
1449
 
        op= 0;
 
1395
        assert(0);
 
1396
        op= 0;
1450
1397
      }
1451
1398
    }
1452
1399
    cache->store(val_item);
1485
1432
bool select_max_min_finder_subselect::cmp_decimal()
1486
1433
{
1487
1434
  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);
 
1435
  my_decimal cval, *cvalue= cache->val_decimal(&cval);
 
1436
  my_decimal mval, *mvalue= maxmin->val_decimal(&mval);
1490
1437
  if (fmax)
1491
1438
    return (cache->null_value && !maxmin->null_value) ||
1492
1439
      (!cache->null_value && !maxmin->null_value &&
1493
 
       class_decimal_cmp(cvalue, mvalue) > 0) ;
 
1440
       my_decimal_cmp(cvalue, mvalue) > 0) ;
1494
1441
  return (maxmin->null_value && !cache->null_value) ||
1495
1442
    (!cache->null_value && !maxmin->null_value &&
1496
 
     class_decimal_cmp(cvalue,mvalue) < 0);
 
1443
     my_decimal_cmp(cvalue,mvalue) < 0);
1497
1444
}
1498
1445
 
1499
1446
bool select_max_min_finder_subselect::cmp_str()
1535
1482
void Session::end_statement()
1536
1483
{
1537
1484
  /* Cleanup SQL processing state to reuse this statement in next query. */
1538
 
  lex->end();
 
1485
  lex_end(lex);
1539
1486
  query_cache_key= ""; // reset the cache key
1540
1487
  resetResultsetMessage();
1541
1488
}
1542
1489
 
1543
1490
bool Session::copy_db_to(char **p_db, size_t *p_db_length)
1544
1491
{
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
 
 
 
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();
1561
1499
  return false;
1562
1500
}
1563
1501
 
1579
1517
  /* Fix for Intel compiler */
1580
1518
  if (copy_field)
1581
1519
  {
1582
 
    boost::checked_array_delete(copy_field);
1583
 
    save_copy_field= save_copy_field_end= copy_field= copy_field_end= 0;
 
1520
    delete [] copy_field;
 
1521
    save_copy_field= copy_field= 0;
1584
1522
  }
1585
1523
}
1586
1524
 
1587
1525
void Session::send_kill_message() const
1588
1526
{
1589
 
  drizzled::error_t err= static_cast<drizzled::error_t>(killed_errno());
1590
 
  if (err != EE_OK)
 
1527
  int err= killed_errno();
 
1528
  if (err)
1591
1529
    my_message(err, ER(err), MYF(0));
1592
1530
}
1593
1531
 
1597
1535
}
1598
1536
 
1599
1537
 
1600
 
void Session::set_db(const std::string &new_db)
 
1538
bool Session::set_db(const std::string &new_db)
1601
1539
{
1602
1540
  /* Do not reallocate memory if current chunk is big enough. */
1603
1541
  if (new_db.length())
1604
 
  {
1605
 
    _schema.reset(new std::string(new_db));
1606
 
  }
 
1542
    db= new_db;
1607
1543
  else
1608
 
  {
1609
 
    _schema.reset(new std::string(""));
1610
 
  }
1611
 
}
1612
 
 
 
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
}
1613
1568
 
1614
1569
/**
1615
1570
  Mark transaction to rollback and mark error as fatal to a sub-statement.
1617
1572
  @param  session   Thread handle
1618
1573
  @param  all   true <=> rollback main transaction.
1619
1574
*/
1620
 
void Session::markTransactionForRollback(bool all)
 
1575
void mark_transaction_to_rollback(Session *session, bool all)
1621
1576
{
1622
 
  is_fatal_sub_stmt_error= true;
1623
 
  transaction_rollback_request= all;
 
1577
  if (session)
 
1578
  {
 
1579
    session->is_fatal_sub_stmt_error= true;
 
1580
    session->transaction_rollback_request= all;
 
1581
  }
1624
1582
}
1625
1583
 
1626
 
void Session::disconnect(enum error_t errcode)
 
1584
void Session::disconnect(uint32_t errcode, bool should_lock)
1627
1585
{
1628
1586
  /* Allow any plugins to cleanup their session variables */
1629
1587
  plugin_sessionvar_cleanup(this);
1630
1588
 
1631
1589
  /* If necessary, log any aborted or unauthorized connections */
1632
 
  if (getKilled() || client->wasAborted())
 
1590
  if (killed || client->wasAborted())
1633
1591
  {
1634
1592
    status_var.aborted_threads++;
1635
1593
  }
1636
1594
 
1637
1595
  if (client->wasAborted())
1638
1596
  {
1639
 
    if (not getKilled() && variables.log_warnings > 1)
 
1597
    if (! killed && variables.log_warnings > 1)
1640
1598
    {
1641
 
      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)
1642
1602
                  , 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()
 
1603
                  , (db.empty() ? "unconnected" : db.c_str())
 
1604
                  , sctx->getUser().empty() == false ? sctx->getUser().c_str() : "unauthenticated"
 
1605
                  , sctx->getIp().c_str()
1646
1606
                  , (main_da.is_error() ? main_da.message() : ER(ER_UNKNOWN_ERROR)));
1647
1607
    }
1648
1608
  }
1649
1609
 
1650
 
  setKilled(Session::KILL_CONNECTION);
1651
 
 
 
1610
  /* Close out our connection to the client */
 
1611
  if (should_lock)
 
1612
    LOCK_thread_count.lock();
 
1613
  killed= Session::KILL_CONNECTION;
1652
1614
  if (client->isConnected())
1653
1615
  {
1654
 
    if (errcode != EE_OK)
 
1616
    if (errcode)
1655
1617
    {
1656
1618
      /*my_error(errcode, ER(errcode));*/
1657
1619
      client->sendError(errcode, ER(errcode));
1658
1620
    }
1659
1621
    client->close();
1660
1622
  }
 
1623
  if (should_lock)
 
1624
    (void) LOCK_thread_count.unlock();
1661
1625
}
1662
1626
 
1663
1627
void Session::reset_for_next_command()
1685
1649
  Close all temporary tables created by 'CREATE TEMPORARY TABLE' for thread
1686
1650
*/
1687
1651
 
1688
 
void Open_tables_state::close_temporary_tables()
 
1652
void Session::close_temporary_tables()
1689
1653
{
1690
1654
  Table *table;
1691
1655
  Table *tmp_next;
1705
1669
  unlink from session->temporary tables and close temporary table
1706
1670
*/
1707
1671
 
1708
 
void Open_tables_state::close_temporary_table(Table *table)
 
1672
void Session::close_temporary_table(Table *table)
1709
1673
{
1710
1674
  if (table->getPrev())
1711
1675
  {
1741
1705
  If this is needed, use close_temporary_table()
1742
1706
*/
1743
1707
 
1744
 
void Open_tables_state::nukeTable(Table *table)
 
1708
void Session::nukeTable(Table *table)
1745
1709
{
1746
1710
  plugin::StorageEngine *table_type= table->getShare()->db_type();
1747
1711
 
1748
1712
  table->free_io_cache();
1749
1713
  table->delete_table();
1750
1714
 
1751
 
  identifier::Table identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName(), table->getShare()->getPath());
 
1715
  TableIdentifier identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName(), table->getShare()->getPath());
1752
1716
  rm_temporary_table(table_type, identifier);
1753
1717
 
1754
 
  boost::checked_delete(table->getMutableShare());
 
1718
  delete table->getMutableShare();
1755
1719
 
1756
 
  boost::checked_delete(table);
 
1720
  /* This makes me sad, but we're allocating it via malloc */
 
1721
  delete table;
1757
1722
}
1758
1723
 
1759
1724
/** Clear most status variables. */
1771
1736
 
1772
1737
user_var_entry *Session::getVariable(LEX_STRING &name, bool create_if_not_exists)
1773
1738
{
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
1739
  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);
 
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
    }
1800
1762
  }
1801
1763
 
1802
1764
  return entry;
1803
1765
}
1804
1766
 
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()
 
1767
void Session::mark_temp_tables_as_free_for_reuse()
1819
1768
{
1820
1769
  for (Table *table= temporary_tables ; table ; table= table->getNext())
1821
1770
  {
1822
 
    if (table->query_id == getQueryId())
 
1771
    if (table->query_id == query_id)
1823
1772
    {
1824
1773
      table->query_id= 0;
1825
1774
      table->cursor->ha_reset();
1831
1780
{
1832
1781
  for (; table ; table= table->getNext())
1833
1782
  {
1834
 
    if (table->query_id == getQueryId())
 
1783
    if (table->query_id == query_id)
1835
1784
    {
1836
1785
      table->query_id= 0;
1837
1786
      table->cursor->ha_reset();
1850
1799
*/
1851
1800
void Session::close_thread_tables()
1852
1801
{
1853
 
  clearDerivedTables();
 
1802
  if (derived_tables)
 
1803
    derived_tables= NULL; // They should all be invalid by this point
1854
1804
 
1855
1805
  /*
1856
1806
    Mark all temporary tables used by this statement as free for reuse.
1867
1817
  {
1868
1818
    TransactionServices &transaction_services= TransactionServices::singleton();
1869
1819
    main_da.can_overwrite_status= true;
1870
 
    transaction_services.autocommitOrRollback(*this, is_error());
 
1820
    transaction_services.autocommitOrRollback(this, is_error());
1871
1821
    main_da.can_overwrite_status= false;
1872
1822
    transaction.stmt.reset();
1873
1823
  }
1883
1833
      handled either before writing a query log event (inside
1884
1834
      binlog_query()) or when preparing a pending event.
1885
1835
     */
1886
 
    unlockTables(lock);
 
1836
    mysql_unlock_tables(this, lock);
1887
1837
    lock= 0;
1888
1838
  }
1889
1839
  /*
1890
 
    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
1891
1841
    open_tables list. Another thread may work on it.
1892
 
    (See: table::Cache::singleton().removeTable(), wait_completed_table())
 
1842
    (See: remove_table_from_cache(), mysql_wait_completed_table())
1893
1843
    Closing a MERGE child before the parent would be fatal if the
1894
1844
    other thread tries to abort the MERGE lock in between.
1895
1845
  */
1923
1873
 
1924
1874
    if (not lock_tables(tables, counter, &need_reopen))
1925
1875
      break;
1926
 
 
1927
1876
    if (not need_reopen)
1928
1877
      return true;
1929
 
 
1930
1878
    close_tables_for_reopen(&tables);
1931
1879
  }
1932
 
 
1933
 
  if ((handle_derived(lex, &derived_prepare) || (handle_derived(lex, &derived_filling))))
1934
 
    return true;
1935
 
 
 
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
  }
1936
1898
  return false;
1937
1899
}
1938
1900
 
1942
1904
  might be an issue (lame engines).
1943
1905
*/
1944
1906
 
1945
 
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)
1946
1908
{
1947
 
  if (not plugin::StorageEngine::dropTable(*static_cast<Session *>(this), identifier))
 
1909
  if (plugin::StorageEngine::dropTable(*this, identifier))
1948
1910
  {
1949
1911
    if (not best_effort)
1950
1912
    {
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);
 
1913
      errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
 
1914
                    identifier.getSQLPath().c_str(), errno);
1955
1915
    }
1956
1916
 
1957
1917
    return true;
1960
1920
  return false;
1961
1921
}
1962
1922
 
1963
 
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)
1964
1924
{
1965
 
  drizzled::error_t error;
1966
1925
  assert(base);
1967
1926
 
1968
 
  if (not plugin::StorageEngine::dropTable(*static_cast<Session *>(this), *base, identifier, error))
 
1927
  if (plugin::StorageEngine::dropTable(*this, *base, identifier))
1969
1928
  {
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);
 
1929
    errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
 
1930
                  identifier.getSQLPath().c_str(), errno);
1974
1931
 
1975
1932
    return true;
1976
1933
  }
1982
1939
  @note this will be removed, I am looking through Hudson to see if it is finding
1983
1940
  any tables that are missed during cleanup.
1984
1941
*/
1985
 
void Open_tables_state::dumpTemporaryTableNames(const char *foo)
 
1942
void Session::dumpTemporaryTableNames(const char *foo)
1986
1943
{
1987
1944
  Table *table;
1988
1945
 
1994
1951
  {
1995
1952
    bool have_proto= false;
1996
1953
 
1997
 
    message::Table *proto= table->getShare()->getTableMessage();
1998
 
    if (table->getShare()->getTableMessage())
 
1954
    message::Table *proto= table->getShare()->getTableProto();
 
1955
    if (table->getShare()->getTableProto())
1999
1956
      have_proto= true;
2000
1957
 
2001
1958
    const char *answer= have_proto ? "true" : "false";
2006
1963
      cerr << "\t\t Proto " << proto->schema() << " " << proto->name() << "\n";
2007
1964
    }
2008
1965
    else
2009
 
    {
2010
1966
      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 */
 
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
}
2081
2048
 
2082
2049
} /* namespace drizzled */