~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/session.cc

Added pandora check for berkeley db.

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
 * @file Implementation of the Session class and API
22
22
 */
23
23
 
24
 
#include "config.h"
25
 
#include "drizzled/session.h"
26
 
#include "drizzled/session/cache.h"
 
24
#include <drizzled/server_includes.h>
 
25
#include <drizzled/session.h>
27
26
#include <sys/stat.h>
28
 
#include "drizzled/error.h"
29
 
#include "drizzled/gettext.h"
30
 
#include "drizzled/query_id.h"
31
 
#include "drizzled/data_home.h"
32
 
#include "drizzled/sql_base.h"
33
 
#include "drizzled/lock.h"
34
 
#include "drizzled/item/cache.h"
35
 
#include "drizzled/item/float.h"
36
 
#include "drizzled/item/return_int.h"
37
 
#include "drizzled/item/empty_string.h"
38
 
#include "drizzled/show.h"
39
 
#include "drizzled/plugin/client.h"
 
27
#include <mysys/mysys_err.h>
 
28
#include <drizzled/error.h>
 
29
#include <drizzled/gettext.h>
 
30
#include <drizzled/query_id.h>
 
31
#include <drizzled/data_home.h>
 
32
#include <drizzled/sql_base.h>
 
33
#include <drizzled/lock.h>
 
34
#include <drizzled/item/cache.h>
 
35
#include <drizzled/item/float.h>
 
36
#include <drizzled/item/return_int.h>
 
37
#include <drizzled/item/empty_string.h>
 
38
#include <drizzled/show.h>
 
39
#include <drizzled/plugin/client.h>
40
40
#include "drizzled/plugin/scheduler.h"
41
41
#include "drizzled/plugin/authentication.h"
42
 
#include "drizzled/plugin/logging.h"
43
 
#include "drizzled/plugin/transactional_storage_engine.h"
44
 
#include "drizzled/plugin/query_rewrite.h"
45
42
#include "drizzled/probes.h"
46
43
#include "drizzled/table_proto.h"
47
 
#include "drizzled/db.h"
48
 
#include "drizzled/pthread_globals.h"
49
 
#include "drizzled/transaction_services.h"
50
 
#include "drizzled/drizzled.h"
51
 
 
52
 
#include "drizzled/table/instance.h"
53
 
 
54
 
#include "plugin/myisam/myisam.h"
55
 
#include "drizzled/internal/iocache.h"
56
 
#include "drizzled/internal/thread_var.h"
57
 
#include "drizzled/plugin/event_observer.h"
58
 
 
59
 
#include "drizzled/util/functors.h"
60
 
 
61
 
#include "drizzled/display.h"
62
 
 
63
 
#include <fcntl.h>
 
44
 
64
45
#include <algorithm>
65
 
#include <climits>
66
 
#include <boost/filesystem.hpp>
67
 
 
68
 
#include "drizzled/util/backtrace.h"
69
46
 
70
47
using namespace std;
 
48
using namespace drizzled;
71
49
 
72
 
namespace fs=boost::filesystem;
73
 
namespace drizzled
 
50
extern "C"
74
51
{
 
52
  unsigned char *get_var_key(user_var_entry *entry, size_t *length, bool );
 
53
  void free_user_var(user_var_entry *entry);
 
54
}
75
55
 
76
56
/*
77
57
  The following is used to initialise Table_ident with a internal
81
61
char empty_c_string[1]= {0};    /* used for not defined db */
82
62
 
83
63
const char * const Session::DEFAULT_WHERE= "field list";
 
64
extern pthread_key_t THR_Session;
 
65
extern pthread_key_t THR_Mem_root;
 
66
extern uint32_t max_used_connections;
 
67
extern drizzled::atomic<uint32_t> connection_count;
 
68
 
 
69
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
 
70
/* Used templates */
 
71
template class List<Key>;
 
72
template class List_iterator<Key>;
 
73
template class List<Key_part_spec>;
 
74
template class List_iterator<Key_part_spec>;
 
75
template class List<AlterDrop>;
 
76
template class List_iterator<AlterDrop>;
 
77
template class List<AlterColumn>;
 
78
template class List_iterator<AlterColumn>;
 
79
#endif
 
80
 
 
81
/****************************************************************************
 
82
** User variables
 
83
****************************************************************************/
 
84
unsigned char *get_var_key(user_var_entry *entry, size_t *length, bool )
 
85
{
 
86
  *length= entry->name.length;
 
87
  return (unsigned char*) entry->name.str;
 
88
}
 
89
 
 
90
void free_user_var(user_var_entry *entry)
 
91
{
 
92
  delete entry;
 
93
}
84
94
 
85
95
bool Key_part_spec::operator==(const Key_part_spec& other) const
86
96
{
87
97
  return length == other.length &&
88
98
         field_name.length == other.field_name.length &&
89
 
    !my_strcasecmp(system_charset_info, field_name.str, other.field_name.str);
 
99
         !strcmp(field_name.str, other.field_name.str);
90
100
}
91
101
 
92
 
Open_tables_state::Open_tables_state(uint64_t version_arg) :
93
 
  version(version_arg)
 
102
Open_tables_state::Open_tables_state(ulong version_arg)
 
103
  :version(version_arg), backups_available(false)
94
104
{
95
 
  open_tables= temporary_tables= derived_tables= NULL;
96
 
  extra_lock= lock= NULL;
 
105
  reset_open_tables_state();
97
106
}
98
107
 
99
108
/*
100
109
  The following functions form part of the C plugin API
101
110
*/
102
 
int mysql_tmpfile(const char *prefix)
 
111
extern "C" int mysql_tmpfile(const char *prefix)
103
112
{
104
113
  char filename[FN_REFLEN];
105
 
  int fd = internal::create_temp_file(filename, drizzle_tmpdir.c_str(), prefix, MYF(MY_WME));
 
114
  File fd = create_temp_file(filename, drizzle_tmpdir, prefix, MYF(MY_WME));
106
115
  if (fd >= 0) {
107
116
    unlink(filename);
108
117
  }
110
119
  return fd;
111
120
}
112
121
 
 
122
extern "C"
113
123
int session_tablespace_op(const Session *session)
114
124
{
115
125
  return test(session->tablespace_op);
123
133
 
124
134
   @see Session::set_proc_info
125
135
 */
126
 
void set_session_proc_info(Session *session, const char *info)
 
136
extern "C" void
 
137
set_session_proc_info(Session *session, const char *info)
127
138
{
128
139
  session->set_proc_info(info);
129
140
}
130
141
 
 
142
extern "C"
131
143
const char *get_session_proc_info(Session *session)
132
144
{
133
145
  return session->get_proc_info();
134
146
}
135
147
 
136
 
void **Session::getEngineData(const plugin::MonitoredInTransaction *monitored)
137
 
{
138
 
  return static_cast<void **>(&ha_data[monitored->getId()].ha_ptr);
139
 
}
140
 
 
141
 
ResourceContext *Session::getResourceContext(const plugin::MonitoredInTransaction *monitored,
142
 
                                             size_t index)
143
 
{
144
 
  return &ha_data[monitored->getId()].resource_context[index];
145
 
}
146
 
 
 
148
extern "C"
 
149
void **session_ha_data(const Session *session, const plugin::StorageEngine *engine)
 
150
{
 
151
  return (void **) &session->ha_data[engine->slot].ha_ptr;
 
152
}
 
153
 
 
154
extern "C"
147
155
int64_t session_test_options(const Session *session, int64_t test_options)
148
156
{
149
157
  return session->options & test_options;
150
158
}
151
159
 
 
160
extern "C"
152
161
int session_sql_command(const Session *session)
153
162
{
154
163
  return (int) session->lex->sql_command;
155
164
}
156
165
 
157
 
enum_tx_isolation session_tx_isolation(const Session *session)
158
 
{
159
 
  return (enum_tx_isolation)session->variables.tx_isolation;
160
 
}
161
 
 
162
 
Session::Session(plugin::Client *client_arg) :
 
166
extern "C"
 
167
int session_tx_isolation(const Session *session)
 
168
{
 
169
  return (int) session->variables.tx_isolation;
 
170
}
 
171
 
 
172
extern "C"
 
173
void session_inc_row_count(Session *session)
 
174
{
 
175
  session->row_count++;
 
176
}
 
177
 
 
178
Session::Session(plugin::Client *client_arg)
 
179
  :
163
180
  Open_tables_state(refresh_version),
164
181
  mem_root(&main_mem_root),
165
 
  xa_id(0),
166
182
  lex(&main_lex),
167
 
  query(new std::string),
168
 
  _schema(new std::string("")),
169
 
  catalog("LOCAL"),
 
183
  db(NULL),
170
184
  client(client_arg),
171
185
  scheduler(NULL),
172
186
  scheduler_arg(NULL),
173
187
  lock_id(&main_lock_id),
174
188
  user_time(0),
175
 
  ha_data(plugin::num_trx_monitored_objects),
176
 
  concurrent_execute_allowed(true),
177
189
  arg_of_last_insert_id_function(false),
178
190
  first_successful_insert_id_in_prev_stmt(0),
179
191
  first_successful_insert_id_in_cur_stmt(0),
180
192
  limit_found_rows(0),
181
 
  _global_read_lock(NONE),
182
 
  _killed(NOT_KILLED),
 
193
  global_read_lock(0),
183
194
  some_tables_deleted(false),
184
195
  no_errors(false),
185
196
  password(false),
191
202
  m_lip(NULL),
192
203
  cached_table(0),
193
204
  transaction_message(NULL),
194
 
  statement_message(NULL),
195
 
  session_event_observers(NULL),
196
 
  use_usage(false)
 
205
  statement_message(NULL)
197
206
{
 
207
  memset(process_list_info, 0, PROCESS_LIST_WIDTH);
198
208
  client->setSession(this);
199
209
 
200
210
  /*
202
212
    the destructor works OK in case of an error. The main_mem_root
203
213
    will be re-initialized in init_for_queries().
204
214
  */
205
 
  memory::init_sql_alloc(&main_mem_root, memory::ROOT_MIN_BLOCK_SIZE, 0);
 
215
  init_sql_alloc(&main_mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
206
216
  thread_stack= NULL;
207
 
  count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
 
217
  count_cuted_fields= CHECK_FIELD_IGNORE;
 
218
  killed= NOT_KILLED;
208
219
  col_access= 0;
209
220
  tmp_table= 0;
210
221
  used_tables= 0;
220
231
  thread_id= 0;
221
232
  file_id = 0;
222
233
  query_id= 0;
223
 
  warn_query_id= 0;
 
234
  query= NULL;
 
235
  query_length= 0;
 
236
  warn_id= 0;
 
237
  memset(ha_data, 0, sizeof(ha_data));
 
238
  replication_data= 0;
224
239
  mysys_var= 0;
225
 
  scoreboard_index= -1;
226
240
  dbug_sentry=Session_SENTRY_MAGIC;
227
 
  cleanup_done= abort_on_warning= no_warnings_for_error= false;  
228
 
 
229
 
  /* query_cache init */
230
 
  query_cache_key= "";
231
 
  resultset= NULL;
 
241
  cleanup_done= abort_on_warning= no_warnings_for_error= false;
 
242
  transaction.on= 1;
 
243
  pthread_mutex_init(&LOCK_delete, MY_MUTEX_INIT_FAST);
232
244
 
233
245
  /* Variables with default values */
234
246
  proc_info="login";
250
262
  else
251
263
    options &= ~OPTION_BIG_SELECTS;
252
264
 
 
265
  transaction.all.modified_non_trans_table= transaction.stmt.modified_non_trans_table= false;
253
266
  open_options=ha_open_options;
254
267
  update_lock_default= TL_WRITE;
255
268
  session_tx_isolation= (enum_tx_isolation) variables.tx_isolation;
259
272
  memset(&status_var, 0, sizeof(status_var));
260
273
 
261
274
  /* Initialize sub structures */
262
 
  memory::init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
 
275
  init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
 
276
  hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
 
277
            (hash_get_key) get_var_key,
 
278
            (hash_free_key) free_user_var, 0);
263
279
 
264
280
  substitute_null_with_insert_id = false;
265
 
  lock_info.init(); /* safety: will be reset after start */
 
281
  thr_lock_info_init(&lock_info); /* safety: will be reset after start */
266
282
  thr_lock_owner_init(&main_lock_id, &lock_info);
267
283
 
268
284
  m_internal_handler= NULL;
269
 
  
270
 
  plugin::EventObserver::registerSessionEvents(*this); 
271
285
}
272
286
 
273
287
void Session::free_items()
274
288
{
275
289
  Item *next;
276
 
  /* This works because items are allocated with memory::sql_alloc() */
 
290
  /* This works because items are allocated with sql_alloc() */
277
291
  for (; free_list; free_list= next)
278
292
  {
279
293
    next= free_list->next;
302
316
  return false;                                 // 'false', as per coding style
303
317
}
304
318
 
305
 
void Session::setAbort(bool arg)
306
 
{
307
 
  mysys_var->abort= arg;
308
 
}
309
 
 
310
 
void Session::lockOnSys()
311
 
{
312
 
  if (not mysys_var)
313
 
    return;
314
 
 
315
 
  setAbort(true);
316
 
  boost_unique_lock_t scopedLock(mysys_var->mutex);
317
 
  if (mysys_var->current_cond)
318
 
  {
319
 
    mysys_var->current_mutex->lock();
320
 
    mysys_var->current_cond->notify_all();
321
 
    mysys_var->current_mutex->unlock();
322
 
  }
323
 
}
324
 
 
325
319
void Session::pop_internal_handler()
326
320
{
327
321
  assert(m_internal_handler != NULL);
328
322
  m_internal_handler= NULL;
329
323
}
330
324
 
331
 
void Session::get_xid(DRIZZLE_XID *xid)
332
 
{
333
 
  *xid = *(DRIZZLE_XID *) &transaction.xid_state.xid;
334
 
}
 
325
#if defined(__cplusplus)
 
326
extern "C" {
 
327
#endif
 
328
 
 
329
void *session_alloc(Session *session, unsigned int size)
 
330
{
 
331
  return session->alloc(size);
 
332
}
 
333
 
 
334
void *session_calloc(Session *session, unsigned int size)
 
335
{
 
336
  return session->calloc(size);
 
337
}
 
338
 
 
339
char *session_strdup(Session *session, const char *str)
 
340
{
 
341
  return session->strdup(str);
 
342
}
 
343
 
 
344
char *session_strmake(Session *session, const char *str, unsigned int size)
 
345
{
 
346
  return session->strmake(str, size);
 
347
}
 
348
 
 
349
void *session_memdup(Session *session, const void* str, unsigned int size)
 
350
{
 
351
  return session->memdup(str, size);
 
352
}
 
353
 
 
354
void session_get_xid(const Session *session, DRIZZLE_XID *xid)
 
355
{
 
356
  *xid = *(DRIZZLE_XID *) &session->transaction.xid_state.xid;
 
357
}
 
358
 
 
359
#if defined(__cplusplus)
 
360
}
 
361
#endif
335
362
 
336
363
/* Do operations that may take a long time */
337
364
 
339
366
{
340
367
  assert(cleanup_done == false);
341
368
 
342
 
  setKilled(KILL_CONNECTION);
 
369
  killed= KILL_CONNECTION;
343
370
#ifdef ENABLE_WHEN_BINLOG_WILL_BE_ABLE_TO_PREPARE
344
371
  if (transaction.xid_state.xa_state == XA_PREPARED)
345
372
  {
347
374
  }
348
375
#endif
349
376
  {
350
 
    TransactionServices &transaction_services= TransactionServices::singleton();
351
 
    transaction_services.rollbackTransaction(this, true);
 
377
    ha_rollback(this);
352
378
    xid_cache_delete(&transaction.xid_state);
353
379
  }
354
 
 
355
 
  for (UserVars::iterator iter= user_vars.begin();
356
 
       iter != user_vars.end();
357
 
       iter++)
358
 
  {
359
 
    user_var_entry *entry= (*iter).second;
360
 
    delete entry;
361
 
  }
362
 
  user_vars.clear();
363
 
 
364
 
 
 
380
  hash_free(&user_vars);
365
381
  close_temporary_tables();
366
382
 
367
383
  if (global_read_lock)
368
 
  {
369
 
    unlockGlobalReadLock();
370
 
  }
 
384
    unlock_global_read_lock(this);
371
385
 
372
386
  cleanup_done= true;
373
387
}
374
388
 
375
389
Session::~Session()
376
390
{
377
 
  this->checkSentry();
 
391
  Session_CHECK_SENTRY(this);
 
392
  add_to_status(&global_status_var, &status_var);
378
393
 
379
394
  if (client->isConnected())
380
395
  {
381
396
    if (global_system_variables.log_warnings)
382
 
        errmsg_printf(ERRMSG_LVL_WARN, ER(ER_FORCING_CLOSE),internal::my_progname,
 
397
        errmsg_printf(ERRMSG_LVL_WARN, ER(ER_FORCING_CLOSE),my_progname,
383
398
                      thread_id,
384
 
                      (getSecurityContext().getUser().c_str() ?
385
 
                       getSecurityContext().getUser().c_str() : ""));
 
399
                      (security_ctx.user.c_str() ?
 
400
                       security_ctx.user.c_str() : ""));
386
401
    disconnect(0, false);
387
402
  }
388
403
 
396
411
  plugin::StorageEngine::closeConnection(this);
397
412
  plugin_sessionvar_cleanup(this);
398
413
 
399
 
  warn_root.free_root(MYF(0));
 
414
  if (db)
 
415
  {
 
416
    free(db);
 
417
    db= NULL;
 
418
  }
 
419
  free_root(&warn_root,MYF(0));
 
420
  free_root(&transaction.mem_root,MYF(0));
400
421
  mysys_var=0;                                  // Safety (shouldn't be needed)
401
422
  dbug_sentry= Session_SENTRY_GONE;
402
423
 
403
 
  main_mem_root.free_root(MYF(0));
404
 
  currentMemRoot().release();
405
 
  currentSession().release();
406
 
 
407
 
  plugin::Logging::postEndDo(this);
408
 
  plugin::EventObserver::deregisterSessionEvents(*this); 
409
 
 
410
 
  for (PropertyMap::iterator iter= life_properties.begin(); iter != life_properties.end(); iter++)
411
 
  {
412
 
    delete (*iter).second;
413
 
  }
414
 
  life_properties.clear();
415
 
}
416
 
 
417
 
void Session::setClient(plugin::Client *client_arg)
418
 
{
419
 
  client= client_arg;
420
 
  client->setSession(this);
421
 
}
422
 
 
423
 
void Session::awake(Session::killed_state_t state_to_set)
424
 
{
425
 
  if ((state_to_set == Session::KILL_QUERY) and (command == COM_SLEEP))
426
 
    return;
427
 
 
428
 
  this->checkSentry();
429
 
 
430
 
  setKilled(state_to_set);
431
 
  scheduler->killSession(this);
432
 
 
 
424
  free_root(&main_mem_root, MYF(0));
 
425
  pthread_setspecific(THR_Session,  0);
 
426
 
 
427
 
 
428
  /* Ensure that no one is using Session */
 
429
  pthread_mutex_unlock(&LOCK_delete);
 
430
  pthread_mutex_destroy(&LOCK_delete);
 
431
}
 
432
 
 
433
/*
 
434
  Add all status variables to another status variable array
 
435
 
 
436
  SYNOPSIS
 
437
   add_to_status()
 
438
   to_var       add to this array
 
439
   from_var     from this array
 
440
 
 
441
  NOTES
 
442
    This function assumes that all variables are long/ulong.
 
443
    If this assumption will change, then we have to explictely add
 
444
    the other variables after the while loop
 
445
*/
 
446
void add_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var)
 
447
{
 
448
  ulong *end= (ulong*) ((unsigned char*) to_var +
 
449
                        offsetof(STATUS_VAR, last_system_status_var) +
 
450
                        sizeof(ulong));
 
451
  ulong *to= (ulong*) to_var, *from= (ulong*) from_var;
 
452
 
 
453
  while (to != end)
 
454
    *(to++)+= *(from++);
 
455
}
 
456
 
 
457
/*
 
458
  Add the difference between two status variable arrays to another one.
 
459
 
 
460
  SYNOPSIS
 
461
    add_diff_to_status
 
462
    to_var       add to this array
 
463
    from_var     from this array
 
464
    dec_var      minus this array
 
465
 
 
466
  NOTE
 
467
    This function assumes that all variables are long/ulong.
 
468
*/
 
469
void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var,
 
470
                        STATUS_VAR *dec_var)
 
471
{
 
472
  ulong *end= (ulong*) ((unsigned char*) to_var + offsetof(STATUS_VAR,
 
473
                                                  last_system_status_var) +
 
474
                        sizeof(ulong));
 
475
  ulong *to= (ulong*) to_var, *from= (ulong*) from_var, *dec= (ulong*) dec_var;
 
476
 
 
477
  while (to != end)
 
478
    *(to++)+= *(from++) - *(dec++);
 
479
}
 
480
 
 
481
void Session::awake(Session::killed_state state_to_set)
 
482
{
 
483
  Session_CHECK_SENTRY(this);
 
484
  safe_mutex_assert_owner(&LOCK_delete);
 
485
 
 
486
  killed= state_to_set;
433
487
  if (state_to_set != Session::KILL_QUERY)
434
488
  {
 
489
    scheduler->killSession(this);
435
490
    DRIZZLE_CONNECTION_DONE(thread_id);
436
491
  }
437
 
 
438
492
  if (mysys_var)
439
493
  {
440
 
    boost_unique_lock_t scopedLock(mysys_var->mutex);
 
494
    pthread_mutex_lock(&mysys_var->mutex);
441
495
    /*
442
 
      "
443
496
      This broadcast could be up in the air if the victim thread
444
497
      exits the cond in the time between read and broadcast, but that is
445
498
      ok since all we want to do is to make the victim thread get out
460
513
    */
461
514
    if (mysys_var->current_cond && mysys_var->current_mutex)
462
515
    {
463
 
      mysys_var->current_mutex->lock();
464
 
      mysys_var->current_cond->notify_all();
465
 
      mysys_var->current_mutex->unlock();
 
516
      pthread_mutex_lock(mysys_var->current_mutex);
 
517
      pthread_cond_broadcast(mysys_var->current_cond);
 
518
      pthread_mutex_unlock(mysys_var->current_mutex);
466
519
    }
 
520
    pthread_mutex_unlock(&mysys_var->mutex);
467
521
  }
468
522
}
469
523
 
470
524
/*
471
525
  Remember the location of thread info, the structure needed for
472
 
  memory::sql_alloc() and the structure for the net buffer
 
526
  sql_alloc() and the structure for the net buffer
473
527
*/
474
528
bool Session::storeGlobals()
475
529
{
479
533
  */
480
534
  assert(thread_stack);
481
535
 
482
 
  currentSession().release();
483
 
  currentSession().reset(this);
484
 
 
485
 
  currentMemRoot().release();
486
 
  currentMemRoot().reset(&mem_root);
 
536
  if (pthread_setspecific(THR_Session,  this) ||
 
537
      pthread_setspecific(THR_Mem_root, &mem_root))
 
538
    return true;
487
539
 
488
540
  mysys_var=my_thread_var;
489
541
 
492
544
    This allows us to move Session to different threads if needed.
493
545
  */
494
546
  mysys_var->id= thread_id;
 
547
  real_id= pthread_self();                      // For debugging
495
548
 
496
549
  /*
497
550
    We have to call thr_lock_info_init() again here as Session may have been
498
551
    created in another thread
499
552
  */
500
 
  lock_info.init();
501
 
 
 
553
  thr_lock_info_init(&lock_info);
502
554
  return false;
503
555
}
504
556
 
517
569
  set_proc_info(NULL);
518
570
  command= COM_SLEEP;
519
571
  set_time();
 
572
  ha_enable_transaction(this,true);
520
573
 
521
 
  mem_root->reset_root_defaults(variables.query_alloc_block_size,
522
 
                                variables.query_prealloc_size);
 
574
  reset_root_defaults(mem_root, variables.query_alloc_block_size,
 
575
                      variables.query_prealloc_size);
 
576
  reset_root_defaults(&transaction.mem_root,
 
577
                      variables.trans_alloc_block_size,
 
578
                      variables.trans_prealloc_size);
523
579
  transaction.xid_state.xid.null();
524
580
  transaction.xid_state.in_session=1;
525
 
  if (use_usage)
526
 
    resetUsage();
527
581
}
528
582
 
529
583
bool Session::initGlobals()
531
585
  if (storeGlobals())
532
586
  {
533
587
    disconnect(ER_OUT_OF_RESOURCES, true);
534
 
    status_var.aborted_connects++;
 
588
    statistic_increment(aborted_connects, &LOCK_status);
535
589
    return true;
536
590
  }
537
591
  return false;
547
601
 
548
602
  prepareForQueries();
549
603
 
550
 
  while (not client->haveError() && getKilled() != KILL_CONNECTION)
 
604
  while (! client->haveError() && killed != KILL_CONNECTION)
551
605
  {
552
 
    if (not executeStatement())
 
606
    if (! executeStatement())
553
607
      break;
554
608
  }
555
609
 
556
610
  disconnect(0, true);
557
611
}
558
612
 
559
 
bool Session::schedule(Session::shared_ptr &arg)
 
613
bool Session::schedule()
560
614
{
561
 
  arg->scheduler= plugin::Scheduler::getScheduler();
562
 
  assert(arg->scheduler);
563
 
 
564
 
  connection_count.increment();
565
 
 
566
 
  if (connection_count > current_global_counters.max_used_connections)
567
 
  {
568
 
    current_global_counters.max_used_connections= connection_count;
569
 
  }
570
 
 
571
 
  current_global_counters.connections++;
572
 
  arg->thread_id= arg->variables.pseudo_thread_id= global_thread_id++;
573
 
 
574
 
  session::Cache::singleton().insert(arg);
575
 
 
576
 
  if (unlikely(plugin::EventObserver::connectSession(*arg)))
577
 
  {
578
 
    // We should do something about an error...
579
 
  }
580
 
 
581
 
  if (plugin::Scheduler::getScheduler()->addSession(arg))
582
 
  {
583
 
    DRIZZLE_CONNECTION_START(arg->getSessionId());
 
615
  scheduler= plugin::Scheduler::getScheduler();
 
616
  assert(scheduler);
 
617
 
 
618
  ++connection_count;
 
619
 
 
620
  if (connection_count > max_used_connections)
 
621
    max_used_connections= connection_count;
 
622
 
 
623
  thread_id= variables.pseudo_thread_id= global_thread_id++;
 
624
 
 
625
  pthread_mutex_lock(&LOCK_thread_count);
 
626
  session_list.push_back(this);
 
627
  pthread_mutex_unlock(&LOCK_thread_count);
 
628
 
 
629
  if (scheduler->addSession(this))
 
630
  {
 
631
    DRIZZLE_CONNECTION_START(thread_id);
584
632
    char error_message_buff[DRIZZLE_ERRMSG_SIZE];
585
633
 
586
 
    arg->setKilled(Session::KILL_CONNECTION);
 
634
    killed= Session::KILL_CONNECTION;
587
635
 
588
 
    arg->status_var.aborted_connects++;
 
636
    statistic_increment(aborted_connects, &LOCK_status);
589
637
 
590
638
    /* Can't use my_error() since store_globals has not been called. */
591
639
    /* TODO replace will better error message */
592
640
    snprintf(error_message_buff, sizeof(error_message_buff),
593
641
             ER(ER_CANT_CREATE_THREAD), 1);
594
 
    arg->client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
595
 
 
 
642
    client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
596
643
    return true;
597
644
  }
598
645
 
599
646
  return false;
600
647
}
601
648
 
602
 
 
603
 
/*
604
 
  Is this session viewable by the current user?
605
 
*/
606
 
bool Session::isViewable() const
607
 
{
608
 
  return plugin::Authorization::isAuthorized(current_session->getSecurityContext(),
609
 
                                             this,
610
 
                                             false);
611
 
}
612
 
 
613
 
 
614
 
const char* Session::enter_cond(boost::condition_variable_any &cond, boost::mutex &mutex, const char* msg)
615
 
{
616
 
  const char* old_msg = get_proc_info();
617
 
  safe_mutex_assert_owner(mutex);
618
 
  mysys_var->current_mutex = &mutex;
619
 
  mysys_var->current_cond = &cond;
620
 
  this->set_proc_info(msg);
621
 
  return old_msg;
622
 
}
623
 
 
624
 
void Session::exit_cond(const char* old_msg)
625
 
{
626
 
  /*
627
 
    Putting the mutex unlock in exit_cond() ensures that
628
 
    mysys_var->current_mutex is always unlocked _before_ mysys_var->mutex is
629
 
    locked (if that would not be the case, you'll get a deadlock if someone
630
 
    does a Session::awake() on you).
631
 
  */
632
 
  mysys_var->current_mutex->unlock();
633
 
  boost_unique_lock_t scopedLock(mysys_var->mutex);
634
 
  mysys_var->current_mutex = 0;
635
 
  mysys_var->current_cond = 0;
636
 
  this->set_proc_info(old_msg);
637
 
}
638
 
 
639
649
bool Session::authenticate()
640
650
{
641
 
  lex->start(this);
 
651
  lex_start(this);
642
652
  if (client->authenticate())
643
653
    return false;
644
654
 
645
 
  status_var.aborted_connects++;
646
 
 
 
655
  statistic_increment(aborted_connects, &LOCK_status);
647
656
  return true;
648
657
}
649
658
 
650
 
bool Session::checkUser(const std::string &passwd_str,
651
 
                        const std::string &in_db)
 
659
bool Session::checkUser(const char *passwd, uint32_t passwd_len, const char *in_db)
652
660
{
653
 
  bool is_authenticated=
654
 
    plugin::Authentication::isAuthenticated(getSecurityContext(),
655
 
                                            passwd_str);
 
661
  LEX_STRING db_str= { (char *) in_db, in_db ? strlen(in_db) : 0 };
 
662
  bool is_authenticated;
 
663
 
 
664
  /*
 
665
    Clear session->db as it points to something, that will be freed when
 
666
    connection is closed. We don't want to accidentally free a wrong
 
667
    pointer if connect failed. Also in case of 'CHANGE USER' failure,
 
668
    current database will be switched to 'no database selected'.
 
669
  */
 
670
  reset_db(NULL, 0);
 
671
 
 
672
  if (passwd_len != 0 && passwd_len != SCRAMBLE_LENGTH)
 
673
  {
 
674
    my_error(ER_HANDSHAKE_ERROR, MYF(0), security_ctx.ip.c_str());
 
675
    return false;
 
676
  }
 
677
 
 
678
  is_authenticated= plugin::Authentication::isAuthenticated(this, passwd);
656
679
 
657
680
  if (is_authenticated != true)
658
681
  {
659
 
    status_var.access_denied++;
660
 
    /* isAuthenticated has pushed the error message */
 
682
    my_error(ER_ACCESS_DENIED_ERROR, MYF(0),
 
683
             security_ctx.user.c_str(),
 
684
             security_ctx.ip.c_str(),
 
685
             passwd_len ? ER(ER_YES) : ER(ER_NO));
 
686
 
661
687
    return false;
662
688
  }
663
689
 
 
690
  security_ctx.skip_grants();
 
691
 
664
692
  /* Change database if necessary */
665
 
  if (not in_db.empty())
 
693
  if (in_db && in_db[0])
666
694
  {
667
 
    SchemaIdentifier identifier(in_db);
668
 
    if (mysql_change_db(this, identifier))
 
695
    if (mysql_change_db(this, &db_str, false))
669
696
    {
670
697
      /* mysql_change_db() has pushed the error message. */
671
698
      return false;
672
699
    }
673
700
  }
674
701
  my_ok();
675
 
  password= not passwd_str.empty();
 
702
  password= test(passwd_len);          // remember for error messages
676
703
 
677
704
  /* Ready to handle queries */
678
705
  return true;
694
721
  main_da.reset_diagnostics_area();
695
722
 
696
723
  if (client->readCommand(&l_packet, &packet_length) == false)
697
 
  {
698
 
    return false;
699
 
  }
700
 
 
701
 
  if (getKilled() == KILL_CONNECTION)
702
724
    return false;
703
725
 
704
726
  if (packet_length == 0)
705
727
    return true;
706
728
 
707
 
  l_command= static_cast<enum_server_command>(l_packet[0]);
 
729
  l_command= (enum enum_server_command) (unsigned char) l_packet[0];
708
730
 
709
731
  if (command >= COM_END)
710
732
    command= COM_END;                           // Wrong command
711
733
 
712
734
  assert(packet_length);
713
 
  return not dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
 
735
  return ! dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
714
736
}
715
737
 
716
738
bool Session::readAndStoreQuery(const char *in_packet, uint32_t in_packet_length)
722
744
    in_packet_length--;
723
745
  }
724
746
  const char *pos= in_packet + in_packet_length; /* Point at end null */
725
 
  while (in_packet_length > 0 && (pos[-1] == ';' || my_isspace(charset() ,pos[-1])))
 
747
  while (in_packet_length > 0 &&
 
748
         (pos[-1] == ';' || my_isspace(charset() ,pos[-1])))
726
749
  {
727
750
    pos--;
728
751
    in_packet_length--;
729
752
  }
730
753
 
731
 
  std::string *new_query= new std::string(in_packet, in_packet + in_packet_length);
732
 
  // We can not be entirely sure _schema has a value
733
 
  if (_schema)
734
 
  {
735
 
    plugin::QueryRewriter::rewriteQuery(*_schema, *new_query);
736
 
  }
737
 
  query.reset(new_query);
738
 
  _state.reset(new State(in_packet, in_packet_length));
 
754
  /* We must allocate some extra memory for the cached query string */
 
755
  query_length= 0; /* Extra safety: Avoid races */
 
756
  query= (char*) memdup_w_gap((unsigned char*) in_packet, in_packet_length, db_length + 1);
 
757
  if (! query)
 
758
    return false;
 
759
 
 
760
  query[in_packet_length]=0;
 
761
  query_length= in_packet_length;
739
762
 
740
763
  return true;
741
764
}
744
767
{
745
768
  bool do_release= 0;
746
769
  bool result= true;
747
 
  TransactionServices &transaction_services= TransactionServices::singleton();
748
770
 
749
771
  if (transaction.xid_state.xa_state != XA_NOTR)
750
772
  {
760
782
       * (Which of course should never happen...)
761
783
       */
762
784
      server_status&= ~SERVER_STATUS_IN_TRANS;
763
 
      if (transaction_services.commitTransaction(this, true))
 
785
      if (ha_commit(this))
764
786
        result= false;
765
787
      options&= ~(OPTION_BEGIN);
 
788
      transaction.all.modified_non_trans_table= false;
766
789
      break;
767
790
    case COMMIT_RELEASE:
768
791
      do_release= 1; /* fall through */
777
800
    case ROLLBACK_AND_CHAIN:
778
801
    {
779
802
      server_status&= ~SERVER_STATUS_IN_TRANS;
780
 
      if (transaction_services.rollbackTransaction(this, true))
 
803
      if (ha_rollback(this))
781
804
        result= false;
782
805
      options&= ~(OPTION_BEGIN);
 
806
      transaction.all.modified_non_trans_table= false;
783
807
      if (result == true && (completion == ROLLBACK_AND_CHAIN))
784
808
        result= startTransaction();
785
809
      break;
790
814
  }
791
815
 
792
816
  if (result == false)
793
 
  {
794
817
    my_error(killed_errno(), MYF(0));
795
 
  }
796
818
  else if ((result == true) && do_release)
797
 
  {
798
 
    setKilled(Session::KILL_CONNECTION);
799
 
  }
 
819
    killed= Session::KILL_CONNECTION;
800
820
 
801
821
  return result;
802
822
}
804
824
bool Session::endActiveTransaction()
805
825
{
806
826
  bool result= true;
807
 
  TransactionServices &transaction_services= TransactionServices::singleton();
808
827
 
809
828
  if (transaction.xid_state.xa_state != XA_NOTR)
810
829
  {
814
833
  if (options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
815
834
  {
816
835
    server_status&= ~SERVER_STATUS_IN_TRANS;
817
 
    if (transaction_services.commitTransaction(this, true))
 
836
    if (ha_commit(this))
818
837
      result= false;
819
838
  }
820
839
  options&= ~(OPTION_BEGIN);
 
840
  transaction.all.modified_non_trans_table= false;
821
841
  return result;
822
842
}
823
843
 
834
854
    options|= OPTION_BEGIN;
835
855
    server_status|= SERVER_STATUS_IN_TRANS;
836
856
 
837
 
    if (plugin::TransactionalStorageEngine::notifyStartTransaction(this, opt))
 
857
    if (opt == START_TRANS_OPT_WITH_CONS_SNAPSHOT)
838
858
    {
839
 
      result= false;
 
859
      // TODO make this a loop for all engines, not just this one (Inno only
 
860
      // right now)
 
861
      if (plugin::StorageEngine::startConsistentSnapshot(this))
 
862
      {
 
863
        result= false;
 
864
      }
840
865
    }
841
866
  }
842
867
 
865
890
  free_items();
866
891
  /* Reset where. */
867
892
  where= Session::DEFAULT_WHERE;
868
 
 
869
 
  /* Reset the temporary shares we built */
870
 
  for_each(temporary_shares.begin(),
871
 
           temporary_shares.end(),
872
 
           DeletePtr());
873
 
  temporary_shares.clear();
874
893
}
875
894
 
876
895
/**
884
903
  @return  NULL on failure, or pointer to the LEX_STRING object
885
904
*/
886
905
LEX_STRING *Session::make_lex_string(LEX_STRING *lex_str,
887
 
                                     const std::string &str,
888
 
                                     bool allocate_lex_string)
889
 
{
890
 
  return make_lex_string(lex_str, str.c_str(), str.length(), allocate_lex_string);
891
 
}
892
 
 
893
 
LEX_STRING *Session::make_lex_string(LEX_STRING *lex_str,
894
 
                                     const char* str, uint32_t length,
895
 
                                     bool allocate_lex_string)
 
906
                                 const char* str, uint32_t length,
 
907
                                 bool allocate_lex_string)
896
908
{
897
909
  if (allocate_lex_string)
898
910
    if (!(lex_str= (LEX_STRING *)alloc(sizeof(LEX_STRING))))
899
911
      return 0;
900
 
  if (!(lex_str->str= mem_root->strmake_root(str, length)))
 
912
  if (!(lex_str->str= strmake_root(mem_root, str, length)))
901
913
    return 0;
902
914
  lex_str->length= length;
903
915
  return lex_str;
904
916
}
905
917
 
 
918
/* routings to adding tables to list of changed in transaction tables */
 
919
inline static void list_include(CHANGED_TableList** prev,
 
920
                                CHANGED_TableList* curr,
 
921
                                CHANGED_TableList* new_table)
 
922
{
 
923
  if (new_table)
 
924
  {
 
925
    *prev = new_table;
 
926
    (*prev)->next = curr;
 
927
  }
 
928
}
 
929
 
 
930
/* add table to list of changed in transaction tables */
 
931
 
 
932
void Session::add_changed_table(Table *table)
 
933
{
 
934
  assert((options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) &&
 
935
              table->cursor->has_transactions());
 
936
  add_changed_table(table->s->table_cache_key.str,
 
937
                    (long) table->s->table_cache_key.length);
 
938
}
 
939
 
 
940
 
 
941
void Session::add_changed_table(const char *key, long key_length)
 
942
{
 
943
  CHANGED_TableList **prev_changed = &transaction.changed_tables;
 
944
  CHANGED_TableList *curr = transaction.changed_tables;
 
945
 
 
946
  for (; curr; prev_changed = &(curr->next), curr = curr->next)
 
947
  {
 
948
    int cmp =  (long)curr->key_length - (long)key_length;
 
949
    if (cmp < 0)
 
950
    {
 
951
      list_include(prev_changed, curr, changed_table_dup(key, key_length));
 
952
      return;
 
953
    }
 
954
    else if (cmp == 0)
 
955
    {
 
956
      cmp = memcmp(curr->key, key, curr->key_length);
 
957
      if (cmp < 0)
 
958
      {
 
959
        list_include(prev_changed, curr, changed_table_dup(key, key_length));
 
960
        return;
 
961
      }
 
962
      else if (cmp == 0)
 
963
      {
 
964
        return;
 
965
      }
 
966
    }
 
967
  }
 
968
  *prev_changed = changed_table_dup(key, key_length);
 
969
}
 
970
 
 
971
 
 
972
CHANGED_TableList* Session::changed_table_dup(const char *key, long key_length)
 
973
{
 
974
  CHANGED_TableList* new_table =
 
975
    (CHANGED_TableList*) trans_alloc(ALIGN_SIZE(sizeof(CHANGED_TableList))+
 
976
                                      key_length + 1);
 
977
  if (!new_table)
 
978
  {
 
979
    my_error(EE_OUTOFMEMORY, MYF(ME_BELL),
 
980
             ALIGN_SIZE(sizeof(TableList)) + key_length + 1);
 
981
    killed= KILL_CONNECTION;
 
982
    return 0;
 
983
  }
 
984
 
 
985
  new_table->key= ((char*)new_table)+ ALIGN_SIZE(sizeof(CHANGED_TableList));
 
986
  new_table->next = 0;
 
987
  new_table->key_length = key_length;
 
988
  ::memcpy(new_table->key, key, key_length);
 
989
  return new_table;
 
990
}
 
991
 
 
992
 
906
993
int Session::send_explain_fields(select_result *result)
907
994
{
908
995
  List<Item> field_list;
941
1028
  return (result->send_fields(field_list));
942
1029
}
943
1030
 
944
 
void select_result::send_error(uint32_t errcode, const char *err)
945
 
{
946
 
  my_message(errcode, err, MYF(0));
947
 
}
948
 
 
949
1031
/************************************************************************
950
1032
  Handling writing to file
951
1033
************************************************************************/
955
1037
  my_message(errcode, err, MYF(0));
956
1038
  if (file > 0)
957
1039
  {
958
 
    (void) cache->end_io_cache();
959
 
    (void) internal::my_close(file, MYF(0));
960
 
    (void) internal::my_delete(path.file_string().c_str(), MYF(0));             // Delete file on error
 
1040
    (void) end_io_cache(&cache);
 
1041
    (void) my_close(file, MYF(0));
 
1042
    (void) my_delete(path, MYF(0));             // Delete file on error
961
1043
    file= -1;
962
1044
  }
963
1045
}
965
1047
 
966
1048
bool select_to_file::send_eof()
967
1049
{
968
 
  int error= test(cache->end_io_cache());
969
 
  if (internal::my_close(file, MYF(MY_WME)))
 
1050
  int error= test(end_io_cache(&cache));
 
1051
  if (my_close(file, MYF(MY_WME)))
970
1052
    error= 1;
971
1053
  if (!error)
972
1054
  {
987
1069
  /* In case of error send_eof() may be not called: close the file here. */
988
1070
  if (file >= 0)
989
1071
  {
990
 
    (void) cache->end_io_cache();
991
 
    (void) internal::my_close(file, MYF(0));
 
1072
    (void) end_io_cache(&cache);
 
1073
    (void) my_close(file, MYF(0));
992
1074
    file= -1;
993
1075
  }
994
 
  path= "";
 
1076
  path[0]= '\0';
995
1077
  row_count= 0;
996
1078
}
997
1079
 
998
 
select_to_file::select_to_file(file_exchange *ex)
999
 
  : exchange(ex),
1000
 
    file(-1),
1001
 
    cache(static_cast<internal::IO_CACHE *>(memory::sql_calloc(sizeof(internal::IO_CACHE)))),
1002
 
    row_count(0L)
1003
 
{
1004
 
  path= "";
1005
 
}
1006
1080
 
1007
1081
select_to_file::~select_to_file()
1008
1082
{
1009
 
  cleanup();
 
1083
  if (file >= 0)
 
1084
  {                                     // This only happens in case of error
 
1085
    (void) end_io_cache(&cache);
 
1086
    (void) my_close(file, MYF(0));
 
1087
    file= -1;
 
1088
  }
1010
1089
}
1011
1090
 
1012
1091
/***************************************************************************
1035
1114
*/
1036
1115
 
1037
1116
 
1038
 
static int create_file(Session *session,
1039
 
                       fs::path &target_path,
1040
 
                       file_exchange *exchange,
1041
 
                       internal::IO_CACHE *cache)
 
1117
static File create_file(Session *session, char *path, file_exchange *exchange, IO_CACHE *cache)
1042
1118
{
1043
 
  fs::path to_file(exchange->file_name);
1044
 
  int file;
1045
 
 
1046
 
  if (not to_file.has_root_directory())
 
1119
  File file;
 
1120
  uint32_t option= MY_UNPACK_FILENAME | MY_RELATIVE_PATH;
 
1121
 
 
1122
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
 
1123
  option|= MY_REPLACE_DIR;                      // Force use of db directory
 
1124
#endif
 
1125
 
 
1126
  if (!dirname_length(exchange->file_name))
1047
1127
  {
1048
 
    target_path= fs::system_complete(getDataHomeCatalog());
1049
 
    util::string::const_shared_ptr schema(session->schema());
1050
 
    if (schema and not schema->empty())
1051
 
    {
1052
 
      int count_elements= 0;
1053
 
      for (fs::path::iterator iter= to_file.begin();
1054
 
           iter != to_file.end();
1055
 
           ++iter, ++count_elements)
1056
 
      { }
1057
 
 
1058
 
      if (count_elements == 1)
1059
 
      {
1060
 
        target_path /= *schema;
1061
 
      }
1062
 
    }
1063
 
    target_path /= to_file;
 
1128
    strcpy(path, drizzle_real_data_home);
 
1129
    if (session->db)
 
1130
      strncat(path, session->db, FN_REFLEN-strlen(drizzle_real_data_home)-1);
 
1131
    (void) fn_format(path, exchange->file_name, path, "", option);
1064
1132
  }
1065
1133
  else
1066
 
  {
1067
 
    target_path = exchange->file_name;
1068
 
  }
1069
 
 
1070
 
  if (not secure_file_priv.string().empty())
1071
 
  {
1072
 
    if (target_path.file_string().substr(0, secure_file_priv.file_string().size()) != secure_file_priv.file_string())
1073
 
    {
1074
 
      /* Write only allowed to dir or subdir specified by secure_file_priv */
1075
 
      my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
1076
 
      return -1;
1077
 
    }
1078
 
  }
1079
 
 
1080
 
  if (!access(target_path.file_string().c_str(), F_OK))
 
1134
    (void) fn_format(path, exchange->file_name, drizzle_real_data_home, "", option);
 
1135
 
 
1136
  if (opt_secure_file_priv &&
 
1137
      strncmp(opt_secure_file_priv, path, strlen(opt_secure_file_priv)))
 
1138
  {
 
1139
    /* Write only allowed to dir or subdir specified by secure_file_priv */
 
1140
    my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
 
1141
    return -1;
 
1142
  }
 
1143
 
 
1144
  if (!access(path, F_OK))
1081
1145
  {
1082
1146
    my_error(ER_FILE_EXISTS_ERROR, MYF(0), exchange->file_name);
1083
1147
    return -1;
1084
1148
  }
1085
1149
  /* Create the file world readable */
1086
 
  if ((file= internal::my_create(target_path.file_string().c_str(), 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
 
1150
  if ((file= my_create(path, 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
1087
1151
    return file;
 
1152
#ifdef HAVE_FCHMOD
1088
1153
  (void) fchmod(file, 0666);                    // Because of umask()
1089
 
  if (cache->init_io_cache(file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
 
1154
#else
 
1155
  (void) chmod(path, 0666);
 
1156
#endif
 
1157
  if (init_io_cache(cache, file, 0L, WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1090
1158
  {
1091
 
    internal::my_close(file, MYF(0));
1092
 
    internal::my_delete(target_path.file_string().c_str(), MYF(0));  // Delete file on error, it was just created
 
1159
    my_close(file, MYF(0));
 
1160
    my_delete(path, MYF(0));  // Delete file on error, it was just created
1093
1161
    return -1;
1094
1162
  }
1095
1163
  return file;
1103
1171
  bool string_results= false, non_string_results= false;
1104
1172
  unit= u;
1105
1173
  if ((uint32_t) strlen(exchange->file_name) + NAME_LEN >= FN_REFLEN)
1106
 
  {
1107
 
    path= exchange->file_name;
1108
 
  }
 
1174
    strncpy(path,exchange->file_name,FN_REFLEN-1);
1109
1175
 
1110
1176
  /* Check if there is any blobs in data */
1111
1177
  {
1115
1181
    {
1116
1182
      if (item->max_length >= MAX_BLOB_WIDTH)
1117
1183
      {
1118
 
        blob_flag=1;
1119
 
        break;
 
1184
        blob_flag=1;
 
1185
        break;
1120
1186
      }
1121
 
 
1122
1187
      if (item->result_type() == STRING_RESULT)
1123
1188
        string_results= true;
1124
1189
      else
1153
1218
    return 1;
1154
1219
  }
1155
1220
 
1156
 
  if ((file= create_file(session, path, exchange, cache)) < 0)
 
1221
  if ((file= create_file(session, path, exchange, &cache)) < 0)
1157
1222
    return 1;
1158
1223
 
1159
1224
  return 0;
1160
1225
}
1161
1226
 
 
1227
 
 
1228
#define NEED_ESCAPING(x) ((int) (unsigned char) (x) == escape_char    || \
 
1229
                          (enclosed ? (int) (unsigned char) (x) == field_sep_char      \
 
1230
                                    : (int) (unsigned char) (x) == field_term_char) || \
 
1231
                          (int) (unsigned char) (x) == line_sep_char  || \
 
1232
                          !(x))
 
1233
 
1162
1234
bool select_export::send_data(List<Item> &items)
1163
1235
{
1164
1236
  char buff[MAX_FIELD_WIDTH],null_buff[2],space[MAX_FIELD_WIDTH];
1169
1241
  if (unit->offset_limit_cnt)
1170
1242
  {                                             // using limit offset,count
1171
1243
    unit->offset_limit_cnt--;
1172
 
    return false;
 
1244
    return(0);
1173
1245
  }
1174
1246
  row_count++;
1175
1247
  Item *item;
1176
1248
  uint32_t used_length=0,items_left=items.elements;
1177
1249
  List_iterator_fast<Item> li(items);
1178
1250
 
1179
 
  if (my_b_write(cache,(unsigned char*) exchange->line_start->ptr(),
 
1251
  if (my_b_write(&cache,(unsigned char*) exchange->line_start->ptr(),
1180
1252
                 exchange->line_start->length()))
1181
 
    return true;
1182
 
 
 
1253
    goto err;
1183
1254
  while ((item=li++))
1184
1255
  {
1185
1256
    Item_result result_type=item->result_type();
1188
1259
    res=item->str_result(&tmp);
1189
1260
    if (res && enclosed)
1190
1261
    {
1191
 
      if (my_b_write(cache,(unsigned char*) exchange->enclosed->ptr(),
 
1262
      if (my_b_write(&cache,(unsigned char*) exchange->enclosed->ptr(),
1192
1263
                     exchange->enclosed->length()))
1193
 
        return true;
 
1264
        goto err;
1194
1265
    }
1195
1266
    if (!res)
1196
1267
    {                                           // NULL
1200
1271
        {
1201
1272
          null_buff[0]=escape_char;
1202
1273
          null_buff[1]='N';
1203
 
          if (my_b_write(cache,(unsigned char*) null_buff,2))
1204
 
            return true;
 
1274
          if (my_b_write(&cache,(unsigned char*) null_buff,2))
 
1275
            goto err;
1205
1276
        }
1206
 
        else if (my_b_write(cache,(unsigned char*) "NULL",4))
1207
 
          return true;
 
1277
        else if (my_b_write(&cache,(unsigned char*) "NULL",4))
 
1278
          goto err;
1208
1279
      }
1209
1280
      else
1210
1281
      {
1214
1285
    else
1215
1286
    {
1216
1287
      if (fixed_row_size)
1217
 
        used_length= min(res->length(), static_cast<size_t>(item->max_length));
 
1288
        used_length= min(res->length(),item->max_length);
1218
1289
      else
1219
1290
        used_length= res->length();
1220
1291
 
1276
1347
            assert before the loop makes that sure.
1277
1348
          */
1278
1349
 
1279
 
          if ((needs_escaping(*pos, enclosed) ||
 
1350
          if ((NEED_ESCAPING(*pos) ||
1280
1351
               (check_second_byte &&
1281
1352
                my_mbcharlen(character_set_client, (unsigned char) *pos) == 2 &&
1282
1353
                pos + 1 < end &&
1283
 
                needs_escaping(pos[1], enclosed))) &&
 
1354
                NEED_ESCAPING(pos[1]))) &&
1284
1355
              /*
1285
1356
                Don't escape field_term_char by doubling - doubling is only
1286
1357
                valid for ENCLOSED BY characters:
1293
1364
                          is_ambiguous_field_sep) ?
1294
1365
              field_sep_char : escape_char;
1295
1366
            tmp_buff[1]= *pos ? *pos : '0';
1296
 
            if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)) ||
1297
 
                my_b_write(cache,(unsigned char*) tmp_buff,2))
1298
 
              return true;
 
1367
            if (my_b_write(&cache,(unsigned char*) start,(uint32_t) (pos-start)) ||
 
1368
                my_b_write(&cache,(unsigned char*) tmp_buff,2))
 
1369
              goto err;
1299
1370
            start=pos+1;
1300
1371
          }
1301
1372
        }
1302
 
        if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)))
1303
 
          return true;
 
1373
        if (my_b_write(&cache,(unsigned char*) start,(uint32_t) (pos-start)))
 
1374
          goto err;
1304
1375
      }
1305
 
      else if (my_b_write(cache,(unsigned char*) res->ptr(),used_length))
1306
 
        return true;
 
1376
      else if (my_b_write(&cache,(unsigned char*) res->ptr(),used_length))
 
1377
        goto err;
1307
1378
    }
1308
1379
    if (fixed_row_size)
1309
1380
    {                                           // Fill with space
1318
1389
        uint32_t length=item->max_length-used_length;
1319
1390
        for (; length > sizeof(space) ; length-=sizeof(space))
1320
1391
        {
1321
 
          if (my_b_write(cache,(unsigned char*) space,sizeof(space)))
1322
 
            return true;
 
1392
          if (my_b_write(&cache,(unsigned char*) space,sizeof(space)))
 
1393
            goto err;
1323
1394
        }
1324
 
        if (my_b_write(cache,(unsigned char*) space,length))
1325
 
          return true;
 
1395
        if (my_b_write(&cache,(unsigned char*) space,length))
 
1396
          goto err;
1326
1397
      }
1327
1398
    }
1328
1399
    if (res && enclosed)
1329
1400
    {
1330
 
      if (my_b_write(cache, (unsigned char*) exchange->enclosed->ptr(),
 
1401
      if (my_b_write(&cache, (unsigned char*) exchange->enclosed->ptr(),
1331
1402
                     exchange->enclosed->length()))
1332
 
        return true;
 
1403
        goto err;
1333
1404
    }
1334
1405
    if (--items_left)
1335
1406
    {
1336
 
      if (my_b_write(cache, (unsigned char*) exchange->field_term->ptr(),
 
1407
      if (my_b_write(&cache, (unsigned char*) exchange->field_term->ptr(),
1337
1408
                     field_term_length))
1338
 
        return true;
 
1409
        goto err;
1339
1410
    }
1340
1411
  }
1341
 
  if (my_b_write(cache,(unsigned char*) exchange->line_term->ptr(),
 
1412
  if (my_b_write(&cache,(unsigned char*) exchange->line_term->ptr(),
1342
1413
                 exchange->line_term->length()))
1343
 
  {
1344
 
    return true;
1345
 
  }
1346
 
 
1347
 
  return false;
 
1414
    goto err;
 
1415
  return(0);
 
1416
err:
 
1417
  return(1);
1348
1418
}
1349
1419
 
1350
1420
 
1357
1427
select_dump::prepare(List<Item> &, Select_Lex_Unit *u)
1358
1428
{
1359
1429
  unit= u;
1360
 
  return (int) ((file= create_file(session, path, exchange, cache)) < 0);
 
1430
  return (int) ((file= create_file(session, path, exchange, &cache)) < 0);
1361
1431
}
1362
1432
 
1363
1433
 
1377
1447
  if (row_count++ > 1)
1378
1448
  {
1379
1449
    my_message(ER_TOO_MANY_ROWS, ER(ER_TOO_MANY_ROWS), MYF(0));
1380
 
    return 1;
 
1450
    goto err;
1381
1451
  }
1382
1452
  while ((item=li++))
1383
1453
  {
1384
1454
    res=item->str_result(&tmp);
1385
1455
    if (!res)                                   // If NULL
1386
1456
    {
1387
 
      if (my_b_write(cache,(unsigned char*) "",1))
1388
 
        return 1;
 
1457
      if (my_b_write(&cache,(unsigned char*) "",1))
 
1458
        goto err;
1389
1459
    }
1390
 
    else if (my_b_write(cache,(unsigned char*) res->ptr(),res->length()))
 
1460
    else if (my_b_write(&cache,(unsigned char*) res->ptr(),res->length()))
1391
1461
    {
1392
 
      my_error(ER_ERROR_ON_WRITE, MYF(0), path.file_string().c_str(), errno);
1393
 
      return 1;
 
1462
      my_error(ER_ERROR_ON_WRITE, MYF(0), path, my_errno);
 
1463
      goto err;
1394
1464
    }
1395
1465
  }
1396
1466
  return(0);
 
1467
err:
 
1468
  return(1);
1397
1469
}
1398
1470
 
1399
1471
 
1451
1523
      switch (val_item->result_type())
1452
1524
      {
1453
1525
      case REAL_RESULT:
1454
 
        op= &select_max_min_finder_subselect::cmp_real;
1455
 
        break;
 
1526
        op= &select_max_min_finder_subselect::cmp_real;
 
1527
        break;
1456
1528
      case INT_RESULT:
1457
 
        op= &select_max_min_finder_subselect::cmp_int;
1458
 
        break;
 
1529
        op= &select_max_min_finder_subselect::cmp_int;
 
1530
        break;
1459
1531
      case STRING_RESULT:
1460
 
        op= &select_max_min_finder_subselect::cmp_str;
1461
 
        break;
 
1532
        op= &select_max_min_finder_subselect::cmp_str;
 
1533
        break;
1462
1534
      case DECIMAL_RESULT:
1463
1535
        op= &select_max_min_finder_subselect::cmp_decimal;
1464
1536
        break;
1465
1537
      case ROW_RESULT:
1466
1538
        // This case should never be choosen
1467
 
        assert(0);
1468
 
        op= 0;
 
1539
        assert(0);
 
1540
        op= 0;
1469
1541
      }
1470
1542
    }
1471
1543
    cache->store(val_item);
1554
1626
void Session::end_statement()
1555
1627
{
1556
1628
  /* Cleanup SQL processing state to reuse this statement in next query. */
1557
 
  lex->end();
1558
 
  query_cache_key= ""; // reset the cache key
1559
 
  resetResultsetMessage();
 
1629
  lex_end(lex);
1560
1630
}
1561
1631
 
1562
1632
bool Session::copy_db_to(char **p_db, size_t *p_db_length)
1563
1633
{
1564
 
  assert(_schema);
1565
 
  if (_schema and _schema->empty())
1566
 
  {
1567
 
    my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
1568
 
    return true;
1569
 
  }
1570
 
  else if (not _schema)
1571
 
  {
1572
 
    my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
1573
 
    return true;
1574
 
  }
1575
 
  assert(_schema);
1576
 
 
1577
 
  *p_db= strmake(_schema->c_str(), _schema->size());
1578
 
  *p_db_length= _schema->size();
1579
 
 
 
1634
  if (db == NULL)
 
1635
  {
 
1636
    my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
 
1637
    return true;
 
1638
  }
 
1639
  *p_db= strmake(db, db_length);
 
1640
  *p_db_length= db_length;
1580
1641
  return false;
1581
1642
}
1582
1643
 
1591
1652
  quick_group= 1;
1592
1653
  table_charset= 0;
1593
1654
  precomputed_group_by= 0;
 
1655
  bit_fields_as_long= 0;
1594
1656
}
1595
1657
 
1596
1658
void Tmp_Table_Param::cleanup(void)
1615
1677
  memset(&status_var, 0, sizeof(status_var));
1616
1678
}
1617
1679
 
1618
 
 
1619
 
void Session::set_db(const std::string &new_db)
 
1680
void Security_context::skip_grants()
 
1681
{
 
1682
  /* privileges for the user are unknown everything is allowed */
 
1683
}
 
1684
 
 
1685
 
 
1686
/****************************************************************************
 
1687
  Handling of open and locked tables states.
 
1688
 
 
1689
  This is used when we want to open/lock (and then close) some tables when
 
1690
  we already have a set of tables open and locked. We use these methods for
 
1691
  access to mysql.proc table to find definitions of stored routines.
 
1692
****************************************************************************/
 
1693
 
 
1694
void Session::reset_n_backup_open_tables_state(Open_tables_state *backup)
 
1695
{
 
1696
  backup->set_open_tables_state(this);
 
1697
  reset_open_tables_state();
 
1698
  backups_available= false;
 
1699
}
 
1700
 
 
1701
 
 
1702
void Session::restore_backup_open_tables_state(Open_tables_state *backup)
 
1703
{
 
1704
  /*
 
1705
    Before we will throw away current open tables state we want
 
1706
    to be sure that it was properly cleaned up.
 
1707
  */
 
1708
  assert(open_tables == 0 && temporary_tables == 0 &&
 
1709
              derived_tables == 0 &&
 
1710
              lock == 0);
 
1711
  set_open_tables_state(backup);
 
1712
}
 
1713
 
 
1714
 
 
1715
bool Session::set_db(const char *new_db, size_t new_db_len)
1620
1716
{
1621
1717
  /* Do not reallocate memory if current chunk is big enough. */
1622
 
  if (new_db.length())
1623
 
  {
1624
 
    _schema.reset(new std::string(new_db));
1625
 
  }
 
1718
  if (db && new_db && db_length >= new_db_len)
 
1719
    memcpy(db, new_db, new_db_len+1);
1626
1720
  else
1627
1721
  {
1628
 
    _schema.reset(new std::string(""));
 
1722
    if (db)
 
1723
      free(db);
 
1724
    if (new_db)
 
1725
    {
 
1726
      db= (char *)malloc(new_db_len + 1);
 
1727
      if (db != NULL)
 
1728
      {
 
1729
        memcpy(db, new_db, new_db_len);
 
1730
        db[new_db_len]= 0;
 
1731
      }
 
1732
    }
 
1733
    else
 
1734
      db= NULL;
1629
1735
  }
1630
 
}
1631
 
 
 
1736
  db_length= db ? new_db_len : 0;
 
1737
  return new_db && !db;
 
1738
}
 
1739
 
 
1740
 
 
1741
/**
 
1742
  Check the killed state of a user thread
 
1743
  @param session  user thread
 
1744
  @retval 0 the user thread is active
 
1745
  @retval 1 the user thread has been killed
 
1746
*/
 
1747
extern "C" int session_killed(const Session *session)
 
1748
{
 
1749
  return(session->killed);
 
1750
}
 
1751
 
 
1752
/**
 
1753
  Return the session id of a user session
 
1754
  @param pointer to Session object
 
1755
  @return session's id
 
1756
*/
 
1757
extern "C" unsigned long session_get_thread_id(const Session *session)
 
1758
{
 
1759
  return (unsigned long) session->getSessionId();
 
1760
}
 
1761
 
 
1762
 
 
1763
extern "C"
 
1764
LEX_STRING *session_make_lex_string(Session *session, LEX_STRING *lex_str,
 
1765
                                const char *str, unsigned int size,
 
1766
                                int allocate_lex_string)
 
1767
{
 
1768
  return session->make_lex_string(lex_str, str, size,
 
1769
                              (bool) allocate_lex_string);
 
1770
}
 
1771
 
 
1772
const struct charset_info_st *session_charset(Session *session)
 
1773
{
 
1774
  return(session->charset());
 
1775
}
 
1776
 
 
1777
char **session_query(Session *session)
 
1778
{
 
1779
  return(&session->query);
 
1780
}
 
1781
 
 
1782
int session_non_transactional_update(const Session *session)
 
1783
{
 
1784
  return(session->transaction.all.modified_non_trans_table);
 
1785
}
 
1786
 
 
1787
void session_mark_transaction_to_rollback(Session *session, bool all)
 
1788
{
 
1789
  mark_transaction_to_rollback(session, all);
 
1790
}
1632
1791
 
1633
1792
/**
1634
1793
  Mark transaction to rollback and mark error as fatal to a sub-statement.
1651
1810
  plugin_sessionvar_cleanup(this);
1652
1811
 
1653
1812
  /* If necessary, log any aborted or unauthorized connections */
1654
 
  if (getKilled() || client->wasAborted())
1655
 
  {
1656
 
    status_var.aborted_threads++;
1657
 
  }
 
1813
  if (killed || client->wasAborted())
 
1814
    statistic_increment(aborted_threads, &LOCK_status);
1658
1815
 
1659
1816
  if (client->wasAborted())
1660
1817
  {
1661
 
    if (not getKilled() && variables.log_warnings > 1)
 
1818
    if (! killed && variables.log_warnings > 1)
1662
1819
    {
1663
 
      SecurityContext *sctx= &security_ctx;
 
1820
      Security_context *sctx= &security_ctx;
1664
1821
 
1665
1822
      errmsg_printf(ERRMSG_LVL_WARN, ER(ER_NEW_ABORTING_CONNECTION)
1666
1823
                  , thread_id
1667
 
                  , (_schema->empty() ? "unconnected" : _schema->c_str())
1668
 
                  , sctx->getUser().empty() == false ? sctx->getUser().c_str() : "unauthenticated"
1669
 
                  , sctx->getIp().c_str()
 
1824
                  , (db ? db : "unconnected")
 
1825
                  , sctx->user.empty() == false ? sctx->user.c_str() : "unauthenticated"
 
1826
                  , sctx->ip.c_str()
1670
1827
                  , (main_da.is_error() ? main_da.message() : ER(ER_UNKNOWN_ERROR)));
1671
1828
    }
1672
1829
  }
1673
1830
 
1674
1831
  /* Close out our connection to the client */
1675
1832
  if (should_lock)
1676
 
    session::Cache::singleton().mutex().lock();
1677
 
 
1678
 
  setKilled(Session::KILL_CONNECTION);
1679
 
 
 
1833
    (void) pthread_mutex_lock(&LOCK_thread_count);
 
1834
  killed= Session::KILL_CONNECTION;
1680
1835
  if (client->isConnected())
1681
1836
  {
1682
1837
    if (errcode)
1686
1841
    }
1687
1842
    client->close();
1688
1843
  }
1689
 
 
1690
1844
  if (should_lock)
1691
 
  {
1692
 
    session::Cache::singleton().mutex().unlock();
1693
 
  }
 
1845
    (void) pthread_mutex_unlock(&LOCK_thread_count);
1694
1846
}
1695
1847
 
1696
1848
void Session::reset_for_next_command()
1707
1859
  server_status&= ~ (SERVER_MORE_RESULTS_EXISTS |
1708
1860
                          SERVER_QUERY_NO_INDEX_USED |
1709
1861
                          SERVER_QUERY_NO_GOOD_INDEX_USED);
 
1862
  /*
 
1863
    If in autocommit mode and not in a transaction, reset
 
1864
    OPTION_STATUS_NO_TRANS_UPDATE to not get warnings
 
1865
    in ha_rollback_trans() about some tables couldn't be rolled back.
 
1866
  */
 
1867
  if (!(options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
 
1868
  {
 
1869
    transaction.all.modified_non_trans_table= false;
 
1870
  }
1710
1871
 
1711
1872
  clear_error();
1712
1873
  main_da.reset_diagnostics_area();
1718
1879
  Close all temporary tables created by 'CREATE TEMPORARY TABLE' for thread
1719
1880
*/
1720
1881
 
1721
 
void Open_tables_state::close_temporary_tables()
 
1882
void Session::close_temporary_tables()
1722
1883
{
1723
1884
  Table *table;
1724
1885
  Table *tmp_next;
1725
1886
 
1726
 
  if (not temporary_tables)
 
1887
  if (!temporary_tables)
1727
1888
    return;
1728
1889
 
1729
1890
  for (table= temporary_tables; table; table= tmp_next)
1730
1891
  {
1731
 
    tmp_next= table->getNext();
1732
 
    nukeTable(table);
 
1892
    tmp_next= table->next;
 
1893
    close_temporary(table, true, true);
1733
1894
  }
1734
1895
  temporary_tables= NULL;
1735
1896
}
1738
1899
  unlink from session->temporary tables and close temporary table
1739
1900
*/
1740
1901
 
1741
 
void Open_tables_state::close_temporary_table(Table *table)
 
1902
void Session::close_temporary_table(Table *table,
 
1903
                                    bool free_share, bool delete_table)
1742
1904
{
1743
 
  if (table->getPrev())
 
1905
  if (table->prev)
1744
1906
  {
1745
 
    table->getPrev()->setNext(table->getNext());
1746
 
    if (table->getPrev()->getNext())
1747
 
    {
1748
 
      table->getNext()->setPrev(table->getPrev());
1749
 
    }
 
1907
    table->prev->next= table->next;
 
1908
    if (table->prev->next)
 
1909
      table->next->prev= table->prev;
1750
1910
  }
1751
1911
  else
1752
1912
  {
1757
1917
      passing non-zero value to end_slave via rli->save_temporary_tables
1758
1918
      when no temp tables opened, see an invariant below.
1759
1919
    */
1760
 
    temporary_tables= table->getNext();
 
1920
    temporary_tables= table->next;
1761
1921
    if (temporary_tables)
1762
 
    {
1763
 
      table->getNext()->setPrev(NULL);
1764
 
    }
 
1922
      table->next->prev= NULL;
1765
1923
  }
1766
 
  nukeTable(table);
 
1924
  close_temporary(table, free_share, delete_table);
1767
1925
}
1768
1926
 
1769
1927
/*
1770
 
  Close and drop a temporary table
 
1928
  Close and delete a temporary table
1771
1929
 
1772
1930
  NOTE
1773
1931
  This dosn't unlink table from session->temporary
1774
1932
  If this is needed, use close_temporary_table()
1775
1933
*/
1776
1934
 
1777
 
void Open_tables_state::nukeTable(Table *table)
 
1935
void Session::close_temporary(Table *table, bool free_share, bool delete_table)
1778
1936
{
1779
 
  plugin::StorageEngine *table_type= table->getShare()->db_type();
 
1937
  plugin::StorageEngine *table_type= table->s->db_type();
1780
1938
 
1781
1939
  table->free_io_cache();
1782
 
  table->delete_table();
1783
 
 
1784
 
  TableIdentifier identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName(), table->getShare()->getPath());
1785
 
  rm_temporary_table(table_type, identifier);
1786
 
 
1787
 
  delete table->getMutableShare();
1788
 
 
1789
 
  /* This makes me sad, but we're allocating it via malloc */
1790
 
  delete table;
 
1940
  table->closefrm(false);
 
1941
 
 
1942
  if (delete_table)
 
1943
    rm_temporary_table(table_type, table->s->path.str);
 
1944
 
 
1945
  if (free_share)
 
1946
  {
 
1947
    table->s->free_table_share();
 
1948
    /* This makes me sad, but we're allocating it via malloc */
 
1949
    free(table);
 
1950
  }
1791
1951
}
1792
1952
 
1793
1953
/** Clear most status variables. */
1794
1954
extern time_t flush_status_time;
 
1955
extern uint32_t max_used_connections;
1795
1956
 
1796
1957
void Session::refresh_status()
1797
1958
{
 
1959
  pthread_mutex_lock(&LOCK_status);
 
1960
 
 
1961
  /* Add thread's status variabes to global status */
 
1962
  add_to_status(&global_status_var, &status_var);
 
1963
 
1798
1964
  /* Reset thread's status variables */
1799
1965
  memset(&status_var, 0, sizeof(status_var));
1800
1966
 
 
1967
  /* Reset some global variables */
 
1968
  reset_status_vars();
 
1969
 
 
1970
  /* Reset the counters of all key caches (default and named). */
 
1971
  reset_key_cache_counters();
1801
1972
  flush_status_time= time((time_t*) 0);
1802
 
  current_global_counters.max_used_connections= 1; /* We set it to one, because we know we exist */
1803
 
  current_global_counters.connections= 0;
 
1973
  max_used_connections= 1; /* We set it to one, because we know we exist */
 
1974
  pthread_mutex_unlock(&LOCK_status);
1804
1975
}
1805
1976
 
1806
1977
user_var_entry *Session::getVariable(LEX_STRING &name, bool create_if_not_exists)
1807
1978
{
1808
 
  return getVariable(std::string(name.str, name.length), create_if_not_exists);
1809
 
}
1810
 
 
1811
 
user_var_entry *Session::getVariable(const std::string  &name, bool create_if_not_exists)
1812
 
{
1813
 
  UserVarsRange ppp= user_vars.equal_range(name);
1814
 
 
1815
 
  for (UserVars::iterator iter= ppp.first;
1816
 
       iter != ppp.second; ++iter)
1817
 
  {
1818
 
    return (*iter).second;
1819
 
  }
1820
 
 
1821
 
  if (not create_if_not_exists)
1822
 
    return NULL;
1823
 
 
1824
1979
  user_var_entry *entry= NULL;
1825
 
  entry= new (nothrow) user_var_entry(name.c_str(), query_id);
1826
 
 
1827
 
  if (entry == NULL)
1828
 
    return NULL;
1829
 
 
1830
 
  std::pair<UserVars::iterator, bool> returnable= user_vars.insert(make_pair(name, entry));
1831
 
 
1832
 
  if (not returnable.second)
 
1980
 
 
1981
  entry= (user_var_entry*) hash_search(&user_vars, (unsigned char*) name.str, name.length);
 
1982
 
 
1983
  if ((entry == NULL) && create_if_not_exists)
1833
1984
  {
1834
 
    delete entry;
 
1985
    if (!hash_inited(&user_vars))
 
1986
      return NULL;
 
1987
    entry= new (nothrow) user_var_entry(name.str, query_id);
 
1988
 
 
1989
    if (entry == NULL)
 
1990
      return NULL;
 
1991
 
 
1992
    if (my_hash_insert(&user_vars, (unsigned char*) entry))
 
1993
    {
 
1994
      assert(1);
 
1995
      free((char*) entry);
 
1996
      return 0;
 
1997
    }
 
1998
 
1835
1999
  }
1836
2000
 
1837
2001
  return entry;
1838
2002
}
1839
2003
 
1840
 
void Session::setVariable(const std::string &name, const std::string &value)
1841
 
{
1842
 
  user_var_entry *updateable_var= getVariable(name.c_str(), true);
1843
 
 
1844
 
  updateable_var->update_hash(false,
1845
 
                              (void*)value.c_str(),
1846
 
                              static_cast<uint32_t>(value.length()), STRING_RESULT,
1847
 
                              &my_charset_bin,
1848
 
                              DERIVATION_IMPLICIT, false);
1849
 
}
1850
 
 
1851
 
void Open_tables_state::mark_temp_tables_as_free_for_reuse()
1852
 
{
1853
 
  for (Table *table= temporary_tables ; table ; table= table->getNext())
 
2004
void Session::mark_temp_tables_as_free_for_reuse()
 
2005
{
 
2006
  for (Table *table= temporary_tables ; table ; table= table->next)
1854
2007
  {
1855
 
    if (table->query_id == getQueryId())
 
2008
    if (table->query_id == query_id)
1856
2009
    {
1857
2010
      table->query_id= 0;
1858
2011
      table->cursor->ha_reset();
1862
2015
 
1863
2016
void Session::mark_used_tables_as_free_for_reuse(Table *table)
1864
2017
{
1865
 
  for (; table ; table= table->getNext())
 
2018
  for (; table ; table= table->next)
1866
2019
  {
1867
 
    if (table->query_id == getQueryId())
 
2020
    if (table->query_id == query_id)
1868
2021
    {
1869
2022
      table->query_id= 0;
1870
2023
      table->cursor->ha_reset();
1883
2036
*/
1884
2037
void Session::close_thread_tables()
1885
2038
{
1886
 
  clearDerivedTables();
 
2039
  Table *table;
 
2040
 
 
2041
  /*
 
2042
    We are assuming here that session->derived_tables contains ONLY derived
 
2043
    tables for this substatement. i.e. instead of approach which uses
 
2044
    query_id matching for determining which of the derived tables belong
 
2045
    to this substatement we rely on the ability of substatements to
 
2046
    save/restore session->derived_tables during their execution.
 
2047
 
 
2048
    TODO: Probably even better approach is to simply associate list of
 
2049
          derived tables with (sub-)statement instead of thread and destroy
 
2050
          them at the end of its execution.
 
2051
  */
 
2052
  if (derived_tables)
 
2053
  {
 
2054
    Table *next;
 
2055
    /*
 
2056
      Close all derived tables generated in queries like
 
2057
      SELECT * FROM (SELECT * FROM t1)
 
2058
    */
 
2059
    for (table= derived_tables ; table ; table= next)
 
2060
    {
 
2061
      next= table->next;
 
2062
      table->free_tmp_table(this);
 
2063
    }
 
2064
    derived_tables= 0;
 
2065
  }
1887
2066
 
1888
2067
  /*
1889
2068
    Mark all temporary tables used by this statement as free for reuse.
1897
2076
    does not belong to statement for which we do close_thread_tables()).
1898
2077
    TODO: This should be fixed in later releases.
1899
2078
   */
 
2079
  if (backups_available == false)
1900
2080
  {
1901
 
    TransactionServices &transaction_services= TransactionServices::singleton();
1902
2081
    main_da.can_overwrite_status= true;
1903
 
    transaction_services.autocommitOrRollback(this, is_error());
 
2082
    ha_autocommit_or_rollback(this, is_error());
1904
2083
    main_da.can_overwrite_status= false;
1905
2084
    transaction.stmt.reset();
1906
2085
  }
1916
2095
      handled either before writing a query log event (inside
1917
2096
      binlog_query()) or when preparing a pending event.
1918
2097
     */
1919
 
    unlockTables(lock);
 
2098
    mysql_unlock_tables(this, lock);
1920
2099
    lock= 0;
1921
2100
  }
1922
2101
  /*
1923
 
    Note that we need to hold table::Cache::singleton().mutex() while changing the
 
2102
    Note that we need to hold LOCK_open while changing the
1924
2103
    open_tables list. Another thread may work on it.
1925
 
    (See: table::Cache::singleton().removeTable(), mysql_wait_completed_table())
 
2104
    (See: remove_table_from_cache(), mysql_wait_completed_table())
1926
2105
    Closing a MERGE child before the parent would be fatal if the
1927
2106
    other thread tries to abort the MERGE lock in between.
1928
2107
  */
1954
2133
    if (open_tables_from_list(&tables, &counter))
1955
2134
      return true;
1956
2135
 
1957
 
    if (not lock_tables(tables, counter, &need_reopen))
 
2136
    if (!lock_tables(tables, counter, &need_reopen))
1958
2137
      break;
1959
 
    if (not need_reopen)
 
2138
    if (!need_reopen)
1960
2139
      return true;
1961
2140
    close_tables_for_reopen(&tables);
1962
2141
  }
1963
2142
  if ((mysql_handle_derived(lex, &mysql_derived_prepare) ||
1964
 
       (
 
2143
       (fill_derived_tables() &&
1965
2144
        mysql_handle_derived(lex, &mysql_derived_filling))))
1966
2145
    return true;
1967
2146
 
1968
2147
  return false;
1969
2148
}
1970
2149
 
1971
 
/*
1972
 
  @note "best_effort" is used in cases were if a failure occurred on this
1973
 
  operation it would not be surprising because we are only removing because there
1974
 
  might be an issue (lame engines).
1975
 
*/
1976
 
 
1977
 
bool Open_tables_state::rm_temporary_table(const TableIdentifier &identifier, bool best_effort)
 
2150
bool Session::openTables(TableList *tables, uint32_t flags)
1978
2151
{
1979
 
  if (plugin::StorageEngine::dropTable(*static_cast<Session *>(this), identifier))
1980
 
  {
1981
 
    if (not best_effort)
1982
 
    {
1983
 
      std::string path;
1984
 
      identifier.getSQLPath(path);
1985
 
      errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
1986
 
                    path.c_str(), errno);
1987
 
    }
1988
 
 
 
2152
  uint32_t counter;
 
2153
  bool ret= fill_derived_tables();
 
2154
  assert(ret == false);
 
2155
  if (open_tables_from_list(&tables, &counter, flags) ||
 
2156
      mysql_handle_derived(lex, &mysql_derived_prepare))
1989
2157
    return true;
1990
 
  }
1991
 
 
1992
2158
  return false;
1993
2159
}
1994
2160
 
1995
 
bool Open_tables_state::rm_temporary_table(plugin::StorageEngine *base, const TableIdentifier &identifier)
 
2161
bool Session::rm_temporary_table(plugin::StorageEngine *base, char *path)
1996
2162
{
 
2163
  bool error=0;
 
2164
 
1997
2165
  assert(base);
1998
2166
 
1999
 
  if (plugin::StorageEngine::dropTable(*static_cast<Session *>(this), *base, identifier))
 
2167
  if (delete_table_proto_file(path))
 
2168
    error=1;
 
2169
 
 
2170
  if (base->doDropTable(*this, path))
2000
2171
  {
2001
 
    std::string path;
2002
 
    identifier.getSQLPath(path);
 
2172
    error=1;
2003
2173
    errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
2004
 
                  path.c_str(), errno);
2005
 
 
2006
 
    return true;
2007
 
  }
2008
 
 
2009
 
  return false;
2010
 
}
2011
 
 
2012
 
/**
2013
 
  @note this will be removed, I am looking through Hudson to see if it is finding
2014
 
  any tables that are missed during cleanup.
2015
 
*/
2016
 
void Open_tables_state::dumpTemporaryTableNames(const char *foo)
2017
 
{
2018
 
  Table *table;
2019
 
 
2020
 
  if (not temporary_tables)
2021
 
    return;
2022
 
 
2023
 
  cerr << "Begin Run: " << foo << "\n";
2024
 
  for (table= temporary_tables; table; table= table->getNext())
2025
 
  {
2026
 
    bool have_proto= false;
2027
 
 
2028
 
    message::Table *proto= table->getShare()->getTableProto();
2029
 
    if (table->getShare()->getTableProto())
2030
 
      have_proto= true;
2031
 
 
2032
 
    const char *answer= have_proto ? "true" : "false";
2033
 
 
2034
 
    if (have_proto)
2035
 
    {
2036
 
      cerr << "\tTable Name " << table->getShare()->getSchemaName() << "." << table->getShare()->getTableName() << " : " << answer << "\n";
2037
 
      cerr << "\t\t Proto " << proto->schema() << " " << proto->name() << "\n";
2038
 
    }
2039
 
    else
2040
 
    {
2041
 
      cerr << "\tTabl;e Name " << table->getShare()->getSchemaName() << "." << table->getShare()->getTableName() << " : " << answer << "\n";
2042
 
    }
2043
 
  }
2044
 
}
2045
 
 
2046
 
bool Session::TableMessages::storeTableMessage(const TableIdentifier &identifier, message::Table &table_message)
2047
 
{
2048
 
  table_message_cache.insert(make_pair(identifier.getPath(), table_message));
2049
 
 
2050
 
  return true;
2051
 
}
2052
 
 
2053
 
bool Session::TableMessages::removeTableMessage(const TableIdentifier &identifier)
2054
 
{
2055
 
  TableMessageCache::iterator iter;
2056
 
 
2057
 
  iter= table_message_cache.find(identifier.getPath());
2058
 
 
2059
 
  if (iter == table_message_cache.end())
2060
 
    return false;
2061
 
 
2062
 
  table_message_cache.erase(iter);
2063
 
 
2064
 
  return true;
2065
 
}
2066
 
 
2067
 
bool Session::TableMessages::getTableMessage(const TableIdentifier &identifier, message::Table &table_message)
2068
 
{
2069
 
  TableMessageCache::iterator iter;
2070
 
 
2071
 
  iter= table_message_cache.find(identifier.getPath());
2072
 
 
2073
 
  if (iter == table_message_cache.end())
2074
 
    return false;
2075
 
 
2076
 
  table_message.CopyFrom(((*iter).second));
2077
 
 
2078
 
  return true;
2079
 
}
2080
 
 
2081
 
bool Session::TableMessages::doesTableMessageExist(const TableIdentifier &identifier)
2082
 
{
2083
 
  TableMessageCache::iterator iter;
2084
 
 
2085
 
  iter= table_message_cache.find(identifier.getPath());
2086
 
 
2087
 
  if (iter == table_message_cache.end())
2088
 
  {
2089
 
    return false;
2090
 
  }
2091
 
 
2092
 
  return true;
2093
 
}
2094
 
 
2095
 
bool Session::TableMessages::renameTableMessage(const TableIdentifier &from, const TableIdentifier &to)
2096
 
{
2097
 
  TableMessageCache::iterator iter;
2098
 
 
2099
 
  table_message_cache[to.getPath()]= table_message_cache[from.getPath()];
2100
 
 
2101
 
  iter= table_message_cache.find(to.getPath());
2102
 
 
2103
 
  if (iter == table_message_cache.end())
2104
 
  {
2105
 
    return false;
2106
 
  }
2107
 
 
2108
 
  (*iter).second.set_schema(to.getSchemaName());
2109
 
  (*iter).second.set_name(to.getTableName());
2110
 
 
2111
 
  return true;
2112
 
}
2113
 
 
2114
 
table::Instance *Session::getInstanceTable()
2115
 
{
2116
 
  temporary_shares.push_back(new table::Instance()); // This will not go into the tableshare cache, so no key is used.
2117
 
 
2118
 
  table::Instance *tmp_share= temporary_shares.back();
2119
 
 
2120
 
  assert(tmp_share);
2121
 
 
2122
 
  return tmp_share;
2123
 
}
2124
 
 
2125
 
 
2126
 
/**
2127
 
  Create a reduced Table object with properly set up Field list from a
2128
 
  list of field definitions.
2129
 
 
2130
 
    The created table doesn't have a table Cursor associated with
2131
 
    it, has no keys, no group/distinct, no copy_funcs array.
2132
 
    The sole purpose of this Table object is to use the power of Field
2133
 
    class to read/write data to/from table->getInsertRecord(). Then one can store
2134
 
    the record in any container (RB tree, hash, etc).
2135
 
    The table is created in Session mem_root, so are the table's fields.
2136
 
    Consequently, if you don't BLOB fields, you don't need to free it.
2137
 
 
2138
 
  @param session         connection handle
2139
 
  @param field_list  list of column definitions
2140
 
 
2141
 
  @return
2142
 
    0 if out of memory, Table object in case of success
2143
 
*/
2144
 
table::Instance *Session::getInstanceTable(List<CreateField> &field_list)
2145
 
{
2146
 
  temporary_shares.push_back(new table::Instance(this, field_list)); // This will not go into the tableshare cache, so no key is used.
2147
 
 
2148
 
  table::Instance *tmp_share= temporary_shares.back();
2149
 
 
2150
 
  assert(tmp_share);
2151
 
 
2152
 
  return tmp_share;
2153
 
}
2154
 
 
2155
 
namespace display  {
2156
 
 
2157
 
static const std::string NONE= "NONE";
2158
 
static const std::string GOT_GLOBAL_READ_LOCK= "HAS GLOBAL READ LOCK";
2159
 
static const std::string MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT= "HAS GLOBAL READ LOCK WITH BLOCKING COMMIT";
2160
 
 
2161
 
const std::string &type(drizzled::Session::global_read_lock_t type)
2162
 
{
2163
 
  switch (type) {
2164
 
    default:
2165
 
    case Session::NONE:
2166
 
      return NONE;
2167
 
    case Session::GOT_GLOBAL_READ_LOCK:
2168
 
      return GOT_GLOBAL_READ_LOCK;
2169
 
    case Session::MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT:
2170
 
      return MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT;
2171
 
  }
2172
 
}
2173
 
 
2174
 
size_t max_string_length(drizzled::Session::global_read_lock_t)
2175
 
{
2176
 
  return MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT.size();
2177
 
}
2178
 
 
2179
 
} /* namespace display */
2180
 
 
2181
 
} /* namespace drizzled */
 
2174
                  path, my_errno);
 
2175
  }
 
2176
  return(error);
 
2177
}
 
2178
 
 
2179