~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/session.cc

  • Committer: Patrick Galbraith
  • Date: 2009-10-08 22:42:05 UTC
  • mto: (1166.5.3 memcached_functions)
  • mto: This revision was merged to the branch mainline in revision 1189.
  • Revision ID: patg@patrick-galbraiths-macbook-pro.local-20091008224205-gq1pehjsivvx0qo9
Starting over with a fresh tree, moved in memcached functions.

Memcached Functions for Drizzle. 

All tests pass.

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