~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/session.cc

  • Committer: Jay Pipes
  • Date: 2009-09-15 21:01:42 UTC
  • mto: (1126.2.5 merge)
  • mto: This revision was merged to the branch mainline in revision 1128.
  • Revision ID: jpipes@serialcoder-20090915210142-x8mwiqn1q0vzjspp
Moves Alter_info out into its own header and source file, cleans up some related include mess in sql_lex.h, and renames Alter_info to AlterInfo.

Show diffs side-by-side

added added

removed removed

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