~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/session.cc

  • Committer: Stewart Smith
  • Date: 2009-06-16 03:02:59 UTC
  • mto: This revision was merged to the branch mainline in revision 1065.
  • Revision ID: stewart@flamingspork.com-20090616030259-tn2thqrajk6cappd
ER_NISAMCHK is unused, mark it as so. Thanks to Paul DuBois for researching this for MySQL.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2000-2006 MySQL AB
2
 
 
3
 
   This program is free software; you can redistribute it and/or modify
4
 
   it under the terms of the GNU General Public License as published by
5
 
   the Free Software Foundation; version 2 of the License.
6
 
 
7
 
   This program is distributed in the hope that it will be useful,
8
 
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
 
   GNU General Public License for more details.
11
 
 
12
 
   You should have received a copy of the GNU General Public License
13
 
   along with this program; if not, write to the Free Software
14
 
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
 
 
16
 
 
17
 
/*****************************************************************************
18
 
**
19
 
** This file implements classes defined in sql_class.h
20
 
** Especially the classes to handle a result from a select
21
 
**
22
 
*****************************************************************************/
 
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
 
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
 
3
 *
 
4
 *  Copyright (C) 2008 Sun Microsystems
 
5
 *
 
6
 *  This program is free software; you can redistribute it and/or modify
 
7
 *  it under the terms of the GNU General Public License as published by
 
8
 *  the Free Software Foundation; version 2 of the License.
 
9
 *
 
10
 *  This program is distributed in the hope that it will be useful,
 
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 *  GNU General Public License for more details.
 
14
 *
 
15
 *  You should have received a copy of the GNU General Public License
 
16
 *  along with this program; if not, write to the Free Software
 
17
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
18
 */
 
19
 
 
20
/**
 
21
 * @file Implementation of the Session class and API
 
22
 */
 
23
 
23
24
#include <drizzled/server_includes.h>
24
 
#include "rpl_rli.h"
25
 
#include "rpl_record.h"
26
 
#include "log_event.h"
 
25
#include <drizzled/session.h>
27
26
#include <sys/stat.h>
28
 
#include <mysys/thr_alarm.h>
29
27
#include <mysys/mysys_err.h>
30
 
#include <drizzled/drizzled_error_messages.h>
 
28
#include <drizzled/error.h>
 
29
#include <drizzled/query_id.h>
 
30
#include <drizzled/data_home.h>
 
31
#include <drizzled/sql_base.h>
 
32
#include <drizzled/lock.h>
 
33
#include <drizzled/item/cache.h>
 
34
#include <drizzled/item/float.h>
 
35
#include <drizzled/item/return_int.h>
 
36
#include <drizzled/item/empty_string.h>
 
37
#include <drizzled/show.h>
 
38
#include <drizzled/scheduling.h>
31
39
 
32
40
/*
33
41
  The following is used to initialise Table_ident with a internal
36
44
char internal_table_name[2]= "*";
37
45
char empty_c_string[1]= {0};    /* used for not defined db */
38
46
 
39
 
const char * const THD::DEFAULT_WHERE= "field list";
40
 
 
41
 
 
42
 
/*****************************************************************************
43
 
** Instansiate templates
44
 
*****************************************************************************/
 
47
const char * const Session::DEFAULT_WHERE= "field list";
 
48
extern pthread_key_t THR_Session;
 
49
extern pthread_key_t THR_Mem_root;
45
50
 
46
51
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
47
52
/* Used templates */
58
63
/****************************************************************************
59
64
** User variables
60
65
****************************************************************************/
61
 
 
62
66
extern "C" unsigned char *get_var_key(user_var_entry *entry, size_t *length,
63
 
                              bool not_used __attribute__((unused)))
 
67
                              bool )
64
68
{
65
69
  *length= entry->name.length;
66
70
  return (unsigned char*) entry->name.str;
81
85
         !strcmp(field_name.str, other.field_name.str);
82
86
}
83
87
 
84
 
/**
85
 
  Construct an (almost) deep copy of this key. Only those
86
 
  elements that are known to never change are not copied.
87
 
  If out of memory, a partial copy is returned and an error is set
88
 
  in THD.
89
 
*/
90
 
 
91
 
Key::Key(const Key &rhs, MEM_ROOT *mem_root)
92
 
  :type(rhs.type),
93
 
  key_create_info(rhs.key_create_info),
94
 
  columns(rhs.columns, mem_root),
95
 
  name(rhs.name),
96
 
  generated(rhs.generated)
97
 
{
98
 
  list_copy_and_replace_each_value(columns, mem_root);
99
 
}
100
 
 
101
 
/**
102
 
  Construct an (almost) deep copy of this foreign key. Only those
103
 
  elements that are known to never change are not copied.
104
 
  If out of memory, a partial copy is returned and an error is set
105
 
  in THD.
106
 
*/
107
 
 
108
 
Foreign_key::Foreign_key(const Foreign_key &rhs, MEM_ROOT *mem_root)
109
 
  :Key(rhs),
110
 
  ref_table(rhs.ref_table),
111
 
  ref_columns(rhs.ref_columns),
112
 
  delete_opt(rhs.delete_opt),
113
 
  update_opt(rhs.update_opt),
114
 
  match_opt(rhs.match_opt)
115
 
{
116
 
  list_copy_and_replace_each_value(ref_columns, mem_root);
117
 
}
118
 
 
119
 
/*
120
 
  Test if a foreign key (= generated key) is a prefix of the given key
121
 
  (ignoring key name, key type and order of columns)
122
 
 
123
 
  NOTES:
124
 
    This is only used to test if an index for a FOREIGN KEY exists
125
 
 
126
 
  IMPLEMENTATION
127
 
    We only compare field names
128
 
 
129
 
  RETURN
130
 
    0   Generated key is a prefix of other key
131
 
    1   Not equal
132
 
*/
133
 
 
134
 
bool foreign_key_prefix(Key *a, Key *b)
135
 
{
136
 
  /* Ensure that 'a' is the generated key */
137
 
  if (a->generated)
138
 
  {
139
 
    if (b->generated && a->columns.elements > b->columns.elements)
140
 
      std::swap(a, b);                       // Put shorter key in 'a'
141
 
  }
142
 
  else
143
 
  {
144
 
    if (!b->generated)
145
 
      return true;                              // No foreign key
146
 
    std::swap(a, b);                       // Put generated key in 'a'
147
 
  }
148
 
 
149
 
  /* Test if 'a' is a prefix of 'b' */
150
 
  if (a->columns.elements > b->columns.elements)
151
 
    return true;                                // Can't be prefix
152
 
 
153
 
  List_iterator<Key_part_spec> col_it1(a->columns);
154
 
  List_iterator<Key_part_spec> col_it2(b->columns);
155
 
  const Key_part_spec *col1, *col2;
156
 
 
157
 
#ifdef ENABLE_WHEN_INNODB_CAN_HANDLE_SWAPED_FOREIGN_KEY_COLUMNS
158
 
  while ((col1= col_it1++))
159
 
  {
160
 
    bool found= 0;
161
 
    col_it2.rewind();
162
 
    while ((col2= col_it2++))
163
 
    {
164
 
      if (*col1 == *col2)
165
 
      {
166
 
        found= true;
167
 
        break;
168
 
      }
169
 
    }
170
 
    if (!found)
171
 
      return true;                              // Error
172
 
  }
173
 
  return false;                                 // Is prefix
174
 
#else
175
 
  while ((col1= col_it1++))
176
 
  {
177
 
    col2= col_it2++;
178
 
    if (!(*col1 == *col2))
179
 
      return true;
180
 
  }
181
 
  return false;                                 // Is prefix
182
 
#endif
183
 
}
184
 
 
185
 
 
186
 
/****************************************************************************
187
 
** Thread specific functions
188
 
****************************************************************************/
189
 
 
190
88
Open_tables_state::Open_tables_state(ulong version_arg)
191
89
  :version(version_arg), state_flags(0U)
192
90
{
196
94
/*
197
95
  The following functions form part of the C plugin API
198
96
*/
199
 
 
200
97
extern "C" int mysql_tmpfile(const char *prefix)
201
98
{
202
99
  char filename[FN_REFLEN];
203
 
  File fd = create_temp_file(filename, mysql_tmpdir, prefix,
204
 
                             O_CREAT | O_EXCL | O_RDWR | O_TEMPORARY,
205
 
                             MYF(MY_WME));
 
100
  File fd = create_temp_file(filename, drizzle_tmpdir, prefix, MYF(MY_WME));
206
101
  if (fd >= 0) {
207
 
    /*
208
 
      This can be removed once the following bug is fixed:
209
 
      Bug #28903  create_temp_file() doesn't honor O_TEMPORARY option
210
 
                  (file not removed) (Unix)
211
 
    */
212
102
    unlink(filename);
213
103
  }
214
104
 
215
105
  return fd;
216
106
}
217
107
 
218
 
 
219
 
extern "C"
220
 
int thd_in_lock_tables(const THD *thd)
221
 
{
222
 
  return test(thd->in_lock_tables);
223
 
}
224
 
 
225
 
 
226
 
extern "C"
227
 
int thd_tablespace_op(const THD *thd)
228
 
{
229
 
  return test(thd->tablespace_op);
230
 
}
231
 
 
232
 
 
233
 
extern "C"
234
 
const char *set_thd_proc_info(THD *thd, const char *info,
235
 
                              const char *calling_function __attribute__((unused)),
236
 
                              const char *calling_file __attribute__((unused)),
237
 
                              const unsigned int calling_line __attribute__((unused)))
238
 
{
239
 
  const char *old_info= thd->get_proc_info();
240
 
  thd->set_proc_info(info);
241
 
  return old_info;
242
 
}
243
 
 
244
 
extern "C"
245
 
void **thd_ha_data(const THD *thd, const struct handlerton *hton)
246
 
{
247
 
  return (void **) &thd->ha_data[hton->slot].ha_ptr;
248
 
}
249
 
 
250
 
extern "C"
251
 
int64_t thd_test_options(const THD *thd, int64_t test_options)
252
 
{
253
 
  return thd->options & test_options;
254
 
}
255
 
 
256
 
extern "C"
257
 
int thd_sql_command(const THD *thd)
258
 
{
259
 
  return (int) thd->lex->sql_command;
260
 
}
261
 
 
262
 
extern "C"
263
 
int thd_tx_isolation(const THD *thd)
264
 
{
265
 
  return (int) thd->variables.tx_isolation;
266
 
}
267
 
 
268
 
extern "C"
269
 
void thd_inc_row_count(THD *thd)
270
 
{
271
 
  thd->row_count++;
272
 
}
273
 
 
274
 
/**
275
 
  Clear this diagnostics area. 
276
 
 
277
 
  Normally called at the end of a statement.
278
 
*/
279
 
 
280
 
void
281
 
Diagnostics_area::reset_diagnostics_area()
282
 
{
283
 
  can_overwrite_status= false;
284
 
  /** Don't take chances in production */
285
 
  m_message[0]= '\0';
286
 
  m_sql_errno= 0;
287
 
  m_server_status= 0;
288
 
  m_affected_rows= 0;
289
 
  m_last_insert_id= 0;
290
 
  m_total_warn_count= 0;
291
 
  is_sent= false;
292
 
  /** Tiny reset in debug mode to see garbage right away */
293
 
  m_status= DA_EMPTY;
294
 
}
295
 
 
296
 
 
297
 
/**
298
 
  Set OK status -- ends commands that do not return a
299
 
  result set, e.g. INSERT/UPDATE/DELETE.
300
 
*/
301
 
 
302
 
void
303
 
Diagnostics_area::set_ok_status(THD *thd, ha_rows affected_rows_arg,
304
 
                                uint64_t last_insert_id_arg,
305
 
                                const char *message_arg)
306
 
{
307
 
  assert(! is_set());
308
 
  /*
309
 
    In production, refuse to overwrite an error or a custom response
310
 
    with an OK packet.
311
 
  */
312
 
  if (is_error() || is_disabled())
313
 
    return;
314
 
  /** Only allowed to report success if has not yet reported an error */
315
 
 
316
 
  m_server_status= thd->server_status;
317
 
  m_total_warn_count= thd->total_warn_count;
318
 
  m_affected_rows= affected_rows_arg;
319
 
  m_last_insert_id= last_insert_id_arg;
320
 
  if (message_arg)
321
 
    strmake(m_message, message_arg, sizeof(m_message) - 1);
322
 
  else
323
 
    m_message[0]= '\0';
324
 
  m_status= DA_OK;
325
 
}
326
 
 
327
 
 
328
 
/**
329
 
  Set EOF status.
330
 
*/
331
 
 
332
 
void
333
 
Diagnostics_area::set_eof_status(THD *thd)
334
 
{
335
 
  /** Only allowed to report eof if has not yet reported an error */
336
 
 
337
 
  assert(! is_set());
338
 
  /*
339
 
    In production, refuse to overwrite an error or a custom response
340
 
    with an EOF packet.
341
 
  */
342
 
  if (is_error() || is_disabled())
343
 
    return;
344
 
 
345
 
  m_server_status= thd->server_status;
346
 
  /*
347
 
    If inside a stored procedure, do not return the total
348
 
    number of warnings, since they are not available to the client
349
 
    anyway.
350
 
  */
351
 
  m_total_warn_count= thd->total_warn_count;
352
 
 
353
 
  m_status= DA_EOF;
354
 
}
355
 
 
356
 
/**
357
 
  Set ERROR status.
358
 
*/
359
 
 
360
 
void
361
 
Diagnostics_area::set_error_status(THD *thd __attribute__((unused)),
362
 
                                   uint32_t sql_errno_arg,
363
 
                                   const char *message_arg)
364
 
{
365
 
  /*
366
 
    Only allowed to report error if has not yet reported a success
367
 
    The only exception is when we flush the message to the client,
368
 
    an error can happen during the flush.
369
 
  */
370
 
  assert(! is_set() || can_overwrite_status);
371
 
  /*
372
 
    In production, refuse to overwrite a custom response with an
373
 
    ERROR packet.
374
 
  */
375
 
  if (is_disabled())
376
 
    return;
377
 
 
378
 
  m_sql_errno= sql_errno_arg;
379
 
  strmake(m_message, message_arg, sizeof(m_message) - 1);
380
 
 
381
 
  m_status= DA_ERROR;
382
 
}
383
 
 
384
 
 
385
 
/**
386
 
  Mark the diagnostics area as 'DISABLED'.
387
 
 
388
 
  This is used in rare cases when the COM_ command at hand sends a response
389
 
  in a custom format. One example is the query cache, another is
390
 
  COM_STMT_PREPARE.
391
 
*/
392
 
 
393
 
void
394
 
Diagnostics_area::disable_status()
395
 
{
396
 
  assert(! is_set());
397
 
  m_status= DA_DISABLED;
398
 
}
399
 
 
400
 
 
401
 
THD::THD()
402
 
   :Statement(&main_lex, &main_mem_root,
403
 
              /* statement id */ 0),
404
 
   Open_tables_state(refresh_version), rli_fake(0),
405
 
   lock_id(&main_lock_id),
406
 
   user_time(0), in_sub_stmt(0),
407
 
   binlog_table_maps(0), binlog_flags(0UL),
408
 
   arg_of_last_insert_id_function(false),
409
 
   first_successful_insert_id_in_prev_stmt(0),
410
 
   first_successful_insert_id_in_prev_stmt_for_binlog(0),
411
 
   first_successful_insert_id_in_cur_stmt(0),
412
 
   stmt_depends_on_first_successful_insert_id_in_prev_stmt(false),
413
 
   global_read_lock(0),
414
 
   is_fatal_error(0),
415
 
   transaction_rollback_request(0),
416
 
   is_fatal_sub_stmt_error(0),
417
 
   rand_used(0),
418
 
   time_zone_used(0),
419
 
   in_lock_tables(0),
420
 
   bootstrap(0),
421
 
   derived_tables_processing(false),
422
 
   m_lip(NULL)
423
 
{
424
 
  ulong tmp;
 
108
extern "C"
 
109
int session_tablespace_op(const Session *session)
 
110
{
 
111
  return test(session->tablespace_op);
 
112
}
 
113
 
 
114
/**
 
115
   Set the process info field of the Session structure.
 
116
 
 
117
   This function is used by plug-ins. Internally, the
 
118
   Session::set_proc_info() function should be used.
 
119
 
 
120
   @see Session::set_proc_info
 
121
 */
 
122
extern "C" void
 
123
set_session_proc_info(Session *session, const char *info)
 
124
{
 
125
  session->set_proc_info(info);
 
126
}
 
127
 
 
128
extern "C"
 
129
const char *get_session_proc_info(Session *session)
 
130
{
 
131
  return session->get_proc_info();
 
132
}
 
133
 
 
134
extern "C"
 
135
void **session_ha_data(const Session *session, const struct StorageEngine *engine)
 
136
{
 
137
  return (void **) &session->ha_data[engine->slot].ha_ptr;
 
138
}
 
139
 
 
140
extern "C"
 
141
int64_t session_test_options(const Session *session, int64_t test_options)
 
142
{
 
143
  return session->options & test_options;
 
144
}
 
145
 
 
146
extern "C"
 
147
int session_sql_command(const Session *session)
 
148
{
 
149
  return (int) session->lex->sql_command;
 
150
}
 
151
 
 
152
extern "C"
 
153
int session_tx_isolation(const Session *session)
 
154
{
 
155
  return (int) session->variables.tx_isolation;
 
156
}
 
157
 
 
158
extern "C"
 
159
void session_inc_row_count(Session *session)
 
160
{
 
161
  session->row_count++;
 
162
}
 
163
 
 
164
Session::Session(Protocol *protocol_arg)
 
165
  :
 
166
  Statement(&main_lex, &main_mem_root, /* statement id */ 0),
 
167
  Open_tables_state(refresh_version),
 
168
  lock_id(&main_lock_id),
 
169
  user_time(0),
 
170
  arg_of_last_insert_id_function(false),
 
171
  first_successful_insert_id_in_prev_stmt(0),
 
172
  first_successful_insert_id_in_cur_stmt(0),
 
173
  limit_found_rows(0),
 
174
  global_read_lock(0),
 
175
  some_tables_deleted(false),
 
176
  no_errors(false),
 
177
  password(false),
 
178
  is_fatal_error(false),
 
179
  transaction_rollback_request(false),
 
180
  is_fatal_sub_stmt_error(0),
 
181
  derived_tables_processing(false),
 
182
  tablespace_op(false),
 
183
  m_lip(NULL),
 
184
  scheduler(0),
 
185
  cached_table(0)
 
186
{
 
187
  uint64_t tmp;
 
188
 
 
189
  memset(process_list_info, 0, PROCESS_LIST_WIDTH);
425
190
 
426
191
  /*
427
192
    Pass nominal parameters to init_alloc_root only to ensure that
429
194
    will be re-initialized in init_for_queries().
430
195
  */
431
196
  init_sql_alloc(&main_mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
432
 
  thread_stack= 0;
433
 
  catalog= (char*)"std"; // the only catalog we have for now
434
 
  main_security_ctx.init();
435
 
  security_ctx= &main_security_ctx;
436
 
  some_tables_deleted=no_errors=password= 0;
437
 
  query_start_used= 0;
 
197
  thread_stack= NULL;
438
198
  count_cuted_fields= CHECK_FIELD_IGNORE;
439
199
  killed= NOT_KILLED;
440
 
  col_access=0;
441
 
  is_slave_error= thread_specific_used= false;
442
 
  hash_clear(&handler_tables_hash);
443
 
  tmp_table=0;
444
 
  used_tables=0;
 
200
  col_access= 0;
 
201
  tmp_table= 0;
 
202
  used_tables= 0;
445
203
  cuted_fields= sent_row_count= row_count= 0L;
446
 
  limit_found_rows= 0;
447
204
  row_count_func= -1;
448
205
  statement_id_counter= 0UL;
449
 
  // Must be reset to handle error with THD's created for init of mysqld
 
206
  // Must be reset to handle error with Session's created for init of mysqld
450
207
  lex->current_select= 0;
451
208
  start_time=(time_t) 0;
452
209
  start_utime= 0L;
453
210
  utime_after_lock= 0L;
454
 
  current_linfo =  0;
455
 
  slave_thread = 0;
456
211
  memset(&variables, 0, sizeof(variables));
457
212
  thread_id= 0;
458
 
  one_shot_set= 0;
459
213
  file_id = 0;
460
214
  query_id= 0;
461
215
  warn_id= 0;
462
 
  db_charset= global_system_variables.collation_database;
463
216
  memset(ha_data, 0, sizeof(ha_data));
464
 
  mysys_var=0;
465
 
  binlog_evt_union.do_union= false;
466
 
  dbug_sentry=THD_SENTRY_MAGIC;
467
 
  net.vio=0;
 
217
  replication_data= 0;
 
218
  mysys_var= 0;
 
219
  dbug_sentry=Session_SENTRY_MAGIC;
468
220
  client_capabilities= 0;                       // minimalistic client
469
 
  system_thread= NON_SYSTEM_THREAD;
470
 
  cleanup_done= abort_on_warning= no_warnings_for_error= 0;
 
221
  cleanup_done= abort_on_warning= no_warnings_for_error= false;
471
222
  peer_port= 0;                                 // For SHOW PROCESSLIST
472
 
  transaction.m_pending_rows_event= 0;
473
223
  transaction.on= 1;
474
224
  pthread_mutex_init(&LOCK_delete, MY_MUTEX_INIT_FAST);
475
225
 
476
226
  /* Variables with default values */
477
227
  proc_info="login";
478
 
  where= THD::DEFAULT_WHERE;
479
 
  server_id = ::server_id;
480
 
  slave_net = 0;
481
 
  command=COM_CONNECT;
482
 
  *scramble= '\0';
483
 
 
484
 
  init();
 
228
  where= Session::DEFAULT_WHERE;
 
229
  command= COM_CONNECT;
 
230
 
 
231
  plugin_sessionvar_init(this);
 
232
  /*
 
233
    variables= global_system_variables above has reset
 
234
    variables.pseudo_thread_id to 0. We need to correct it here to
 
235
    avoid temporary tables replication failure.
 
236
  */
 
237
  variables.pseudo_thread_id= thread_id;
 
238
  server_status= SERVER_STATUS_AUTOCOMMIT;
 
239
  options= session_startup_options;
 
240
 
 
241
  if (variables.max_join_size == HA_POS_ERROR)
 
242
    options |= OPTION_BIG_SELECTS;
 
243
  else
 
244
    options &= ~OPTION_BIG_SELECTS;
 
245
 
 
246
  transaction.all.modified_non_trans_table= transaction.stmt.modified_non_trans_table= false;
 
247
  open_options=ha_open_options;
 
248
  update_lock_default= TL_WRITE;
 
249
  session_tx_isolation= (enum_tx_isolation) variables.tx_isolation;
 
250
  warn_list.empty();
 
251
  memset(warn_count, 0, sizeof(warn_count));
 
252
  total_warn_count= 0;
 
253
  memset(&status_var, 0, sizeof(status_var));
 
254
 
485
255
  /* Initialize sub structures */
486
256
  init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
487
 
  user_connect=(USER_CONN *)0;
488
257
  hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
489
258
            (hash_get_key) get_var_key,
490
259
            (hash_free_key) free_user_var, 0);
491
260
 
492
 
  /* For user vars replication*/
493
 
  if (opt_bin_log)
494
 
    my_init_dynamic_array(&user_var_events,
495
 
                          sizeof(BINLOG_USER_VAR_EVENT *), 16, 16);
496
 
  else
497
 
    memset(&user_var_events, 0, sizeof(user_var_events));
498
 
 
499
261
  /* Protocol */
500
 
  protocol= &protocol_text;                     // Default protocol
501
 
  protocol_text.init(this);
 
262
  protocol= protocol_arg;
 
263
  protocol->setSession(this);
502
264
 
503
 
  tablespace_op= false;
 
265
  const Query_id& local_query_id= Query_id::get_query_id();
504
266
  tmp= sql_rnd();
505
 
  randominit(&rand, tmp + (ulong) &rand, tmp + (ulong) ::global_query_id);
 
267
  protocol->setRandom(tmp + (uint64_t) &protocol,
 
268
                      tmp + (uint64_t)local_query_id.value());
506
269
  substitute_null_with_insert_id = false;
507
270
  thr_lock_info_init(&lock_info); /* safety: will be reset after start */
508
271
  thr_lock_owner_init(&main_lock_id, &lock_info);
510
273
  m_internal_handler= NULL;
511
274
}
512
275
 
 
276
void Statement::free_items()
 
277
{
 
278
  Item *next;
 
279
  /* This works because items are allocated with sql_alloc() */
 
280
  for (; free_list; free_list= next)
 
281
  {
 
282
    next= free_list->next;
 
283
    free_list->delete_self();
 
284
  }
 
285
}
513
286
 
514
 
void THD::push_internal_handler(Internal_error_handler *handler)
 
287
void Session::push_internal_handler(Internal_error_handler *handler)
515
288
{
516
289
  /*
517
290
    TODO: The current implementation is limited to 1 handler at a time only.
518
 
    THD and sp_rcontext need to be modified to use a common handler stack.
 
291
    Session and sp_rcontext need to be modified to use a common handler stack.
519
292
  */
520
293
  assert(m_internal_handler == NULL);
521
294
  m_internal_handler= handler;
522
295
}
523
296
 
524
 
 
525
 
bool THD::handle_error(uint32_t sql_errno, const char *message,
 
297
bool Session::handle_error(uint32_t sql_errno, const char *message,
526
298
                       DRIZZLE_ERROR::enum_warning_level level)
527
299
{
528
300
  if (m_internal_handler)
533
305
  return false;                                 // 'false', as per coding style
534
306
}
535
307
 
536
 
 
537
 
void THD::pop_internal_handler()
 
308
void Session::pop_internal_handler()
538
309
{
539
310
  assert(m_internal_handler != NULL);
540
311
  m_internal_handler= NULL;
541
312
}
542
313
 
543
 
extern "C"
544
 
void *thd_alloc(DRIZZLE_THD thd, unsigned int size)
545
 
{
546
 
  return thd->alloc(size);
547
 
}
548
 
 
549
 
extern "C"
550
 
void *thd_calloc(DRIZZLE_THD thd, unsigned int size)
551
 
{
552
 
  return thd->calloc(size);
553
 
}
554
 
 
555
 
extern "C"
556
 
char *thd_strdup(DRIZZLE_THD thd, const char *str)
557
 
{
558
 
  return thd->strdup(str);
559
 
}
560
 
 
561
 
extern "C"
562
 
char *thd_strmake(DRIZZLE_THD thd, const char *str, unsigned int size)
563
 
{
564
 
  return thd->strmake(str, size);
565
 
}
566
 
 
567
 
extern "C"
568
 
LEX_STRING *thd_make_lex_string(THD *thd, LEX_STRING *lex_str,
569
 
                                const char *str, unsigned int size,
570
 
                                int allocate_lex_string)
571
 
{
572
 
  return thd->make_lex_string(lex_str, str, size,
573
 
                              (bool) allocate_lex_string);
574
 
}
575
 
 
576
 
extern "C"
577
 
void *thd_memdup(DRIZZLE_THD thd, const void* str, unsigned int size)
578
 
{
579
 
  return thd->memdup(str, size);
580
 
}
581
 
 
582
 
extern "C"
583
 
void thd_get_xid(const DRIZZLE_THD thd, DRIZZLE_XID *xid)
584
 
{
585
 
  *xid = *(DRIZZLE_XID *) &thd->transaction.xid_state.xid;
586
 
}
587
 
 
588
 
/*
589
 
  Init common variables that has to be reset on start and on change_user
590
 
*/
591
 
 
592
 
void THD::init(void)
593
 
{
594
 
  pthread_mutex_lock(&LOCK_global_system_variables);
595
 
  plugin_thdvar_init(this);
596
 
  variables.time_format= date_time_format_copy((THD*) 0,
597
 
                                               variables.time_format);
598
 
  variables.date_format= date_time_format_copy((THD*) 0,
599
 
                                               variables.date_format);
600
 
  variables.datetime_format= date_time_format_copy((THD*) 0,
601
 
                                                   variables.datetime_format);
602
 
  /*
603
 
    variables= global_system_variables above has reset
604
 
    variables.pseudo_thread_id to 0. We need to correct it here to
605
 
    avoid temporary tables replication failure.
606
 
  */
607
 
  variables.pseudo_thread_id= thread_id;
608
 
  pthread_mutex_unlock(&LOCK_global_system_variables);
609
 
  server_status= SERVER_STATUS_AUTOCOMMIT;
610
 
  options= thd_startup_options;
611
 
 
612
 
  if (variables.max_join_size == HA_POS_ERROR)
613
 
    options |= OPTION_BIG_SELECTS;
614
 
  else
615
 
    options &= ~OPTION_BIG_SELECTS;
616
 
 
617
 
  transaction.all.modified_non_trans_table= transaction.stmt.modified_non_trans_table= false;
618
 
  open_options=ha_open_options;
619
 
  update_lock_default= (variables.low_priority_updates ?
620
 
                        TL_WRITE_LOW_PRIORITY :
621
 
                        TL_WRITE);
622
 
  session_tx_isolation= (enum_tx_isolation) variables.tx_isolation;
623
 
  warn_list.empty();
624
 
  memset(warn_count, 0, sizeof(warn_count));
625
 
  total_warn_count= 0;
626
 
  update_charset();
627
 
  reset_current_stmt_binlog_row_based();
628
 
  memset(&status_var, 0, sizeof(status_var));
629
 
}
630
 
 
631
 
 
632
 
/*
633
 
  Init THD for query processing.
 
314
#if defined(__cplusplus)
 
315
extern "C" {
 
316
#endif
 
317
 
 
318
void *session_alloc(Session *session, unsigned int size)
 
319
{
 
320
  return session->alloc(size);
 
321
}
 
322
 
 
323
void *session_calloc(Session *session, unsigned int size)
 
324
{
 
325
  return session->calloc(size);
 
326
}
 
327
 
 
328
char *session_strdup(Session *session, const char *str)
 
329
{
 
330
  return session->strdup(str);
 
331
}
 
332
 
 
333
char *session_strmake(Session *session, const char *str, unsigned int size)
 
334
{
 
335
  return session->strmake(str, size);
 
336
}
 
337
 
 
338
void *session_memdup(Session *session, const void* str, unsigned int size)
 
339
{
 
340
  return session->memdup(str, size);
 
341
}
 
342
 
 
343
void session_get_xid(const Session *session, DRIZZLE_XID *xid)
 
344
{
 
345
  *xid = *(DRIZZLE_XID *) &session->transaction.xid_state.xid;
 
346
}
 
347
 
 
348
#if defined(__cplusplus)
 
349
}
 
350
#endif
 
351
 
 
352
/*
 
353
  Init Session for query processing.
634
354
  This has to be called once before we call mysql_parse.
635
 
  See also comments in sql_class.h.
 
355
  See also comments in session.h.
636
356
*/
637
357
 
638
 
void THD::init_for_queries()
 
358
void Session::init_for_queries()
639
359
{
640
 
  set_time(); 
 
360
  set_time();
641
361
  ha_enable_transaction(this,true);
642
362
 
643
363
  reset_root_defaults(mem_root, variables.query_alloc_block_size,
646
366
                      variables.trans_alloc_block_size,
647
367
                      variables.trans_prealloc_size);
648
368
  transaction.xid_state.xid.null();
649
 
  transaction.xid_state.in_thd=1;
 
369
  transaction.xid_state.in_session=1;
650
370
}
651
371
 
652
372
 
653
373
/* Do operations that may take a long time */
654
374
 
655
 
void THD::cleanup(void)
 
375
void Session::cleanup(void)
656
376
{
657
 
  assert(cleanup_done == 0);
 
377
  assert(cleanup_done == false);
658
378
 
659
379
  killed= KILL_CONNECTION;
660
380
#ifdef ENABLE_WHEN_BINLOG_WILL_BE_ABLE_TO_PREPARE
667
387
    ha_rollback(this);
668
388
    xid_cache_delete(&transaction.xid_state);
669
389
  }
670
 
  if (locked_tables)
671
 
  {
672
 
    lock=locked_tables; locked_tables=0;
673
 
    close_thread_tables(this);
674
 
  }
675
 
  mysql_ha_cleanup(this);
676
 
  delete_dynamic(&user_var_events);
677
390
  hash_free(&user_vars);
678
 
  close_temporary_tables(this);
679
 
  free((char*) variables.time_format);
680
 
  free((char*) variables.date_format);
681
 
  free((char*) variables.datetime_format);
682
 
  
 
391
  close_temporary_tables();
 
392
 
683
393
  if (global_read_lock)
684
394
    unlock_global_read_lock(this);
685
395
 
686
 
  cleanup_done=1;
687
 
  return;
 
396
  cleanup_done= true;
688
397
}
689
398
 
690
 
THD::~THD()
 
399
Session::~Session()
691
400
{
692
 
  THD_CHECK_SENTRY(this);
693
 
  /* Ensure that no one is using THD */
694
 
  pthread_mutex_lock(&LOCK_delete);
695
 
  pthread_mutex_unlock(&LOCK_delete);
 
401
  Session_CHECK_SENTRY(this);
696
402
  add_to_status(&global_status_var, &status_var);
697
403
 
 
404
  if (protocol->isConnected())
 
405
  {
 
406
    if (global_system_variables.log_warnings)
 
407
        errmsg_printf(ERRMSG_LVL_WARN, ER(ER_FORCING_CLOSE),my_progname,
 
408
                      thread_id,
 
409
                      (security_ctx.user.c_str() ?
 
410
                       security_ctx.user.c_str() : ""));
 
411
    disconnect(0, false);
 
412
  }
 
413
 
698
414
  /* Close connection */
699
 
  if (net.vio)
700
 
  {
701
 
    net_close(&net);
702
 
    net_end(&net);
703
 
  }
704
 
  if (!cleanup_done)
 
415
  protocol->close();
 
416
  delete protocol;
 
417
 
 
418
  if (cleanup_done == false)
705
419
    cleanup();
706
420
 
707
421
  ha_close_connection(this);
708
 
  plugin_thdvar_cleanup(this);
 
422
  plugin_sessionvar_cleanup(this);
709
423
 
710
 
  main_security_ctx.destroy();
711
424
  if (db)
712
425
  {
713
426
    free(db);
716
429
  free_root(&warn_root,MYF(0));
717
430
  free_root(&transaction.mem_root,MYF(0));
718
431
  mysys_var=0;                                  // Safety (shouldn't be needed)
 
432
  dbug_sentry= Session_SENTRY_GONE;
 
433
 
 
434
  free_root(&main_mem_root, MYF(0));
 
435
  pthread_setspecific(THR_Session,  0);
 
436
 
 
437
 
 
438
  /* Ensure that no one is using Session */
 
439
  pthread_mutex_unlock(&LOCK_delete);
719
440
  pthread_mutex_destroy(&LOCK_delete);
720
 
  dbug_sentry= THD_SENTRY_GONE;
721
 
  if (rli_fake)
722
 
  {
723
 
    delete rli_fake;
724
 
    rli_fake= NULL;
725
 
  }
726
 
  
727
 
  free_root(&main_mem_root, MYF(0));
728
 
  return;
729
441
}
730
442
 
731
 
 
732
443
/*
733
444
  Add all status variables to another status variable array
734
445
 
742
453
    If this assumption will change, then we have to explictely add
743
454
    the other variables after the while loop
744
455
*/
745
 
 
746
456
void add_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var)
747
457
{
748
458
  ulong *end= (ulong*) ((unsigned char*) to_var +
762
472
    to_var       add to this array
763
473
    from_var     from this array
764
474
    dec_var      minus this array
765
 
  
 
475
 
766
476
  NOTE
767
477
    This function assumes that all variables are long/ulong.
768
478
*/
769
 
 
770
479
void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var,
771
480
                        STATUS_VAR *dec_var)
772
481
{
779
488
    *(to++)+= *(from++) - *(dec++);
780
489
}
781
490
 
782
 
 
783
 
void THD::awake(THD::killed_state state_to_set)
 
491
void Session::awake(Session::killed_state state_to_set)
784
492
{
785
 
  THD_CHECK_SENTRY(this);
786
 
  safe_mutex_assert_owner(&LOCK_delete); 
 
493
  Session_CHECK_SENTRY(this);
 
494
  safe_mutex_assert_owner(&LOCK_delete);
 
495
  Scheduler &thread_scheduler= get_thread_scheduler();
787
496
 
788
497
  killed= state_to_set;
789
 
  if (state_to_set != THD::KILL_QUERY)
 
498
  if (state_to_set != Session::KILL_QUERY)
790
499
  {
791
 
    thr_alarm_kill(thread_id);
792
 
    if (!slave_thread)
793
 
      thread_scheduler.post_kill_notification(this);
 
500
    thread_scheduler.post_kill_notification(this);
794
501
  }
795
502
  if (mysys_var)
796
503
  {
797
504
    pthread_mutex_lock(&mysys_var->mutex);
798
 
    if (!system_thread)         // Don't abort locks
799
 
      mysys_var->abort=1;
800
505
    /*
801
506
      This broadcast could be up in the air if the victim thread
802
507
      exits the cond in the time between read and broadcast, but that is
813
518
      current_cond and current_mutex are 0), then the victim will not get
814
519
      a signal and it may wait "forever" on the cond (until
815
520
      we issue a second KILL or the status it's waiting for happens).
816
 
      It's true that we have set its thd->killed but it may not
 
521
      It's true that we have set its session->killed but it may not
817
522
      see it immediately and so may have time to reach the cond_wait().
818
523
    */
819
524
    if (mysys_var->current_cond && mysys_var->current_mutex)
824
529
    }
825
530
    pthread_mutex_unlock(&mysys_var->mutex);
826
531
  }
827
 
  return;
828
532
}
829
533
 
830
534
/*
831
535
  Remember the location of thread info, the structure needed for
832
536
  sql_alloc() and the structure for the net buffer
833
537
*/
834
 
 
835
 
bool THD::store_globals()
 
538
bool Session::store_globals()
836
539
{
837
540
  /*
838
541
    Assert that thread_stack is initialized: it's necessary to be able
840
543
  */
841
544
  assert(thread_stack);
842
545
 
843
 
  if (my_pthread_setspecific_ptr(THR_THD,  this) ||
844
 
      my_pthread_setspecific_ptr(THR_MALLOC, &mem_root))
 
546
  if (pthread_setspecific(THR_Session,  this) ||
 
547
      pthread_setspecific(THR_Mem_root, &mem_root))
845
548
    return 1;
846
549
  mysys_var=my_thread_var;
 
550
 
847
551
  /*
848
552
    Let mysqld define the thread id (not mysys)
849
 
    This allows us to move THD to different threads if needed.
 
553
    This allows us to move Session to different threads if needed.
850
554
  */
851
555
  mysys_var->id= thread_id;
852
556
  real_id= pthread_self();                      // For debugging
853
557
 
854
558
  /*
855
 
    We have to call thr_lock_info_init() again here as THD may have been
 
559
    We have to call thr_lock_info_init() again here as Session may have been
856
560
    created in another thread
857
561
  */
858
562
  thr_lock_info_init(&lock_info);
859
563
  return 0;
860
564
}
861
565
 
862
 
 
863
 
/*
864
 
  Cleanup after query.
865
 
 
866
 
  SYNOPSIS
867
 
    THD::cleanup_after_query()
868
 
 
869
 
  DESCRIPTION
870
 
    This function is used to reset thread data to its default state.
871
 
 
872
 
  NOTE
873
 
    This function is not suitable for setting thread data to some
874
 
    non-default values, as there is only one replication thread, so
875
 
    different master threads may overwrite data of each other on
876
 
    slave.
877
 
*/
878
 
 
879
 
void THD::cleanup_after_query()
880
 
{
881
 
  /*
882
 
    Reset rand_used so that detection of calls to rand() will save random 
 
566
void Session::prepareForQueries()
 
567
{
 
568
  if (variables.max_join_size == HA_POS_ERROR)
 
569
    options |= OPTION_BIG_SELECTS;
 
570
  if (client_capabilities & CLIENT_COMPRESS)
 
571
  {
 
572
    protocol->enableCompression();
 
573
  }
 
574
 
 
575
  version= refresh_version;
 
576
  set_proc_info(NULL);
 
577
  command= COM_SLEEP;
 
578
  set_time();
 
579
  init_for_queries();
 
580
}
 
581
 
 
582
bool Session::initGlobals()
 
583
{
 
584
  if (store_globals())
 
585
  {
 
586
    disconnect(ER_OUT_OF_RESOURCES, true);
 
587
    statistic_increment(aborted_connects, &LOCK_status);
 
588
    Scheduler &thread_scheduler= get_thread_scheduler();
 
589
    thread_scheduler.end_thread(this, 0);
 
590
    return false;
 
591
  }
 
592
  return true;
 
593
}
 
594
 
 
595
bool Session::authenticate()
 
596
{
 
597
  lex_start(this);
 
598
  if (protocol->authenticate())
 
599
    return true;
 
600
 
 
601
  statistic_increment(aborted_connects, &LOCK_status);
 
602
  return false;
 
603
}
 
604
 
 
605
bool Session::checkUser(const char *passwd, uint32_t passwd_len, const char *in_db)
 
606
{
 
607
  LEX_STRING db_str= { (char *) in_db, in_db ? strlen(in_db) : 0 };
 
608
  bool is_authenticated;
 
609
 
 
610
  /*
 
611
    Clear session->db as it points to something, that will be freed when
 
612
    connection is closed. We don't want to accidentally free a wrong
 
613
    pointer if connect failed. Also in case of 'CHANGE USER' failure,
 
614
    current database will be switched to 'no database selected'.
 
615
  */
 
616
  reset_db(NULL, 0);
 
617
 
 
618
  if (passwd_len != 0 && passwd_len != SCRAMBLE_LENGTH)
 
619
  {
 
620
    my_error(ER_HANDSHAKE_ERROR, MYF(0), security_ctx.ip.c_str());
 
621
    return false;
 
622
  }
 
623
 
 
624
  is_authenticated= authenticate_user(this, passwd);
 
625
 
 
626
  if (is_authenticated != true)
 
627
  {
 
628
    my_error(ER_ACCESS_DENIED_ERROR, MYF(0),
 
629
             security_ctx.user.c_str(),
 
630
             security_ctx.ip.c_str(),
 
631
             passwd_len ? ER(ER_YES) : ER(ER_NO));
 
632
 
 
633
    return false;
 
634
  }
 
635
 
 
636
  security_ctx.skip_grants();
 
637
 
 
638
  /* Change database if necessary */
 
639
  if (in_db && in_db[0])
 
640
  {
 
641
    if (mysql_change_db(this, &db_str, false))
 
642
    {
 
643
      /* mysql_change_db() has pushed the error message. */
 
644
      return false;
 
645
    }
 
646
  }
 
647
  my_ok();
 
648
  password= test(passwd_len);          // remember for error messages
 
649
 
 
650
  /* Ready to handle queries */
 
651
  return true;
 
652
}
 
653
 
 
654
bool Session::executeStatement()
 
655
{
 
656
  char *l_packet= 0;
 
657
  uint32_t packet_length;
 
658
 
 
659
  enum enum_server_command l_command;
 
660
 
 
661
  /*
 
662
    indicator of uninitialized lex => normal flow of errors handling
 
663
    (see my_message_sql)
 
664
  */
 
665
  lex->current_select= 0;
 
666
 
 
667
  if (protocol->readCommand(&l_packet, &packet_length) == false)
 
668
    return false;
 
669
 
 
670
  if (packet_length == 0)
 
671
    return true;
 
672
 
 
673
  l_command= (enum enum_server_command) (unsigned char) l_packet[0];
 
674
 
 
675
  if (command >= COM_END)
 
676
    command= COM_END;                           // Wrong command
 
677
 
 
678
  assert(packet_length);
 
679
  return ! dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
 
680
}
 
681
 
 
682
bool Session::readAndStoreQuery(const char *in_packet, uint32_t in_packet_length)
 
683
{
 
684
  /* Remove garbage at start and end of query */
 
685
  while (in_packet_length > 0 && my_isspace(charset(), in_packet[0]))
 
686
  {
 
687
    in_packet++;
 
688
    in_packet_length--;
 
689
  }
 
690
  const char *pos= in_packet + in_packet_length; /* Point at end null */
 
691
  while (in_packet_length > 0 &&
 
692
         (pos[-1] == ';' || my_isspace(charset() ,pos[-1])))
 
693
  {
 
694
    pos--;
 
695
    in_packet_length--;
 
696
  }
 
697
 
 
698
  /* We must allocate some extra memory for the cached query string */
 
699
  query_length= 0; /* Extra safety: Avoid races */
 
700
  query= (char*) memdup_w_gap((unsigned char*) in_packet, in_packet_length, db_length + 1);
 
701
  if (! query)
 
702
    return false;
 
703
 
 
704
  query[in_packet_length]=0;
 
705
  query_length= in_packet_length;
 
706
 
 
707
  /* Reclaim some memory */
 
708
  packet.shrink(variables.net_buffer_length);
 
709
  convert_buffer.shrink(variables.net_buffer_length);
 
710
 
 
711
  return true;
 
712
}
 
713
 
 
714
bool Session::endTransaction(enum enum_mysql_completiontype completion)
 
715
{
 
716
  bool do_release= 0;
 
717
  bool result= true;
 
718
 
 
719
  if (transaction.xid_state.xa_state != XA_NOTR)
 
720
  {
 
721
    my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[transaction.xid_state.xa_state]);
 
722
    return false;
 
723
  }
 
724
  switch (completion) 
 
725
  {
 
726
    case COMMIT:
 
727
      /*
 
728
       * We don't use endActiveTransaction() here to ensure that this works
 
729
       * even if there is a problem with the OPTION_AUTO_COMMIT flag
 
730
       * (Which of course should never happen...)
 
731
       */
 
732
      server_status&= ~SERVER_STATUS_IN_TRANS;
 
733
      if (ha_commit(this))
 
734
        result= false;
 
735
      options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
 
736
      transaction.all.modified_non_trans_table= false;
 
737
      break;
 
738
    case COMMIT_RELEASE:
 
739
      do_release= 1; /* fall through */
 
740
    case COMMIT_AND_CHAIN:
 
741
      result= endActiveTransaction();
 
742
      if (result == true && completion == COMMIT_AND_CHAIN)
 
743
        result= startTransaction();
 
744
      break;
 
745
    case ROLLBACK_RELEASE:
 
746
      do_release= 1; /* fall through */
 
747
    case ROLLBACK:
 
748
    case ROLLBACK_AND_CHAIN:
 
749
    {
 
750
      server_status&= ~SERVER_STATUS_IN_TRANS;
 
751
      if (ha_rollback(this))
 
752
        result= false;
 
753
      options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
 
754
      transaction.all.modified_non_trans_table= false;
 
755
      if (result == true && (completion == ROLLBACK_AND_CHAIN))
 
756
        result= startTransaction();
 
757
      break;
 
758
    }
 
759
    default:
 
760
      my_error(ER_UNKNOWN_COM_ERROR, MYF(0));
 
761
      return false;
 
762
  }
 
763
 
 
764
  if (result == false)
 
765
    my_error(killed_errno(), MYF(0));
 
766
  else if ((result == true) && do_release)
 
767
    killed= Session::KILL_CONNECTION;
 
768
 
 
769
  return result;
 
770
}
 
771
 
 
772
bool Session::endActiveTransaction()
 
773
{
 
774
  bool result= true;
 
775
 
 
776
  if (transaction.xid_state.xa_state != XA_NOTR)
 
777
  {
 
778
    my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[transaction.xid_state.xa_state]);
 
779
    return false;
 
780
  }
 
781
  if (options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
 
782
  {
 
783
    server_status&= ~SERVER_STATUS_IN_TRANS;
 
784
    if (ha_commit(this))
 
785
      result= false;
 
786
  }
 
787
  options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
 
788
  transaction.all.modified_non_trans_table= false;
 
789
  return result;
 
790
}
 
791
 
 
792
bool Session::startTransaction()
 
793
{
 
794
  bool result= true;
 
795
 
 
796
  if (! endActiveTransaction())
 
797
    result= false;
 
798
  else
 
799
  {
 
800
    options|= OPTION_BEGIN;
 
801
    server_status|= SERVER_STATUS_IN_TRANS;
 
802
    if (lex->start_transaction_opt & DRIZZLE_START_TRANS_OPT_WITH_CONS_SNAPSHOT)
 
803
      if (ha_start_consistent_snapshot(this))
 
804
        result= false;
 
805
  }
 
806
  return result;
 
807
}
 
808
 
 
809
void Session::cleanup_after_query()
 
810
{
 
811
  /*
 
812
    Reset rand_used so that detection of calls to rand() will save random
883
813
    seeds if needed by the slave.
884
 
 
885
 
    Do not reset rand_used if inside a stored function or trigger because 
886
 
    only the call to these operations is logged. Thus only the calling 
887
 
    statement needs to detect rand() calls made by its substatements. These
888
 
    substatements must not set rand_used to 0 because it would remove the
889
 
    detection of rand() by the calling statement. 
890
814
  */
891
 
  if (!in_sub_stmt) /* stored functions and triggers are a special case */
892
815
  {
893
816
    /* Forget those values, for next binlogger: */
894
 
    stmt_depends_on_first_successful_insert_id_in_prev_stmt= 0;
895
817
    auto_inc_intervals_in_cur_stmt_for_binlog.empty();
896
 
    rand_used= 0;
897
818
  }
898
819
  if (first_successful_insert_id_in_cur_stmt > 0)
899
820
  {
900
821
    /* set what LAST_INSERT_ID() will return */
901
 
    first_successful_insert_id_in_prev_stmt= 
902
 
      first_successful_insert_id_in_cur_stmt;
 
822
    first_successful_insert_id_in_prev_stmt= first_successful_insert_id_in_cur_stmt;
903
823
    first_successful_insert_id_in_cur_stmt= 0;
904
824
    substitute_null_with_insert_id= true;
905
825
  }
906
 
  arg_of_last_insert_id_function= 0;
 
826
  arg_of_last_insert_id_function= false;
907
827
  /* Free Items that were created during this execution */
908
828
  free_items();
909
829
  /* Reset where. */
910
 
  where= THD::DEFAULT_WHERE;
 
830
  where= Session::DEFAULT_WHERE;
911
831
}
912
832
 
913
 
 
914
833
/**
915
834
  Create a LEX_STRING in this connection.
916
835
 
921
840
                              instead of using lex_str value
922
841
  @return  NULL on failure, or pointer to the LEX_STRING object
923
842
*/
924
 
LEX_STRING *THD::make_lex_string(LEX_STRING *lex_str,
 
843
LEX_STRING *Session::make_lex_string(LEX_STRING *lex_str,
925
844
                                 const char* str, uint32_t length,
926
845
                                 bool allocate_lex_string)
927
846
{
934
853
  return lex_str;
935
854
}
936
855
 
937
 
 
938
 
/*
939
 
  Convert a string to another character set
940
 
 
941
 
  SYNOPSIS
942
 
    convert_string()
943
 
    to                          Store new allocated string here
944
 
    to_cs                       New character set for allocated string
945
 
    from                        String to convert
946
 
    from_length                 Length of string to convert
947
 
    from_cs                     Original character set
948
 
 
949
 
  NOTES
950
 
    to will be 0-terminated to make it easy to pass to system funcs
951
 
 
952
 
  RETURN
953
 
    0   ok
954
 
    1   End of memory.
955
 
        In this case to->str will point to 0 and to->length will be 0.
956
 
*/
957
 
 
958
 
bool THD::convert_string(LEX_STRING *to, const CHARSET_INFO * const to_cs,
959
 
                         const char *from, uint32_t from_length,
960
 
                         const CHARSET_INFO * const from_cs)
961
 
{
962
 
  size_t new_length= to_cs->mbmaxlen * from_length;
963
 
  uint32_t dummy_errors;
964
 
  if (!(to->str= (char*) alloc(new_length+1)))
965
 
  {
966
 
    to->length= 0;                              // Safety fix
967
 
    return(1);                          // EOM
968
 
  }
969
 
  to->length= copy_and_convert((char*) to->str, new_length, to_cs,
970
 
                               from, from_length, from_cs, &dummy_errors);
971
 
  to->str[to->length]=0;                        // Safety
972
 
  return(0);
973
 
}
974
 
 
975
 
 
976
 
/*
977
 
  Convert string from source character set to target character set inplace.
978
 
 
979
 
  SYNOPSIS
980
 
    THD::convert_string
981
 
 
982
 
  DESCRIPTION
983
 
    Convert string using convert_buffer - buffer for character set 
984
 
    conversion shared between all protocols.
985
 
 
986
 
  RETURN
987
 
    0   ok
988
 
   !0   out of memory
989
 
*/
990
 
 
991
 
bool THD::convert_string(String *s, const CHARSET_INFO * const from_cs,
992
 
                         const CHARSET_INFO * const to_cs)
993
 
{
994
 
  uint32_t dummy_errors;
995
 
  if (convert_buffer.copy(s->ptr(), s->length(), from_cs, to_cs, &dummy_errors))
996
 
    return true;
997
 
  /* If convert_buffer >> s copying is more efficient long term */
998
 
  if (convert_buffer.alloced_length() >= convert_buffer.length() * 2 ||
999
 
      !s->is_alloced())
1000
 
  {
1001
 
    return s->copy(convert_buffer);
1002
 
  }
1003
 
  s->swap(convert_buffer);
1004
 
  return false;
1005
 
}
1006
 
 
1007
 
 
1008
 
/*
1009
 
  Update some cache variables when character set changes
1010
 
*/
1011
 
 
1012
 
void THD::update_charset()
1013
 
{
1014
 
  uint32_t not_used;
1015
 
  charset_is_system_charset= !String::needs_conversion(0,charset(),
1016
 
                                                       system_charset_info,
1017
 
                                                       &not_used);
1018
 
  charset_is_collation_connection= 
1019
 
    !String::needs_conversion(0,charset(),variables.collation_connection,
1020
 
                              &not_used);
1021
 
  charset_is_character_set_filesystem= 
1022
 
    !String::needs_conversion(0, charset(),
1023
 
                              variables.character_set_filesystem, &not_used);
1024
 
}
1025
 
 
1026
 
 
1027
856
/* routings to adding tables to list of changed in transaction tables */
1028
 
 
1029
857
inline static void list_include(CHANGED_TableList** prev,
1030
858
                                CHANGED_TableList* curr,
1031
859
                                CHANGED_TableList* new_table)
1039
867
 
1040
868
/* add table to list of changed in transaction tables */
1041
869
 
1042
 
void THD::add_changed_table(Table *table)
 
870
void Session::add_changed_table(Table *table)
1043
871
{
1044
872
  assert((options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) &&
1045
873
              table->file->has_transactions());
1046
874
  add_changed_table(table->s->table_cache_key.str,
1047
875
                    (long) table->s->table_cache_key.length);
1048
 
  return;
1049
876
}
1050
877
 
1051
878
 
1052
 
void THD::add_changed_table(const char *key, long key_length)
 
879
void Session::add_changed_table(const char *key, long key_length)
1053
880
{
1054
881
  CHANGED_TableList **prev_changed = &transaction.changed_tables;
1055
882
  CHANGED_TableList *curr = transaction.changed_tables;
1067
894
      cmp = memcmp(curr->key, key, curr->key_length);
1068
895
      if (cmp < 0)
1069
896
      {
1070
 
        list_include(prev_changed, curr, changed_table_dup(key, key_length));
1071
 
        return;
 
897
        list_include(prev_changed, curr, changed_table_dup(key, key_length));
 
898
        return;
1072
899
      }
1073
900
      else if (cmp == 0)
1074
901
      {
1075
 
        return;
 
902
        return;
1076
903
      }
1077
904
    }
1078
905
  }
1079
906
  *prev_changed = changed_table_dup(key, key_length);
1080
 
  return;
1081
907
}
1082
908
 
1083
909
 
1084
 
CHANGED_TableList* THD::changed_table_dup(const char *key, long key_length)
 
910
CHANGED_TableList* Session::changed_table_dup(const char *key, long key_length)
1085
911
{
1086
 
  CHANGED_TableList* new_table = 
 
912
  CHANGED_TableList* new_table =
1087
913
    (CHANGED_TableList*) trans_alloc(ALIGN_SIZE(sizeof(CHANGED_TableList))+
1088
914
                                      key_length + 1);
1089
915
  if (!new_table)
1102
928
}
1103
929
 
1104
930
 
1105
 
int THD::send_explain_fields(select_result *result)
 
931
int Session::send_explain_fields(select_result *result)
1106
932
{
1107
933
  List<Item> field_list;
1108
934
  Item *item;
1141
967
                              Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF));
1142
968
}
1143
969
 
1144
 
 
1145
 
struct Item_change_record: public ilink
1146
 
{
1147
 
  Item **place;
1148
 
  Item *old_value;
1149
 
  /* Placement new was hidden by `new' in ilink (TODO: check): */
1150
 
  static void *operator new(size_t size __attribute__((unused)),
1151
 
                            void *mem)
1152
 
    { return mem; }
1153
 
  static void operator delete(void *ptr __attribute__((unused)),
1154
 
                              size_t size __attribute__((unused)))
1155
 
    {}
1156
 
  static void operator delete(void *ptr __attribute__((unused)),
1157
 
                              void *mem __attribute__((unused)))
1158
 
    { /* never called */ }
1159
 
};
1160
 
 
1161
 
 
1162
 
/*
1163
 
  Register an item tree tree transformation, performed by the query
1164
 
  optimizer. We need a pointer to runtime_memroot because it may be !=
1165
 
  thd->mem_root (this may no longer be a true statement)
1166
 
*/
1167
 
 
1168
 
void THD::nocheck_register_item_tree_change(Item **place, Item *old_value,
1169
 
                                            MEM_ROOT *runtime_memroot)
1170
 
{
1171
 
  Item_change_record *change;
1172
 
  /*
1173
 
    Now we use one node per change, which adds some memory overhead,
1174
 
    but still is rather fast as we use alloc_root for allocations.
1175
 
    A list of item tree changes of an average query should be short.
1176
 
  */
1177
 
  void *change_mem= alloc_root(runtime_memroot, sizeof(*change));
1178
 
  if (change_mem == 0)
1179
 
  {
1180
 
    /*
1181
 
      OOM, thd->fatal_error() is called by the error handler of the
1182
 
      memroot. Just return.
1183
 
    */
1184
 
    return;
1185
 
  }
1186
 
  change= new (change_mem) Item_change_record;
1187
 
  change->place= place;
1188
 
  change->old_value= old_value;
1189
 
  change_list.append(change);
1190
 
}
1191
 
 
1192
 
 
1193
 
void THD::rollback_item_tree_changes()
1194
 
{
1195
 
  I_List_iterator<Item_change_record> it(change_list);
1196
 
  Item_change_record *change;
1197
 
 
1198
 
  while ((change= it++))
1199
 
    *change->place= change->old_value;
1200
 
  /* We can forget about changes memory: it's allocated in runtime memroot */
1201
 
  change_list.empty();
1202
 
  return;
1203
 
}
1204
 
 
1205
 
 
1206
 
/*****************************************************************************
1207
 
** Functions to provide a interface to select results
1208
 
*****************************************************************************/
1209
 
 
1210
 
select_result::select_result()
1211
 
{
1212
 
  thd=current_thd;
1213
 
}
1214
 
 
1215
 
void select_result::send_error(uint32_t errcode,const char *err)
1216
 
{
1217
 
  my_message(errcode, err, MYF(0));
1218
 
}
1219
 
 
1220
 
 
1221
 
void select_result::cleanup()
1222
 
{
1223
 
  /* do nothing */
1224
 
}
1225
 
 
1226
 
bool select_result::check_simple_select() const
1227
 
{
1228
 
  my_error(ER_SP_BAD_CURSOR_QUERY, MYF(0));
1229
 
  return true;
1230
 
}
1231
 
 
1232
 
 
1233
 
static String default_line_term("\n",default_charset_info);
1234
 
static String default_escaped("\\",default_charset_info);
1235
 
static String default_field_term("\t",default_charset_info);
1236
 
 
1237
 
sql_exchange::sql_exchange(char *name, bool flag,
1238
 
                           enum enum_filetype filetype_arg)
1239
 
  :file_name(name), opt_enclosed(0), dumpfile(flag), skip_lines(0)
1240
 
{
1241
 
  filetype= filetype_arg;
1242
 
  field_term= &default_field_term;
1243
 
  enclosed=   line_start= &my_empty_string;
1244
 
  line_term=  &default_line_term;
1245
 
  escaped=    &default_escaped;
1246
 
  cs= NULL;
1247
 
}
1248
 
 
1249
 
bool select_send::send_fields(List<Item> &list, uint32_t flags)
1250
 
{
1251
 
  bool res;
1252
 
  if (!(res= thd->protocol->send_fields(&list, flags)))
1253
 
    is_result_set_started= 1;
1254
 
  return res;
1255
 
}
1256
 
 
1257
 
void select_send::abort()
1258
 
{
1259
 
  return;
1260
 
}
1261
 
 
1262
 
 
1263
 
/** 
1264
 
  Cleanup an instance of this class for re-use
1265
 
  at next execution of a prepared statement/
1266
 
  stored procedure statement.
1267
 
*/
1268
 
 
1269
 
void select_send::cleanup()
1270
 
{
1271
 
  is_result_set_started= false;
1272
 
}
1273
 
 
1274
 
/* Send data to client. Returns 0 if ok */
1275
 
 
1276
 
bool select_send::send_data(List<Item> &items)
1277
 
{
1278
 
  if (unit->offset_limit_cnt)
1279
 
  {                                             // using limit offset,count
1280
 
    unit->offset_limit_cnt--;
1281
 
    return 0;
1282
 
  }
1283
 
 
1284
 
  /*
1285
 
    We may be passing the control from mysqld to the client: release the
1286
 
    InnoDB adaptive hash S-latch to avoid thread deadlocks if it was reserved
1287
 
    by thd
1288
 
  */
1289
 
  ha_release_temporary_latches(thd);
1290
 
 
1291
 
  List_iterator_fast<Item> li(items);
1292
 
  Protocol *protocol= thd->protocol;
1293
 
  char buff[MAX_FIELD_WIDTH];
1294
 
  String buffer(buff, sizeof(buff), &my_charset_bin);
1295
 
 
1296
 
  protocol->prepare_for_resend();
1297
 
  Item *item;
1298
 
  while ((item=li++))
1299
 
  {
1300
 
    if (item->send(protocol, &buffer))
1301
 
    {
1302
 
      protocol->free();                         // Free used buffer
1303
 
      my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
1304
 
      break;
1305
 
    }
1306
 
  }
1307
 
  thd->sent_row_count++;
1308
 
  if (thd->is_error())
1309
 
  {
1310
 
    protocol->remove_last_row();
1311
 
    return(1);
1312
 
  }
1313
 
  if (thd->vio_ok())
1314
 
    return(protocol->write());
1315
 
  return(0);
1316
 
}
1317
 
 
1318
 
bool select_send::send_eof()
1319
 
{
1320
 
  /* 
1321
 
    We may be passing the control from mysqld to the client: release the
1322
 
    InnoDB adaptive hash S-latch to avoid thread deadlocks if it was reserved
1323
 
    by thd 
1324
 
  */
1325
 
  ha_release_temporary_latches(thd);
1326
 
 
1327
 
  /* Unlock tables before sending packet to gain some speed */
1328
 
  if (thd->lock)
1329
 
  {
1330
 
    mysql_unlock_tables(thd, thd->lock);
1331
 
    thd->lock=0;
1332
 
  }
1333
 
  ::my_eof(thd);
1334
 
  is_result_set_started= 0;
1335
 
  return false;
1336
 
}
1337
 
 
1338
 
 
1339
970
/************************************************************************
1340
971
  Handling writing to file
1341
972
************************************************************************/
1365
996
      function, SELECT INTO has to have an own SQLCOM.
1366
997
      TODO: split from SQLCOM_SELECT
1367
998
    */
1368
 
    ::my_ok(thd,row_count);
 
999
    session->my_ok(row_count);
1369
1000
  }
1370
1001
  file= -1;
1371
1002
  return error;
1402
1033
 
1403
1034
select_export::~select_export()
1404
1035
{
1405
 
  thd->sent_row_count=row_count;
 
1036
  session->sent_row_count=row_count;
1406
1037
}
1407
1038
 
1408
1039
 
1411
1042
 
1412
1043
  SYNOPSIS
1413
1044
    create_file()
1414
 
    thd                 Thread handle
 
1045
    session                     Thread handle
1415
1046
    path                File name
1416
1047
    exchange            Excange class
1417
1048
    cache               IO cache
1422
1053
*/
1423
1054
 
1424
1055
 
1425
 
static File create_file(THD *thd, char *path, sql_exchange *exchange,
1426
 
                        IO_CACHE *cache)
 
1056
static File create_file(Session *session, char *path, file_exchange *exchange, IO_CACHE *cache)
1427
1057
{
1428
1058
  File file;
1429
1059
  uint32_t option= MY_UNPACK_FILENAME | MY_RELATIVE_PATH;
1434
1064
 
1435
1065
  if (!dirname_length(exchange->file_name))
1436
1066
  {
1437
 
    strxnmov(path, FN_REFLEN-1, mysql_real_data_home, thd->db ? thd->db : "",
1438
 
             NULL);
 
1067
    strcpy(path, drizzle_real_data_home);
 
1068
    if (session->db)
 
1069
      strncat(path, session->db, FN_REFLEN-strlen(drizzle_real_data_home)-1);
1439
1070
    (void) fn_format(path, exchange->file_name, path, "", option);
1440
1071
  }
1441
1072
  else
1442
 
    (void) fn_format(path, exchange->file_name, mysql_real_data_home, "", option);
 
1073
    (void) fn_format(path, exchange->file_name, drizzle_real_data_home, "", option);
1443
1074
 
1444
1075
  if (opt_secure_file_priv &&
1445
1076
      strncmp(opt_secure_file_priv, path, strlen(opt_secure_file_priv)))
1465
1096
  if (init_io_cache(cache, file, 0L, WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1466
1097
  {
1467
1098
    my_close(file, MYF(0));
1468
 
    my_delete(path, MYF(0));  // Delete file on error, it was just created 
 
1099
    my_delete(path, MYF(0));  // Delete file on error, it was just created
1469
1100
    return -1;
1470
1101
  }
1471
1102
  return file;
1473
1104
 
1474
1105
 
1475
1106
int
1476
 
select_export::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
 
1107
select_export::prepare(List<Item> &list, Select_Lex_Unit *u)
1477
1108
{
1478
1109
  bool blob_flag=0;
1479
1110
  bool string_results= false, non_string_results= false;
1480
1111
  unit= u;
1481
 
  if ((uint) strlen(exchange->file_name) + NAME_LEN >= FN_REFLEN)
1482
 
    strmake(path,exchange->file_name,FN_REFLEN-1);
 
1112
  if ((uint32_t) strlen(exchange->file_name) + NAME_LEN >= FN_REFLEN)
 
1113
    strncpy(path,exchange->file_name,FN_REFLEN-1);
1483
1114
 
1484
 
  if ((file= create_file(thd, path, exchange, &cache)) < 0)
1485
 
    return 1;
1486
1115
  /* Check if there is any blobs in data */
1487
1116
  {
1488
1117
    List_iterator_fast<Item> li(list);
1524
1153
      (exchange->opt_enclosed && non_string_results &&
1525
1154
       field_term_length && strchr(NUMERIC_CHARS, field_term_char)))
1526
1155
  {
1527
 
    push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1528
 
                 ER_AMBIGUOUS_FIELD_TERM, ER(ER_AMBIGUOUS_FIELD_TERM));
1529
 
    is_ambiguous_field_term= true;
 
1156
    my_error(ER_AMBIGUOUS_FIELD_TERM, MYF(0));
 
1157
    return 1;
1530
1158
  }
1531
 
  else
1532
 
    is_ambiguous_field_term= false;
 
1159
 
 
1160
  if ((file= create_file(session, path, exchange, &cache)) < 0)
 
1161
    return 1;
1533
1162
 
1534
1163
  return 0;
1535
1164
}
1603
1232
      {
1604
1233
        char *pos, *start, *end;
1605
1234
        const CHARSET_INFO * const res_charset= res->charset();
1606
 
        const CHARSET_INFO * const character_set_client= thd->variables.
1607
 
                                                            character_set_client;
 
1235
        const CHARSET_INFO * const character_set_client= default_charset_info;
 
1236
 
1608
1237
        bool check_second_byte= (res_charset == &my_charset_bin) &&
1609
1238
                                 character_set_client->
1610
1239
                                 escape_with_backslash_is_dangerous;
1611
1240
        assert(character_set_client->mbmaxlen == 2 ||
1612
 
                    !character_set_client->escape_with_backslash_is_dangerous);
 
1241
               !character_set_client->escape_with_backslash_is_dangerous);
1613
1242
        for (start=pos=(char*) res->ptr(),end=pos+used_length ;
1614
1243
             pos != end ;
1615
1244
             pos++)
1631
1260
            for the clients with character sets big5, cp932, gbk and sjis,
1632
1261
            which can have the escape character (0x5C "\" by default)
1633
1262
            as the second byte of a multi-byte sequence.
1634
 
            
 
1263
 
1635
1264
            If
1636
1265
            - pos[0] is a valid multi-byte head (e.g 0xEE) and
1637
1266
            - pos[1] is 0x00, which will be escaped as "\0",
1638
 
            
 
1267
 
1639
1268
            then we'll get "0xEE + 0x5C + 0x30" in the output file.
1640
 
            
 
1269
 
1641
1270
            If this file is later loaded using this sequence of commands:
1642
 
            
 
1271
 
1643
1272
            mysql> create table t1 (a varchar(128)) character set big5;
1644
1273
            mysql> LOAD DATA INFILE 'dump.txt' INTO Table t1;
1645
 
            
 
1274
 
1646
1275
            then 0x5C will be misinterpreted as the second byte
1647
1276
            of a multi-byte character "0xEE + 0x5C", instead of
1648
1277
            escape character for 0x00.
1649
 
            
 
1278
 
1650
1279
            To avoid this confusion, we'll escape the multi-byte
1651
1280
            head character too, so the sequence "0xEE + 0x00" will be
1652
1281
            dumped as "0x5C + 0xEE + 0x5C + 0x30".
1653
 
            
 
1282
 
1654
1283
            Note, in the condition below we only check if
1655
1284
            mbcharlen is equal to 2, because there are no
1656
1285
            character sets with mbmaxlen longer than 2
1675
1304
                          is_ambiguous_field_sep) ?
1676
1305
                          field_sep_char : escape_char;
1677
1306
            tmp_buff[1]= *pos ? *pos : '0';
1678
 
            if (my_b_write(&cache,(unsigned char*) start,(uint) (pos-start)) ||
 
1307
            if (my_b_write(&cache,(unsigned char*) start,(uint32_t) (pos-start)) ||
1679
1308
                my_b_write(&cache,(unsigned char*) tmp_buff,2))
1680
1309
              goto err;
1681
1310
            start=pos+1;
1682
1311
          }
1683
1312
        }
1684
 
        if (my_b_write(&cache,(unsigned char*) start,(uint) (pos-start)))
 
1313
        if (my_b_write(&cache,(unsigned char*) start,(uint32_t) (pos-start)))
1685
1314
          goto err;
1686
1315
      }
1687
1316
      else if (my_b_write(&cache,(unsigned char*) res->ptr(),used_length))
1735
1364
 
1736
1365
 
1737
1366
int
1738
 
select_dump::prepare(List<Item> &list __attribute__((unused)),
1739
 
                     SELECT_LEX_UNIT *u)
 
1367
select_dump::prepare(List<Item> &, Select_Lex_Unit *u)
1740
1368
{
1741
1369
  unit= u;
1742
 
  return (int) ((file= create_file(thd, path, exchange, &cache)) < 0);
 
1370
  return (int) ((file= create_file(session, path, exchange, &cache)) < 0);
1743
1371
}
1744
1372
 
1745
1373
 
1756
1384
    unit->offset_limit_cnt--;
1757
1385
    return(0);
1758
1386
  }
1759
 
  if (row_count++ > 1) 
 
1387
  if (row_count++ > 1)
1760
1388
  {
1761
1389
    my_message(ER_TOO_MANY_ROWS, ER(ER_TOO_MANY_ROWS), MYF(0));
1762
1390
    goto err;
1812
1440
void select_max_min_finder_subselect::cleanup()
1813
1441
{
1814
1442
  cache= 0;
1815
 
  return;
1816
1443
}
1817
1444
 
1818
1445
 
1919
1546
     sortcmp(val1, val2, cache->collation.collation) < 0);
1920
1547
}
1921
1548
 
1922
 
bool select_exists_subselect::send_data(List<Item> &items __attribute__((unused)))
 
1549
bool select_exists_subselect::send_data(List<Item> &)
1923
1550
{
1924
1551
  Item_exists_subselect *it= (Item_exists_subselect *)item;
1925
1552
  if (unit->offset_limit_cnt)
1932
1559
  return(0);
1933
1560
}
1934
1561
 
1935
 
 
1936
 
/***************************************************************************
1937
 
  Dump of select to variables
1938
 
***************************************************************************/
1939
 
 
1940
 
int select_dumpvar::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
1941
 
{
1942
 
  unit= u;
1943
 
  
1944
 
  if (var_list.elements != list.elements)
1945
 
  {
1946
 
    my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT,
1947
 
               ER(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT), MYF(0));
1948
 
    return 1;
1949
 
  }               
1950
 
  return 0;
1951
 
}
1952
 
 
1953
 
 
1954
 
bool select_dumpvar::check_simple_select() const
1955
 
{
1956
 
  my_error(ER_SP_BAD_CURSOR_SELECT, MYF(0));
1957
 
  return true;
1958
 
}
1959
 
 
1960
 
 
1961
 
void select_dumpvar::cleanup()
1962
 
{
1963
 
  row_count= 0;
1964
 
}
1965
 
 
1966
 
 
1967
 
void Query_arena::free_items()
1968
 
{
1969
 
  Item *next;
1970
 
  /* This works because items are allocated with sql_alloc() */
1971
 
  for (; free_list; free_list= next)
1972
 
  {
1973
 
    next= free_list->next;
1974
 
    free_list->delete_self();
1975
 
  }
1976
 
  /* Postcondition: free_list is 0 */
1977
 
  return;
1978
 
}
1979
 
 
1980
 
 
1981
 
/*
1982
 
  Statement functions
1983
 
*/
1984
 
 
1985
 
Statement::Statement(LEX *lex_arg, MEM_ROOT *mem_root_arg, ulong id_arg)
1986
 
  :Query_arena(mem_root_arg),
1987
 
  id(id_arg),
1988
 
  mark_used_columns(MARK_COLUMNS_READ),
1989
 
  lex(lex_arg),
1990
 
  query(0),
1991
 
  query_length(0),
1992
 
  db(NULL),
1993
 
  db_length(0)
1994
 
{
1995
 
}
1996
 
 
1997
 
 
1998
1562
/*
1999
1563
  Don't free mem_root, as mem_root is freed in the end of dispatch_command
2000
1564
  (once for any command).
2001
1565
*/
2002
 
void THD::end_statement()
 
1566
void Session::end_statement()
2003
1567
{
2004
1568
  /* Cleanup SQL processing state to reuse this statement in next query. */
2005
1569
  lex_end(lex);
2006
1570
}
2007
1571
 
2008
 
 
2009
 
bool THD::copy_db_to(char **p_db, size_t *p_db_length)
 
1572
bool Session::copy_db_to(char **p_db, size_t *p_db_length)
2010
1573
{
2011
1574
  if (db == NULL)
2012
1575
  {
2018
1581
  return false;
2019
1582
}
2020
1583
 
2021
 
 
2022
 
bool select_dumpvar::send_data(List<Item> &items)
2023
 
{
2024
 
  List_iterator_fast<my_var> var_li(var_list);
2025
 
  List_iterator<Item> it(items);
2026
 
  Item *item;
2027
 
  my_var *mv;
2028
 
 
2029
 
  if (unit->offset_limit_cnt)
2030
 
  {                                             // using limit offset,count
2031
 
    unit->offset_limit_cnt--;
2032
 
    return(0);
2033
 
  }
2034
 
  if (row_count++) 
2035
 
  {
2036
 
    my_message(ER_TOO_MANY_ROWS, ER(ER_TOO_MANY_ROWS), MYF(0));
2037
 
    return(1);
2038
 
  }
2039
 
  while ((mv= var_li++) && (item= it++))
2040
 
  {
2041
 
    if (mv->local == 0)
2042
 
    {
2043
 
      Item_func_set_user_var *suv= new Item_func_set_user_var(mv->s, item);
2044
 
      suv->fix_fields(thd, 0);
2045
 
      suv->check(0);
2046
 
      suv->update();
2047
 
    }
2048
 
  }
2049
 
  return(thd->is_error());
2050
 
}
2051
 
 
2052
 
bool select_dumpvar::send_eof()
2053
 
{
2054
 
  if (! row_count)
2055
 
    push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
2056
 
                 ER_SP_FETCH_NO_DATA, ER(ER_SP_FETCH_NO_DATA));
2057
 
  /*
2058
 
    In order to remember the value of affected rows for ROW_COUNT()
2059
 
    function, SELECT INTO has to have an own SQLCOM.
2060
 
    TODO: split from SQLCOM_SELECT
2061
 
  */
2062
 
  ::my_ok(thd,row_count);
2063
 
  return 0;
2064
 
}
2065
 
 
2066
1584
/****************************************************************************
2067
 
  TMP_TABLE_PARAM
 
1585
  Tmp_Table_Param
2068
1586
****************************************************************************/
2069
1587
 
2070
 
void TMP_TABLE_PARAM::init()
 
1588
void Tmp_Table_Param::init()
2071
1589
{
2072
1590
  field_count= sum_func_count= func_count= hidden_field_count= 0;
2073
1591
  group_parts= group_length= group_null_parts= 0;
2075
1593
  table_charset= 0;
2076
1594
  precomputed_group_by= 0;
2077
1595
  bit_fields_as_long= 0;
2078
 
  return;
2079
 
}
2080
 
 
2081
 
 
2082
 
void thd_increment_bytes_sent(ulong length)
2083
 
{
2084
 
  THD *thd=current_thd;
2085
 
  if (likely(thd != 0))
2086
 
  { /* current_thd==0 when close_connection() calls net_send_error() */
2087
 
    thd->status_var.bytes_sent+= length;
2088
 
  }
2089
 
}
2090
 
 
2091
 
 
2092
 
void thd_increment_bytes_received(ulong length)
2093
 
{
2094
 
  current_thd->status_var.bytes_received+= length;
2095
 
}
2096
 
 
2097
 
 
2098
 
void thd_increment_net_big_packet_count(ulong length)
2099
 
{
2100
 
  current_thd->status_var.net_big_packet_count+= length;
2101
 
}
2102
 
 
2103
 
void THD::send_kill_message() const
 
1596
}
 
1597
 
 
1598
void Tmp_Table_Param::cleanup(void)
 
1599
{
 
1600
  /* Fix for Intel compiler */
 
1601
  if (copy_field)
 
1602
  {
 
1603
    delete [] copy_field;
 
1604
    save_copy_field= copy_field= 0;
 
1605
  }
 
1606
}
 
1607
 
 
1608
 
 
1609
void session_increment_bytes_sent(ulong length)
 
1610
{
 
1611
  Session *session=current_session;
 
1612
  if (likely(session != 0))
 
1613
  { /* current_session==0 when disconnect() calls net_send_error() */
 
1614
    session->status_var.bytes_sent+= length;
 
1615
  }
 
1616
}
 
1617
 
 
1618
 
 
1619
void session_increment_bytes_received(ulong length)
 
1620
{
 
1621
  current_session->status_var.bytes_received+= length;
 
1622
}
 
1623
 
 
1624
 
 
1625
void session_increment_net_big_packet_count(ulong length)
 
1626
{
 
1627
  current_session->status_var.net_big_packet_count+= length;
 
1628
}
 
1629
 
 
1630
void Session::send_kill_message() const
2104
1631
{
2105
1632
  int err= killed_errno();
2106
1633
  if (err)
2107
1634
    my_message(err, ER(err), MYF(0));
2108
1635
}
2109
1636
 
2110
 
void THD::set_status_var_init()
 
1637
void Session::set_status_var_init()
2111
1638
{
2112
1639
  memset(&status_var, 0, sizeof(status_var));
2113
1640
}
2114
1641
 
2115
 
 
2116
 
void Security_context::init()
2117
 
{
2118
 
  user= ip= 0;
2119
 
}
2120
 
 
2121
 
 
2122
 
void Security_context::destroy()
2123
 
{
2124
 
  // If not pointer to constant
2125
 
  if (user)
2126
 
  {
2127
 
    free(user);
2128
 
    user= NULL;
2129
 
  }
2130
 
  if (ip)
2131
 
  {
2132
 
    free(ip);
2133
 
    ip= NULL;
2134
 
  }
2135
 
}
2136
 
 
2137
 
 
2138
1642
void Security_context::skip_grants()
2139
1643
{
2140
1644
  /* privileges for the user are unknown everything is allowed */
2149
1653
  access to mysql.proc table to find definitions of stored routines.
2150
1654
****************************************************************************/
2151
1655
 
2152
 
void THD::reset_n_backup_open_tables_state(Open_tables_state *backup)
 
1656
void Session::reset_n_backup_open_tables_state(Open_tables_state *backup)
2153
1657
{
2154
1658
  backup->set_open_tables_state(this);
2155
1659
  reset_open_tables_state();
2156
1660
  state_flags|= Open_tables_state::BACKUPS_AVAIL;
2157
 
  return;
2158
1661
}
2159
1662
 
2160
1663
 
2161
 
void THD::restore_backup_open_tables_state(Open_tables_state *backup)
 
1664
void Session::restore_backup_open_tables_state(Open_tables_state *backup)
2162
1665
{
2163
1666
  /*
2164
1667
    Before we will throw away current open tables state we want
2165
1668
    to be sure that it was properly cleaned up.
2166
1669
  */
2167
1670
  assert(open_tables == 0 && temporary_tables == 0 &&
2168
 
              handler_tables == 0 && derived_tables == 0 &&
2169
 
              lock == 0 && locked_tables == 0);
 
1671
              derived_tables == 0 &&
 
1672
              lock == 0);
2170
1673
  set_open_tables_state(backup);
2171
 
  return;
2172
 
}
 
1674
}
 
1675
 
 
1676
 
 
1677
bool Session::set_db(const char *new_db, size_t new_db_len)
 
1678
{
 
1679
  /* Do not reallocate memory if current chunk is big enough. */
 
1680
  if (db && new_db && db_length >= new_db_len)
 
1681
    memcpy(db, new_db, new_db_len+1);
 
1682
  else
 
1683
  {
 
1684
    if (db)
 
1685
      free(db);
 
1686
    if (new_db)
 
1687
    {
 
1688
      db= (char *)malloc(new_db_len + 1);
 
1689
      if (db != NULL)
 
1690
      {
 
1691
        memcpy(db, new_db, new_db_len);
 
1692
        db[new_db_len]= 0;
 
1693
      }
 
1694
    }
 
1695
    else
 
1696
      db= NULL;
 
1697
  }
 
1698
  db_length= db ? new_db_len : 0;
 
1699
  return new_db && !db;
 
1700
}
 
1701
 
2173
1702
 
2174
1703
/**
2175
1704
  Check the killed state of a user thread
2176
 
  @param thd  user thread
 
1705
  @param session  user thread
2177
1706
  @retval 0 the user thread is active
2178
1707
  @retval 1 the user thread has been killed
2179
1708
*/
2180
 
extern "C" int thd_killed(const DRIZZLE_THD thd)
 
1709
extern "C" int session_killed(const Session *session)
2181
1710
{
2182
 
  return(thd->killed);
 
1711
  return(session->killed);
2183
1712
}
2184
1713
 
2185
1714
/**
2186
1715
  Return the thread id of a user thread
2187
 
  @param thd user thread
 
1716
  @param session user thread
2188
1717
  @return thread id
2189
1718
*/
2190
 
extern "C" unsigned long thd_get_thread_id(const DRIZZLE_THD thd)
2191
 
{
2192
 
  return((unsigned long)thd->thread_id);
2193
 
}
2194
 
 
2195
 
 
2196
 
#ifdef INNODB_COMPATIBILITY_HOOKS
2197
 
extern "C" const struct charset_info_st *thd_charset(DRIZZLE_THD thd)
2198
 
{
2199
 
  return(thd->charset());
2200
 
}
2201
 
 
2202
 
extern "C" char **thd_query(DRIZZLE_THD thd)
2203
 
{
2204
 
  return(&thd->query);
2205
 
}
2206
 
 
2207
 
extern "C" int thd_slave_thread(const DRIZZLE_THD thd)
2208
 
{
2209
 
  return(thd->slave_thread);
2210
 
}
2211
 
 
2212
 
extern "C" int thd_non_transactional_update(const DRIZZLE_THD thd)
2213
 
{
2214
 
  return(thd->transaction.all.modified_non_trans_table);
2215
 
}
2216
 
 
2217
 
extern "C" int thd_binlog_format(const DRIZZLE_THD thd)
2218
 
{
2219
 
  return (int) thd->variables.binlog_format;
2220
 
}
2221
 
 
2222
 
extern "C" void thd_mark_transaction_to_rollback(DRIZZLE_THD thd, bool all)
2223
 
{
2224
 
  mark_transaction_to_rollback(thd, all);
2225
 
}
2226
 
#endif // INNODB_COMPATIBILITY_HOOKS */
2227
 
 
 
1719
extern "C" unsigned long session_get_thread_id(const Session *session)
 
1720
{
 
1721
  return((unsigned long)session->thread_id);
 
1722
}
 
1723
 
 
1724
 
 
1725
extern "C"
 
1726
LEX_STRING *session_make_lex_string(Session *session, LEX_STRING *lex_str,
 
1727
                                const char *str, unsigned int size,
 
1728
                                int allocate_lex_string)
 
1729
{
 
1730
  return session->make_lex_string(lex_str, str, size,
 
1731
                              (bool) allocate_lex_string);
 
1732
}
 
1733
 
 
1734
extern "C" const struct charset_info_st *session_charset(Session *session)
 
1735
{
 
1736
  return(session->charset());
 
1737
}
 
1738
 
 
1739
extern "C" char **session_query(Session *session)
 
1740
{
 
1741
  return(&session->query);
 
1742
}
 
1743
 
 
1744
extern "C" int session_non_transactional_update(const Session *session)
 
1745
{
 
1746
  return(session->transaction.all.modified_non_trans_table);
 
1747
}
 
1748
 
 
1749
extern "C" void session_mark_transaction_to_rollback(Session *session, bool all)
 
1750
{
 
1751
  mark_transaction_to_rollback(session, all);
 
1752
}
2228
1753
 
2229
1754
/**
2230
1755
  Mark transaction to rollback and mark error as fatal to a sub-statement.
2231
1756
 
2232
 
  @param  thd   Thread handle
 
1757
  @param  session   Thread handle
2233
1758
  @param  all   true <=> rollback main transaction.
2234
1759
*/
2235
 
 
2236
 
void mark_transaction_to_rollback(THD *thd, bool all)
2237
 
{
2238
 
  if (thd)
2239
 
  {
2240
 
    thd->is_fatal_sub_stmt_error= true;
2241
 
    thd->transaction_rollback_request= all;
2242
 
  }
2243
 
}
2244
 
/***************************************************************************
2245
 
  Handling of XA id cacheing
2246
 
***************************************************************************/
2247
 
 
2248
 
pthread_mutex_t LOCK_xid_cache;
2249
 
HASH xid_cache;
2250
 
 
2251
 
extern "C" unsigned char *xid_get_hash_key(const unsigned char *, size_t *, bool);
2252
 
extern "C" void xid_free_hash(void *);
2253
 
 
2254
 
unsigned char *xid_get_hash_key(const unsigned char *ptr, size_t *length,
2255
 
                        bool not_used __attribute__((unused)))
2256
 
{
2257
 
  *length=((XID_STATE*)ptr)->xid.key_length();
2258
 
  return ((XID_STATE*)ptr)->xid.key();
2259
 
}
2260
 
 
2261
 
void xid_free_hash(void *ptr)
2262
 
{
2263
 
  if (!((XID_STATE*)ptr)->in_thd)
2264
 
    free((unsigned char*)ptr);
2265
 
}
2266
 
 
2267
 
bool xid_cache_init()
2268
 
{
2269
 
  pthread_mutex_init(&LOCK_xid_cache, MY_MUTEX_INIT_FAST);
2270
 
  return hash_init(&xid_cache, &my_charset_bin, 100, 0, 0,
2271
 
                   xid_get_hash_key, xid_free_hash, 0) != 0;
2272
 
}
2273
 
 
2274
 
void xid_cache_free()
2275
 
{
2276
 
  if (hash_inited(&xid_cache))
2277
 
  {
2278
 
    hash_free(&xid_cache);
2279
 
    pthread_mutex_destroy(&LOCK_xid_cache);
2280
 
  }
2281
 
}
2282
 
 
2283
 
XID_STATE *xid_cache_search(XID *xid)
2284
 
{
2285
 
  pthread_mutex_lock(&LOCK_xid_cache);
2286
 
  XID_STATE *res=(XID_STATE *)hash_search(&xid_cache, xid->key(), xid->key_length());
2287
 
  pthread_mutex_unlock(&LOCK_xid_cache);
2288
 
  return res;
2289
 
}
2290
 
 
2291
 
 
2292
 
bool xid_cache_insert(XID *xid, enum xa_states xa_state)
2293
 
{
2294
 
  XID_STATE *xs;
2295
 
  bool res;
2296
 
  pthread_mutex_lock(&LOCK_xid_cache);
2297
 
  if (hash_search(&xid_cache, xid->key(), xid->key_length()))
2298
 
    res=0;
2299
 
  else if (!(xs=(XID_STATE *)my_malloc(sizeof(*xs), MYF(MY_WME))))
2300
 
    res=1;
2301
 
  else
2302
 
  {
2303
 
    xs->xa_state=xa_state;
2304
 
    xs->xid.set(xid);
2305
 
    xs->in_thd=0;
2306
 
    res=my_hash_insert(&xid_cache, (unsigned char*)xs);
2307
 
  }
2308
 
  pthread_mutex_unlock(&LOCK_xid_cache);
2309
 
  return res;
2310
 
}
2311
 
 
2312
 
 
2313
 
bool xid_cache_insert(XID_STATE *xid_state)
2314
 
{
2315
 
  pthread_mutex_lock(&LOCK_xid_cache);
2316
 
  assert(hash_search(&xid_cache, xid_state->xid.key(),
2317
 
                          xid_state->xid.key_length())==0);
2318
 
  bool res=my_hash_insert(&xid_cache, (unsigned char*)xid_state);
2319
 
  pthread_mutex_unlock(&LOCK_xid_cache);
2320
 
  return res;
2321
 
}
2322
 
 
2323
 
 
2324
 
void xid_cache_delete(XID_STATE *xid_state)
2325
 
{
2326
 
  pthread_mutex_lock(&LOCK_xid_cache);
2327
 
  hash_delete(&xid_cache, (unsigned char *)xid_state);
2328
 
  pthread_mutex_unlock(&LOCK_xid_cache);
2329
 
}
2330
 
 
2331
 
/*
2332
 
  Implementation of interface to write rows to the binary log through the
2333
 
  thread.  The thread is responsible for writing the rows it has
2334
 
  inserted/updated/deleted.
2335
 
*/
2336
 
 
2337
 
 
2338
 
/*
2339
 
  Template member function for ensuring that there is an rows log
2340
 
  event of the apropriate type before proceeding.
2341
 
 
2342
 
  PRE CONDITION:
2343
 
    - Events of type 'RowEventT' have the type code 'type_code'.
2344
 
    
2345
 
  POST CONDITION:
2346
 
    If a non-NULL pointer is returned, the pending event for thread 'thd' will
2347
 
    be an event of type 'RowEventT' (which have the type code 'type_code')
2348
 
    will either empty or have enough space to hold 'needed' bytes.  In
2349
 
    addition, the columns bitmap will be correct for the row, meaning that
2350
 
    the pending event will be flushed if the columns in the event differ from
2351
 
    the columns suppled to the function.
2352
 
 
2353
 
  RETURNS
2354
 
    If no error, a non-NULL pending event (either one which already existed or
2355
 
    the newly created one).
2356
 
    If error, NULL.
2357
 
 */
2358
 
 
2359
 
template <class RowsEventT> Rows_log_event* 
2360
 
THD::binlog_prepare_pending_rows_event(Table* table, uint32_t serv_id,
2361
 
                                       size_t needed,
2362
 
                                       bool is_transactional,
2363
 
                                       RowsEventT *hint __attribute__((unused)))
2364
 
{
2365
 
  /* Pre-conditions */
2366
 
  assert(table->s->table_map_id != UINT32_MAX);
2367
 
 
2368
 
  /* Fetch the type code for the RowsEventT template parameter */
2369
 
  int const type_code= RowsEventT::TYPE_CODE;
2370
 
 
2371
 
  /*
2372
 
    There is no good place to set up the transactional data, so we
2373
 
    have to do it here.
2374
 
  */
2375
 
  if (binlog_setup_trx_data())
2376
 
    return(NULL);
2377
 
 
2378
 
  Rows_log_event* pending= binlog_get_pending_rows_event();
2379
 
 
2380
 
  if (unlikely(pending && !pending->is_valid()))
2381
 
    return(NULL);
2382
 
 
2383
 
  /*
2384
 
    Check if the current event is non-NULL and a write-rows
2385
 
    event. Also check if the table provided is mapped: if it is not,
2386
 
    then we have switched to writing to a new table.
2387
 
    If there is no pending event, we need to create one. If there is a pending
2388
 
    event, but it's not about the same table id, or not of the same type
2389
 
    (between Write, Update and Delete), or not the same affected columns, or
2390
 
    going to be too big, flush this event to disk and create a new pending
2391
 
    event.
2392
 
 
2393
 
    The last test is necessary for the Cluster injector to work
2394
 
    correctly. The reason is that the Cluster can inject two write
2395
 
    rows with different column bitmaps if there is an insert followed
2396
 
    by an update in the same transaction, and these are grouped into a
2397
 
    single epoch/transaction when fed to the injector.
2398
 
 
2399
 
    TODO: Fix the code so that the last test can be removed.
2400
 
  */
2401
 
  if (!pending ||
2402
 
      pending->server_id != serv_id || 
2403
 
      pending->get_table_id() != table->s->table_map_id ||
2404
 
      pending->get_type_code() != type_code || 
2405
 
      pending->get_data_size() + needed > opt_binlog_rows_event_max_size ||
2406
 
      !bitmap_cmp(pending->get_cols(), table->write_set))
2407
 
    {
2408
 
    /* Create a new RowsEventT... */
2409
 
    Rows_log_event* const
2410
 
        ev= new RowsEventT(this, table, table->s->table_map_id,
2411
 
                           is_transactional);
2412
 
    if (unlikely(!ev))
2413
 
      return(NULL);
2414
 
    ev->server_id= serv_id; // I don't like this, it's too easy to forget.
2415
 
    /*
2416
 
      flush the pending event and replace it with the newly created
2417
 
      event...
2418
 
    */
2419
 
    if (unlikely(mysql_bin_log.flush_and_set_pending_rows_event(this, ev)))
2420
 
    {
2421
 
      delete ev;
2422
 
      return(NULL);
2423
 
    }
2424
 
 
2425
 
    return(ev);               /* This is the new pending event */
2426
 
  }
2427
 
  return(pending);        /* This is the current pending event */
2428
 
}
2429
 
 
2430
 
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
2431
 
/*
2432
 
  Instantiate the versions we need, we have -fno-implicit-template as
2433
 
  compiling option.
2434
 
*/
2435
 
template Rows_log_event*
2436
 
THD::binlog_prepare_pending_rows_event(Table*, uint32_t, size_t, bool,
2437
 
                                       Write_rows_log_event*);
2438
 
 
2439
 
template Rows_log_event*
2440
 
THD::binlog_prepare_pending_rows_event(Table*, uint32_t, size_t, bool,
2441
 
                                       Delete_rows_log_event *);
2442
 
 
2443
 
template Rows_log_event* 
2444
 
THD::binlog_prepare_pending_rows_event(Table*, uint32_t, size_t, bool,
2445
 
                                       Update_rows_log_event *);
2446
 
#endif
2447
 
 
2448
 
namespace {
2449
 
  /**
2450
 
     Class to handle temporary allocation of memory for row data.
2451
 
 
2452
 
     The responsibilities of the class is to provide memory for
2453
 
     packing one or two rows of packed data (depending on what
2454
 
     constructor is called).
2455
 
 
2456
 
     In order to make the allocation more efficient for "simple" rows,
2457
 
     i.e., rows that do not contain any blobs, a pointer to the
2458
 
     allocated memory is of memory is stored in the table structure
2459
 
     for simple rows.  If memory for a table containing a blob field
2460
 
     is requested, only memory for that is allocated, and subsequently
2461
 
     released when the object is destroyed.
2462
 
 
2463
 
   */
2464
 
  class Row_data_memory {
2465
 
  public:
2466
 
    /**
2467
 
      Build an object to keep track of a block-local piece of memory
2468
 
      for storing a row of data.
2469
 
 
2470
 
      @param table
2471
 
      Table where the pre-allocated memory is stored.
2472
 
 
2473
 
      @param length
2474
 
      Length of data that is needed, if the record contain blobs.
2475
 
     */
2476
 
    Row_data_memory(Table *table, size_t const len1)
2477
 
      : m_memory(0)
2478
 
    {
2479
 
      m_alloc_checked= false;
2480
 
      allocate_memory(table, len1);
2481
 
      m_ptr[0]= has_memory() ? m_memory : 0;
2482
 
      m_ptr[1]= 0;
2483
 
    }
2484
 
 
2485
 
    Row_data_memory(Table *table, size_t const len1, size_t const len2)
2486
 
      : m_memory(0)
2487
 
    {
2488
 
      m_alloc_checked= false;
2489
 
      allocate_memory(table, len1 + len2);
2490
 
      m_ptr[0]= has_memory() ? m_memory        : 0;
2491
 
      m_ptr[1]= has_memory() ? m_memory + len1 : 0;
2492
 
    }
2493
 
 
2494
 
    ~Row_data_memory()
2495
 
    {
2496
 
      if (m_memory != 0 && m_release_memory_on_destruction)
2497
 
        free((unsigned char*) m_memory);
2498
 
    }
2499
 
 
2500
 
    /**
2501
 
       Is there memory allocated?
2502
 
 
2503
 
       @retval true There is memory allocated
2504
 
       @retval false Memory allocation failed
2505
 
     */
2506
 
    bool has_memory() const {
2507
 
      m_alloc_checked= true;
2508
 
      return m_memory != 0;
2509
 
    }
2510
 
 
2511
 
    unsigned char *slot(uint32_t s)
2512
 
    {
2513
 
      assert(s < sizeof(m_ptr)/sizeof(*m_ptr));
2514
 
      assert(m_ptr[s] != 0);
2515
 
      assert(m_alloc_checked == true);
2516
 
      return m_ptr[s];
2517
 
    }
2518
 
 
2519
 
  private:
2520
 
    void allocate_memory(Table *const table, size_t const total_length)
2521
 
    {
2522
 
      if (table->s->blob_fields == 0)
2523
 
      {
2524
 
        /*
2525
 
          The maximum length of a packed record is less than this
2526
 
          length. We use this value instead of the supplied length
2527
 
          when allocating memory for records, since we don't know how
2528
 
          the memory will be used in future allocations.
2529
 
 
2530
 
          Since table->s->reclength is for unpacked records, we have
2531
 
          to add two bytes for each field, which can potentially be
2532
 
          added to hold the length of a packed field.
2533
 
        */
2534
 
        size_t const maxlen= table->s->reclength + 2 * table->s->fields;
2535
 
 
2536
 
        /*
2537
 
          Allocate memory for two records if memory hasn't been
2538
 
          allocated. We allocate memory for two records so that it can
2539
 
          be used when processing update rows as well.
2540
 
        */
2541
 
        if (table->write_row_record == 0)
2542
 
          table->write_row_record=
2543
 
            (unsigned char *) alloc_root(&table->mem_root, 2 * maxlen);
2544
 
        m_memory= table->write_row_record;
2545
 
        m_release_memory_on_destruction= false;
2546
 
      }
2547
 
      else
2548
 
      {
2549
 
        m_memory= (unsigned char *) my_malloc(total_length, MYF(MY_WME));
2550
 
        m_release_memory_on_destruction= true;
2551
 
      }
2552
 
    }
2553
 
 
2554
 
    mutable bool m_alloc_checked;
2555
 
    bool m_release_memory_on_destruction;
2556
 
    unsigned char *m_memory;
2557
 
    unsigned char *m_ptr[2];
2558
 
  };
2559
 
}
2560
 
 
2561
 
 
2562
 
int THD::binlog_write_row(Table* table, bool is_trans, 
2563
 
                          unsigned char const *record) 
2564
 
2565
 
  assert(current_stmt_binlog_row_based && mysql_bin_log.is_open());
2566
 
 
2567
 
  /*
2568
 
    Pack records into format for transfer. We are allocating more
2569
 
    memory than needed, but that doesn't matter.
2570
 
  */
2571
 
  Row_data_memory memory(table, table->max_row_length(record));
2572
 
  if (!memory.has_memory())
2573
 
    return HA_ERR_OUT_OF_MEM;
2574
 
 
2575
 
  unsigned char *row_data= memory.slot(0);
2576
 
 
2577
 
  size_t const len= pack_row(table, table->write_set, row_data, record);
2578
 
 
2579
 
  Rows_log_event* const ev=
2580
 
    binlog_prepare_pending_rows_event(table, server_id, len, is_trans,
2581
 
                                      static_cast<Write_rows_log_event*>(0));
2582
 
 
2583
 
  if (unlikely(ev == 0))
2584
 
    return HA_ERR_OUT_OF_MEM;
2585
 
 
2586
 
  return ev->add_row_data(row_data, len);
2587
 
}
2588
 
 
2589
 
int THD::binlog_update_row(Table* table, bool is_trans,
2590
 
                           const unsigned char *before_record,
2591
 
                           const unsigned char *after_record)
2592
 
2593
 
  assert(current_stmt_binlog_row_based && mysql_bin_log.is_open());
2594
 
 
2595
 
  size_t const before_maxlen = table->max_row_length(before_record);
2596
 
  size_t const after_maxlen  = table->max_row_length(after_record);
2597
 
 
2598
 
  Row_data_memory row_data(table, before_maxlen, after_maxlen);
2599
 
  if (!row_data.has_memory())
2600
 
    return HA_ERR_OUT_OF_MEM;
2601
 
 
2602
 
  unsigned char *before_row= row_data.slot(0);
2603
 
  unsigned char *after_row= row_data.slot(1);
2604
 
 
2605
 
  size_t const before_size= pack_row(table, table->read_set, before_row,
2606
 
                                        before_record);
2607
 
  size_t const after_size= pack_row(table, table->write_set, after_row,
2608
 
                                       after_record);
2609
 
 
2610
 
  Rows_log_event* const ev=
2611
 
    binlog_prepare_pending_rows_event(table, server_id,
2612
 
                                      before_size + after_size, is_trans,
2613
 
                                      static_cast<Update_rows_log_event*>(0));
2614
 
 
2615
 
  if (unlikely(ev == 0))
2616
 
    return HA_ERR_OUT_OF_MEM;
2617
 
 
2618
 
  return
2619
 
    ev->add_row_data(before_row, before_size) ||
2620
 
    ev->add_row_data(after_row, after_size);
2621
 
}
2622
 
 
2623
 
int THD::binlog_delete_row(Table* table, bool is_trans, 
2624
 
                           unsigned char const *record)
2625
 
2626
 
  assert(current_stmt_binlog_row_based && mysql_bin_log.is_open());
2627
 
 
2628
 
  /* 
2629
 
     Pack records into format for transfer. We are allocating more
2630
 
     memory than needed, but that doesn't matter.
2631
 
  */
2632
 
  Row_data_memory memory(table, table->max_row_length(record));
2633
 
  if (unlikely(!memory.has_memory()))
2634
 
    return HA_ERR_OUT_OF_MEM;
2635
 
 
2636
 
  unsigned char *row_data= memory.slot(0);
2637
 
 
2638
 
  size_t const len= pack_row(table, table->read_set, row_data, record);
2639
 
 
2640
 
  Rows_log_event* const ev=
2641
 
    binlog_prepare_pending_rows_event(table, server_id, len, is_trans,
2642
 
                                      static_cast<Delete_rows_log_event*>(0));
2643
 
 
2644
 
  if (unlikely(ev == 0))
2645
 
    return HA_ERR_OUT_OF_MEM;
2646
 
 
2647
 
  return ev->add_row_data(row_data, len);
2648
 
}
2649
 
 
2650
 
 
2651
 
int THD::binlog_flush_pending_rows_event(bool stmt_end)
2652
 
{
2653
 
  /*
2654
 
    We shall flush the pending event even if we are not in row-based
2655
 
    mode: it might be the case that we left row-based mode before
2656
 
    flushing anything (e.g., if we have explicitly locked tables).
2657
 
   */
2658
 
  if (!mysql_bin_log.is_open())
2659
 
    return(0);
2660
 
 
2661
 
  /*
2662
 
    Mark the event as the last event of a statement if the stmt_end
2663
 
    flag is set.
2664
 
  */
2665
 
  int error= 0;
2666
 
  if (Rows_log_event *pending= binlog_get_pending_rows_event())
2667
 
  {
2668
 
    if (stmt_end)
2669
 
    {
2670
 
      pending->set_flags(Rows_log_event::STMT_END_F);
2671
 
      pending->flags|= LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F;
2672
 
      binlog_table_maps= 0;
2673
 
    }
2674
 
 
2675
 
    error= mysql_bin_log.flush_and_set_pending_rows_event(this, 0);
2676
 
  }
2677
 
 
2678
 
  return(error);
2679
 
}
2680
 
 
2681
 
 
2682
 
/*
2683
 
  Member function that will log query, either row-based or
2684
 
  statement-based depending on the value of the 'current_stmt_binlog_row_based'
2685
 
  the value of the 'qtype' flag.
2686
 
 
2687
 
  This function should be called after the all calls to ha_*_row()
2688
 
  functions have been issued, but before tables are unlocked and
2689
 
  closed.
2690
 
 
2691
 
  OBSERVE
2692
 
    There shall be no writes to any system table after calling
2693
 
    binlog_query(), so these writes has to be moved to before the call
2694
 
    of binlog_query() for correct functioning.
2695
 
 
2696
 
    This is necessesary not only for RBR, but the master might crash
2697
 
    after binlogging the query but before changing the system tables.
2698
 
    This means that the slave and the master are not in the same state
2699
 
    (after the master has restarted), so therefore we have to
2700
 
    eliminate this problem.
2701
 
 
2702
 
  RETURN VALUE
2703
 
    Error code, or 0 if no error.
2704
 
*/
2705
 
int THD::binlog_query(THD::enum_binlog_query_type qtype, char const *query_arg,
2706
 
                      ulong query_len, bool is_trans, bool suppress_use,
2707
 
                      THD::killed_state killed_status_arg)
2708
 
{
2709
 
  assert(query_arg && mysql_bin_log.is_open());
2710
 
 
2711
 
  if (int error= binlog_flush_pending_rows_event(true))
2712
 
    return(error);
2713
 
 
2714
 
  /*
2715
 
    If we are in statement mode and trying to log an unsafe statement,
2716
 
    we should print a warning.
2717
 
  */
2718
 
  if (lex->is_stmt_unsafe() &&
2719
 
      variables.binlog_format == BINLOG_FORMAT_STMT)
2720
 
  {
2721
 
    assert(this->query != NULL);
2722
 
    push_warning(this, DRIZZLE_ERROR::WARN_LEVEL_WARN,
2723
 
                 ER_BINLOG_UNSAFE_STATEMENT,
2724
 
                 ER(ER_BINLOG_UNSAFE_STATEMENT));
2725
 
    if (!(binlog_flags & BINLOG_FLAG_UNSAFE_STMT_PRINTED))
2726
 
    {
2727
 
      char warn_buf[DRIZZLE_ERRMSG_SIZE];
2728
 
      snprintf(warn_buf, DRIZZLE_ERRMSG_SIZE, "%s Statement: %s",
2729
 
               ER(ER_BINLOG_UNSAFE_STATEMENT), this->query);
2730
 
      sql_print_warning(warn_buf);
2731
 
      binlog_flags|= BINLOG_FLAG_UNSAFE_STMT_PRINTED;
2732
 
    }
2733
 
  }
2734
 
 
2735
 
  switch (qtype) {
2736
 
  case THD::ROW_QUERY_TYPE:
2737
 
    if (current_stmt_binlog_row_based)
2738
 
      return(0);
2739
 
    /* Otherwise, we fall through */
2740
 
  case THD::DRIZZLE_QUERY_TYPE:
2741
 
    /*
2742
 
      Using this query type is a conveniece hack, since we have been
2743
 
      moving back and forth between using RBR for replication of
2744
 
      system tables and not using it.
2745
 
 
2746
 
      Make sure to change in check_table_binlog_row_based() according
2747
 
      to how you treat this.
2748
 
    */
2749
 
  case THD::STMT_QUERY_TYPE:
2750
 
    /*
2751
 
      The DRIZZLE_LOG::write() function will set the STMT_END_F flag and
2752
 
      flush the pending rows event if necessary.
2753
 
     */
2754
 
    {
2755
 
      Query_log_event qinfo(this, query_arg, query_len, is_trans, suppress_use,
2756
 
                            killed_status_arg);
2757
 
      qinfo.flags|= LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F;
2758
 
      /*
2759
 
        Binlog table maps will be irrelevant after a Query_log_event
2760
 
        (they are just removed on the slave side) so after the query
2761
 
        log event is written to the binary log, we pretend that no
2762
 
        table maps were written.
2763
 
       */
2764
 
      int error= mysql_bin_log.write(&qinfo);
2765
 
      binlog_table_maps= 0;
2766
 
      return(error);
2767
 
    }
2768
 
    break;
2769
 
 
2770
 
  case THD::QUERY_TYPE_COUNT:
2771
 
  default:
2772
 
    assert(0 <= qtype && qtype < QUERY_TYPE_COUNT);
2773
 
  }
2774
 
  return(0);
2775
 
}
2776
 
 
2777
 
bool Discrete_intervals_list::append(uint64_t start, uint64_t val,
2778
 
                                 uint64_t incr)
2779
 
{
2780
 
  /* first, see if this can be merged with previous */
2781
 
  if ((head == NULL) || tail->merge_if_contiguous(start, val, incr))
2782
 
  {
2783
 
    /* it cannot, so need to add a new interval */
2784
 
    Discrete_interval *new_interval= new Discrete_interval(start, val, incr);
2785
 
    return(append(new_interval));
2786
 
  }
2787
 
  return(0);
2788
 
}
2789
 
 
2790
 
bool Discrete_intervals_list::append(Discrete_interval *new_interval)
2791
 
{
2792
 
  if (unlikely(new_interval == NULL))
2793
 
    return(1);
2794
 
  if (head == NULL)
2795
 
    head= current= new_interval;
2796
 
  else
2797
 
    tail->next= new_interval;
2798
 
  tail= new_interval;
2799
 
  elements++;
2800
 
  return(0);
 
1760
void mark_transaction_to_rollback(Session *session, bool all)
 
1761
{
 
1762
  if (session)
 
1763
  {
 
1764
    session->is_fatal_sub_stmt_error= true;
 
1765
    session->transaction_rollback_request= all;
 
1766
  }
 
1767
}
 
1768
 
 
1769
void Session::disconnect(uint32_t errcode, bool should_lock)
 
1770
{
 
1771
  /* Allow any plugins to cleanup their session variables */
 
1772
  plugin_sessionvar_cleanup(this);
 
1773
 
 
1774
  /* If necessary, log any aborted or unauthorized connections */
 
1775
  if (killed || protocol->wasAborted())
 
1776
    statistic_increment(aborted_threads, &LOCK_status);
 
1777
 
 
1778
  if (protocol->wasAborted())
 
1779
  {
 
1780
    if (! killed && variables.log_warnings > 1)
 
1781
    {
 
1782
      Security_context *sctx= &security_ctx;
 
1783
 
 
1784
      errmsg_printf(ERRMSG_LVL_WARN, ER(ER_NEW_ABORTING_CONNECTION)
 
1785
                  , thread_id
 
1786
                  , (db ? db : "unconnected")
 
1787
                  , sctx->user.empty() == false ? sctx->user.c_str() : "unauthenticated"
 
1788
                  , sctx->ip.c_str()
 
1789
                  , (main_da.is_error() ? main_da.message() : ER(ER_UNKNOWN_ERROR)));
 
1790
    }
 
1791
  }
 
1792
 
 
1793
  /* Close out our connection to the client */
 
1794
  if (should_lock)
 
1795
    (void) pthread_mutex_lock(&LOCK_thread_count);
 
1796
  killed= Session::KILL_CONNECTION;
 
1797
  if (protocol->isConnected())
 
1798
  {
 
1799
    if (errcode)
 
1800
    {
 
1801
      /*my_error(errcode, ER(errcode));*/
 
1802
      protocol->sendError(errcode, ER(errcode)); /* purecov: inspected */
 
1803
    }
 
1804
    protocol->close();
 
1805
  }
 
1806
  if (should_lock)
 
1807
    (void) pthread_mutex_unlock(&LOCK_thread_count);
 
1808
}
 
1809
 
 
1810
void Session::reset_for_next_command()
 
1811
{
 
1812
  free_list= 0;
 
1813
  select_number= 1;
 
1814
  /*
 
1815
    Those two lines below are theoretically unneeded as
 
1816
    Session::cleanup_after_query() should take care of this already.
 
1817
  */
 
1818
  auto_inc_intervals_in_cur_stmt_for_binlog.empty();
 
1819
 
 
1820
  is_fatal_error= false;
 
1821
  server_status&= ~ (SERVER_MORE_RESULTS_EXISTS |
 
1822
                          SERVER_QUERY_NO_INDEX_USED |
 
1823
                          SERVER_QUERY_NO_GOOD_INDEX_USED);
 
1824
  /*
 
1825
    If in autocommit mode and not in a transaction, reset
 
1826
    OPTION_STATUS_NO_TRANS_UPDATE | OPTION_KEEP_LOG to not get warnings
 
1827
    in ha_rollback_trans() about some tables couldn't be rolled back.
 
1828
  */
 
1829
  if (!(options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
 
1830
  {
 
1831
    options&= ~OPTION_KEEP_LOG;
 
1832
    transaction.all.modified_non_trans_table= false;
 
1833
  }
 
1834
 
 
1835
  clear_error();
 
1836
  main_da.reset_diagnostics_area();
 
1837
  total_warn_count=0;                   // Warnings for this query
 
1838
  sent_row_count= examined_row_count= 0;
 
1839
}
 
1840
 
 
1841
/*
 
1842
  Close all temporary tables created by 'CREATE TEMPORARY TABLE' for thread
 
1843
  creates one DROP TEMPORARY Table binlog event for each pseudo-thread
 
1844
*/
 
1845
 
 
1846
void Session::close_temporary_tables()
 
1847
{
 
1848
  Table *table;
 
1849
  Table *tmp_next;
 
1850
 
 
1851
  if (!temporary_tables)
 
1852
    return;
 
1853
 
 
1854
  for (table= temporary_tables; table; table= tmp_next)
 
1855
  {
 
1856
    tmp_next= table->next;
 
1857
    close_temporary(table, true, true);
 
1858
  }
 
1859
  temporary_tables= NULL;
 
1860
}
 
1861
 
 
1862
 
 
1863
/** Clear most status variables. */
 
1864
extern time_t flush_status_time;
 
1865
extern uint32_t max_used_connections;
 
1866
 
 
1867
void Session::refresh_status()
 
1868
{
 
1869
  pthread_mutex_lock(&LOCK_status);
 
1870
 
 
1871
  /* Add thread's status variabes to global status */
 
1872
  add_to_status(&global_status_var, &status_var);
 
1873
 
 
1874
  /* Reset thread's status variables */
 
1875
  memset(&status_var, 0, sizeof(status_var));
 
1876
 
 
1877
  /* Reset some global variables */
 
1878
  reset_status_vars();
 
1879
 
 
1880
  /* Reset the counters of all key caches (default and named). */
 
1881
  process_key_caches(reset_key_cache_counters);
 
1882
  flush_status_time= time((time_t*) 0);
 
1883
  max_used_connections= 1; /* We set it to one, because we know we exist */
 
1884
  pthread_mutex_unlock(&LOCK_status);
 
1885
}
 
1886
 
 
1887
#define extra_size sizeof(double)
 
1888
 
 
1889
user_var_entry *Session::getVariable(LEX_STRING &name, bool create_if_not_exists)
 
1890
{
 
1891
  user_var_entry *entry= NULL;
 
1892
 
 
1893
  assert(name.length == strlen (name.str));
 
1894
  entry= (user_var_entry*) hash_search(&user_vars, (unsigned char*) name.str, name.length);
 
1895
 
 
1896
  if ((entry == NULL) && create_if_not_exists)
 
1897
  {
 
1898
    uint32_t size=ALIGN_SIZE(sizeof(user_var_entry))+name.length+1+extra_size;
 
1899
    if (!hash_inited(&user_vars))
 
1900
      return 0;
 
1901
    if (!(entry = (user_var_entry*) malloc(size)))
 
1902
      return 0;
 
1903
    entry->name.str=(char*) entry+ ALIGN_SIZE(sizeof(user_var_entry))+
 
1904
      extra_size;
 
1905
    entry->name.length=name.length;
 
1906
    entry->value=0;
 
1907
    entry->length=0;
 
1908
    entry->update_query_id=0;
 
1909
    entry->collation.set(NULL, DERIVATION_IMPLICIT);
 
1910
    entry->unsigned_flag= 0;
 
1911
    /*
 
1912
      If we are here, we were called from a SET or a query which sets a
 
1913
      variable. Imagine it is this:
 
1914
      INSERT INTO t SELECT @a:=10, @a:=@a+1.
 
1915
      Then when we have a Item_func_get_user_var (because of the @a+1) so we
 
1916
      think we have to write the value of @a to the binlog. But before that,
 
1917
      we have a Item_func_set_user_var to create @a (@a:=10), in this we mark
 
1918
      the variable as "already logged" (line below) so that it won't be logged
 
1919
      by Item_func_get_user_var (because that's not necessary).
 
1920
    */
 
1921
    entry->used_query_id= query_id;
 
1922
    entry->type=STRING_RESULT;
 
1923
    memcpy(entry->name.str, name.str, name.length+1);
 
1924
    if (my_hash_insert(&user_vars, (unsigned char*) entry))
 
1925
    {
 
1926
      assert(1);
 
1927
      free((char*) entry);
 
1928
      return 0;
 
1929
    }
 
1930
 
 
1931
  }
 
1932
 
 
1933
  return entry;
 
1934
}
 
1935
 
 
1936
void Session::mark_temp_tables_as_free_for_reuse()
 
1937
{
 
1938
  for (Table *table= temporary_tables ; table ; table= table->next)
 
1939
  {
 
1940
    if (table->query_id == query_id)
 
1941
    {
 
1942
      table->query_id= 0;
 
1943
      table->file->ha_reset();
 
1944
    }
 
1945
  }
 
1946
}
 
1947
 
 
1948
void Session::mark_used_tables_as_free_for_reuse(Table *table)
 
1949
{
 
1950
  for (; table ; table= table->next)
 
1951
  {
 
1952
    if (table->query_id == query_id)
 
1953
    {
 
1954
      table->query_id= 0;
 
1955
      table->file->ha_reset();
 
1956
    }
 
1957
  }
 
1958
}
 
1959
 
 
1960
/*
 
1961
  Unlocks tables and frees derived tables.
 
1962
  Put all normal tables used by thread in free list.
 
1963
 
 
1964
  It will only close/mark as free for reuse tables opened by this
 
1965
  substatement, it will also check if we are closing tables after
 
1966
  execution of complete query (i.e. we are on upper level) and will
 
1967
  leave prelocked mode if needed.
 
1968
*/
 
1969
void Session::close_thread_tables()
 
1970
{
 
1971
  Table *table;
 
1972
 
 
1973
  /*
 
1974
    We are assuming here that session->derived_tables contains ONLY derived
 
1975
    tables for this substatement. i.e. instead of approach which uses
 
1976
    query_id matching for determining which of the derived tables belong
 
1977
    to this substatement we rely on the ability of substatements to
 
1978
    save/restore session->derived_tables during their execution.
 
1979
 
 
1980
    TODO: Probably even better approach is to simply associate list of
 
1981
          derived tables with (sub-)statement instead of thread and destroy
 
1982
          them at the end of its execution.
 
1983
  */
 
1984
  if (derived_tables)
 
1985
  {
 
1986
    Table *next;
 
1987
    /*
 
1988
      Close all derived tables generated in queries like
 
1989
      SELECT * FROM (SELECT * FROM t1)
 
1990
    */
 
1991
    for (table= derived_tables ; table ; table= next)
 
1992
    {
 
1993
      next= table->next;
 
1994
      table->free_tmp_table(this);
 
1995
    }
 
1996
    derived_tables= 0;
 
1997
  }
 
1998
 
 
1999
  /*
 
2000
    Mark all temporary tables used by this statement as free for reuse.
 
2001
  */
 
2002
  mark_temp_tables_as_free_for_reuse();
 
2003
  /*
 
2004
    Let us commit transaction for statement. Since in 5.0 we only have
 
2005
    one statement transaction and don't allow several nested statement
 
2006
    transactions this call will do nothing if we are inside of stored
 
2007
    function or trigger (i.e. statement transaction is already active and
 
2008
    does not belong to statement for which we do close_thread_tables()).
 
2009
    TODO: This should be fixed in later releases.
 
2010
   */
 
2011
  if (!(state_flags & Open_tables_state::BACKUPS_AVAIL))
 
2012
  {
 
2013
    main_da.can_overwrite_status= true;
 
2014
    ha_autocommit_or_rollback(this, is_error());
 
2015
    main_da.can_overwrite_status= false;
 
2016
    transaction.stmt.reset();
 
2017
  }
 
2018
 
 
2019
  if (lock)
 
2020
  {
 
2021
    /*
 
2022
      For RBR we flush the pending event just before we unlock all the
 
2023
      tables.  This means that we are at the end of a topmost
 
2024
      statement, so we ensure that the STMT_END_F flag is set on the
 
2025
      pending event.  For statements that are *inside* stored
 
2026
      functions, the pending event will not be flushed: that will be
 
2027
      handled either before writing a query log event (inside
 
2028
      binlog_query()) or when preparing a pending event.
 
2029
     */
 
2030
    mysql_unlock_tables(this, lock);
 
2031
    lock= 0;
 
2032
  }
 
2033
  /*
 
2034
    Note that we need to hold LOCK_open while changing the
 
2035
    open_tables list. Another thread may work on it.
 
2036
    (See: remove_table_from_cache(), mysql_wait_completed_table())
 
2037
    Closing a MERGE child before the parent would be fatal if the
 
2038
    other thread tries to abort the MERGE lock in between.
 
2039
  */
 
2040
  if (open_tables)
 
2041
    close_open_tables();
 
2042
}
 
2043
 
 
2044
void Session::close_tables_for_reopen(TableList **tables)
 
2045
{
 
2046
  /*
 
2047
    If table list consists only from tables from prelocking set, table list
 
2048
    for new attempt should be empty, so we have to update list's root pointer.
 
2049
  */
 
2050
  if (lex->first_not_own_table() == *tables)
 
2051
    *tables= 0;
 
2052
  lex->chop_off_not_own_tables();
 
2053
  for (TableList *tmp= *tables; tmp; tmp= tmp->next_global)
 
2054
    tmp->table= 0;
 
2055
  close_thread_tables();
 
2056
}
 
2057
 
 
2058
int Session::open_and_lock_tables(TableList *tables)
 
2059
{
 
2060
  uint32_t counter;
 
2061
  bool need_reopen;
 
2062
 
 
2063
  for ( ; ; )
 
2064
  {
 
2065
    if (open_tables_from_list(&tables, &counter, 0))
 
2066
      return -1;
 
2067
 
 
2068
    if (!lock_tables(this, tables, counter, &need_reopen))
 
2069
      break;
 
2070
    if (!need_reopen)
 
2071
      return -1;
 
2072
    close_tables_for_reopen(&tables);
 
2073
  }
 
2074
  if ((mysql_handle_derived(lex, &mysql_derived_prepare) ||
 
2075
       (fill_derived_tables() &&
 
2076
        mysql_handle_derived(lex, &mysql_derived_filling))))
 
2077
    return 1; /* purecov: inspected */
 
2078
 
 
2079
  return 0;
 
2080
}
 
2081
 
 
2082
bool Session::open_normal_and_derived_tables(TableList *tables, uint32_t flags)
 
2083
{
 
2084
  uint32_t counter;
 
2085
  assert(!(fill_derived_tables()));
 
2086
  if (open_tables_from_list(&tables, &counter, flags) ||
 
2087
      mysql_handle_derived(lex, &mysql_derived_prepare))
 
2088
    return true; /* purecov: inspected */
 
2089
  return false;
2801
2090
}