1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2008 Sun Microsystems
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.
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.
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
1
/* Copyright (C) 2000-2006 MySQL AB
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.
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.
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 */
21
17
/*****************************************************************************
23
** This file implements classes defined in session.h
19
** This file implements classes defined in sql_class.h
24
20
** Especially the classes to handle a result from a select
26
22
*****************************************************************************/
27
#include <drizzled/server_includes.h>
28
#include <drizzled/session.h>
24
#ifdef USE_PRAGMA_IMPLEMENTATION
25
#pragma implementation // gcc: Class implementation
28
#include "mysql_priv.h"
30
#include "rpl_record.h"
32
#include <my_bitmap.h>
33
#include "log_event.h"
29
35
#include <sys/stat.h>
30
#include <mysys/thr_alarm.h>
31
#include <mysys/mysys_err.h>
32
#include <drizzled/error.h>
33
#include <drizzled/query_id.h>
34
#include <drizzled/data_home.h>
35
#include <drizzled/sql_base.h>
36
#include <drizzled/lock.h>
37
#include <drizzled/item/cache.h>
38
#include <drizzled/item/float.h>
39
#include <drizzled/item/return_int.h>
40
#include <drizzled/item/empty_string.h>
41
#include <drizzled/show.h>
42
#include <drizzled/plugin_scheduling.h>
36
#include <thr_alarm.h>
37
#include <mysys_err.h>
44
extern scheduling_st thread_scheduler;
46
40
The following is used to initialise Table_ident with a internal
283
int session_in_lock_tables(const Session *session)
285
return test(session->in_lock_tables);
290
int session_tablespace_op(const Session *session)
292
return test(session->tablespace_op);
297
Set the process info field of the Session structure.
299
This function is used by plug-ins. Internally, the
300
Session::set_proc_info() function should be used.
302
@see Session::set_proc_info
305
set_session_proc_info(Session *session, const char *info)
307
session->set_proc_info(info);
311
const char *get_session_proc_info(Session *session)
313
return session->get_proc_info();
317
void **session_ha_data(const Session *session, const struct handlerton *hton)
319
return (void **) &session->ha_data[hton->slot].ha_ptr;
323
int64_t session_test_options(const Session *session, int64_t test_options)
325
return session->options & test_options;
329
int session_sql_command(const Session *session)
331
return (int) session->lex->sql_command;
335
int session_tx_isolation(const Session *session)
337
return (int) session->variables.tx_isolation;
341
void session_inc_row_count(Session *session)
343
session->row_count++;
347
Clear this diagnostics area.
227
int thd_in_lock_tables(const THD *thd)
229
return test(thd->in_lock_tables);
234
int thd_tablespace_op(const THD *thd)
236
return test(thd->tablespace_op);
241
const char *set_thd_proc_info(THD *thd, const char *info,
242
const char *calling_function,
243
const char *calling_file,
244
const unsigned int calling_line)
246
const char *old_info= thd->proc_info;
247
DBUG_PRINT("proc_info", ("%s:%d %s", calling_file, calling_line,
248
(info != NULL) ? info : "(null)"));
249
thd->proc_info= info;
254
void **thd_ha_data(const THD *thd, const struct handlerton *hton)
256
return (void **) &thd->ha_data[hton->slot].ha_ptr;
260
long long thd_test_options(const THD *thd, long long test_options)
262
return thd->options & test_options;
266
int thd_sql_command(const THD *thd)
268
return (int) thd->lex->sql_command;
272
int thd_tx_isolation(const THD *thd)
274
return (int) thd->variables.tx_isolation;
278
void thd_inc_row_count(THD *thd)
284
Dumps a text description of a thread, its security context
285
(user, host) and the current query.
288
thd_security_context()
289
thd current thread context
290
buffer pointer to preferred result buffer
291
length length of buffer
292
max_query_len how many chars of query to copy (0 for all)
298
char *thd_security_context(THD *thd, char *buffer, unsigned int length,
299
unsigned int max_query_len)
301
String str(buffer, length, &my_charset_latin1);
302
const Security_context *sctx= &thd->main_security_ctx;
306
len= my_snprintf(header, sizeof(header),
307
"MySQL thread id %lu, query id %lu",
308
thd->thread_id, (ulong) thd->query_id);
310
str.append(header, len);
315
str.append(sctx->host);
321
str.append(sctx->ip);
327
str.append(sctx->user);
333
str.append(thd->proc_info);
338
if (max_query_len < 1)
339
len= thd->query_length;
341
len= min(thd->query_length, max_query_len);
343
str.append(thd->query, len);
345
if (str.c_ptr_safe() == buffer)
347
return thd->strmake(str.ptr(), str.length());
351
Clear this diagnostics area.
349
353
Normally called at the end of a statement.
567
void Session::push_internal_handler(Internal_error_handler *handler)
611
void THD::push_internal_handler(Internal_error_handler *handler)
570
614
TODO: The current implementation is limited to 1 handler at a time only.
571
Session and sp_rcontext need to be modified to use a common handler stack.
615
THD and sp_rcontext need to be modified to use a common handler stack.
573
assert(m_internal_handler == NULL);
617
DBUG_ASSERT(m_internal_handler == NULL);
574
618
m_internal_handler= handler;
578
bool Session::handle_error(uint32_t sql_errno, const char *message,
579
DRIZZLE_ERROR::enum_warning_level level)
622
bool THD::handle_error(uint sql_errno, const char *message,
623
MYSQL_ERROR::enum_warning_level level)
581
625
if (m_internal_handler)
583
627
return m_internal_handler->handle_error(sql_errno, message, level, this);
586
return false; // 'false', as per coding style
630
return FALSE; // 'FALSE', as per coding style
590
void Session::pop_internal_handler()
634
void THD::pop_internal_handler()
592
assert(m_internal_handler != NULL);
636
DBUG_ASSERT(m_internal_handler != NULL);
593
637
m_internal_handler= NULL;
596
#if defined(__cplusplus)
600
void *session_alloc(Session *session, unsigned int size)
602
return session->alloc(size);
605
void *session_calloc(Session *session, unsigned int size)
607
return session->calloc(size);
610
char *session_strdup(Session *session, const char *str)
612
return session->strdup(str);
615
char *session_strmake(Session *session, const char *str, unsigned int size)
617
return session->strmake(str, size);
620
void *session_memdup(Session *session, const void* str, unsigned int size)
622
return session->memdup(str, size);
625
void session_get_xid(const Session *session, DRIZZLE_XID *xid)
627
*xid = *(DRIZZLE_XID *) &session->transaction.xid_state.xid;
630
#if defined(__cplusplus)
641
void *thd_alloc(MYSQL_THD thd, unsigned int size)
643
return thd->alloc(size);
647
void *thd_calloc(MYSQL_THD thd, unsigned int size)
649
return thd->calloc(size);
653
char *thd_strdup(MYSQL_THD thd, const char *str)
655
return thd->strdup(str);
659
char *thd_strmake(MYSQL_THD thd, const char *str, unsigned int size)
661
return thd->strmake(str, size);
665
LEX_STRING *thd_make_lex_string(THD *thd, LEX_STRING *lex_str,
666
const char *str, unsigned int size,
667
int allocate_lex_string)
669
return thd->make_lex_string(lex_str, str, size,
670
(bool) allocate_lex_string);
674
void *thd_memdup(MYSQL_THD thd, const void* str, unsigned int size)
676
return thd->memdup(str, size);
680
void thd_get_xid(const MYSQL_THD thd, MYSQL_XID *xid)
682
*xid = *(MYSQL_XID *) &thd->transaction.xid_state.xid;
635
686
Init common variables that has to be reset on start and on change_user
638
void Session::init(void)
640
691
pthread_mutex_lock(&LOCK_global_system_variables);
641
plugin_sessionvar_init(this);
642
variables.time_format= date_time_format_copy((Session*) 0,
692
plugin_thdvar_init(this);
693
variables.time_format= date_time_format_copy((THD*) 0,
643
694
variables.time_format);
644
variables.date_format= date_time_format_copy((Session*) 0,
695
variables.date_format= date_time_format_copy((THD*) 0,
645
696
variables.date_format);
646
variables.datetime_format= date_time_format_copy((Session*) 0,
697
variables.datetime_format= date_time_format_copy((THD*) 0,
647
698
variables.datetime_format);
649
700
variables= global_system_variables above has reset
1220
void Session::rollback_item_tree_changes()
1352
void THD::rollback_item_tree_changes()
1222
1354
I_List_iterator<Item_change_record> it(change_list);
1223
1355
Item_change_record *change;
1356
DBUG_ENTER("rollback_item_tree_changes");
1225
1358
while ((change= it++))
1226
1359
*change->place= change->old_value;
1227
1360
/* We can forget about changes memory: it's allocated in runtime memroot */
1228
1361
change_list.empty();
1367
Check that the endpoint is still available.
1370
bool THD::vio_is_connected()
1374
/* End of input is signaled by poll if the socket is aborted. */
1375
if (vio_poll_read(net.vio, 0))
1378
/* Socket is aborted if signaled but no data is available. */
1379
if (vio_peek_read(net.vio, &bytes))
1382
return bytes ? TRUE : FALSE;
1386
/*****************************************************************************
1387
** Functions to provide a interface to select results
1388
*****************************************************************************/
1390
select_result::select_result()
1395
void select_result::send_error(uint errcode,const char *err)
1397
my_message(errcode, err, MYF(0));
1401
void select_result::cleanup()
1406
bool select_result::check_simple_select() const
1408
my_error(ER_SP_BAD_CURSOR_QUERY, MYF(0));
1413
static String default_line_term("\n",default_charset_info);
1414
static String default_escaped("\\",default_charset_info);
1415
static String default_field_term("\t",default_charset_info);
1416
static String default_xml_row_term("<row>", default_charset_info);
1418
sql_exchange::sql_exchange(char *name, bool flag,
1419
enum enum_filetype filetype_arg)
1420
:file_name(name), opt_enclosed(0), dumpfile(flag), skip_lines(0)
1422
filetype= filetype_arg;
1423
field_term= &default_field_term;
1424
enclosed= line_start= &my_empty_string;
1425
line_term= filetype == FILETYPE_CSV ?
1426
&default_line_term : &default_xml_row_term;
1427
escaped= &default_escaped;
1431
bool select_send::send_fields(List<Item> &list, uint flags)
1434
if (!(res= thd->protocol->send_fields(&list, flags)))
1435
is_result_set_started= 1;
1439
void select_send::abort()
1441
DBUG_ENTER("select_send::abort");
1447
Cleanup an instance of this class for re-use
1448
at next execution of a prepared statement/
1449
stored procedure statement.
1452
void select_send::cleanup()
1454
is_result_set_started= FALSE;
1457
/* Send data to client. Returns 0 if ok */
1459
bool select_send::send_data(List<Item> &items)
1461
if (unit->offset_limit_cnt)
1462
{ // using limit offset,count
1463
unit->offset_limit_cnt--;
1468
We may be passing the control from mysqld to the client: release the
1469
InnoDB adaptive hash S-latch to avoid thread deadlocks if it was reserved
1472
ha_release_temporary_latches(thd);
1474
List_iterator_fast<Item> li(items);
1475
Protocol *protocol= thd->protocol;
1476
char buff[MAX_FIELD_WIDTH];
1477
String buffer(buff, sizeof(buff), &my_charset_bin);
1478
DBUG_ENTER("select_send::send_data");
1480
protocol->prepare_for_resend();
1484
if (item->send(protocol, &buffer))
1486
protocol->free(); // Free used buffer
1487
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
1491
thd->sent_row_count++;
1492
if (thd->is_error())
1494
protocol->remove_last_row();
1498
DBUG_RETURN(protocol->write());
1502
bool select_send::send_eof()
1505
We may be passing the control from mysqld to the client: release the
1506
InnoDB adaptive hash S-latch to avoid thread deadlocks if it was reserved
1509
ha_release_temporary_latches(thd);
1511
/* Unlock tables before sending packet to gain some speed */
1514
mysql_unlock_tables(thd, thd->lock);
1518
is_result_set_started= 0;
1909
2278
List_iterator<Item> it(items);
2281
DBUG_ENTER("select_dumpvar::send_data");
1913
2283
if (unit->offset_limit_cnt)
1914
2284
{ // using limit offset,count
1915
2285
unit->offset_limit_cnt--;
1920
2290
my_message(ER_TOO_MANY_ROWS, ER(ER_TOO_MANY_ROWS), MYF(0));
1923
2293
while ((mv= var_li++) && (item= it++))
1925
2295
if (mv->local == 0)
1927
2297
Item_func_set_user_var *suv= new Item_func_set_user_var(mv->s, item);
1928
suv->fix_fields(session, 0);
2298
suv->fix_fields(thd, 0);
1933
return(session->is_error());
2303
DBUG_RETURN(thd->is_error());
1936
2306
bool select_dumpvar::send_eof()
1938
2308
if (! row_count)
1939
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
2309
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
1940
2310
ER_SP_FETCH_NO_DATA, ER(ER_SP_FETCH_NO_DATA));
1942
2312
In order to remember the value of affected rows for ROW_COUNT()
1943
2313
function, SELECT INTO has to have an own SQLCOM.
1944
2314
TODO: split from SQLCOM_SELECT
1946
session->my_ok(row_count);
2316
::my_ok(thd,row_count);
1950
2320
/****************************************************************************
1952
2322
****************************************************************************/
1954
void Tmp_Table_Param::init()
2324
void TMP_TABLE_PARAM::init()
2326
DBUG_ENTER("TMP_TABLE_PARAM::init");
2327
DBUG_PRINT("enter", ("this: 0x%lx", (ulong)this));
1956
2328
field_count= sum_func_count= func_count= hidden_field_count= 0;
1957
2329
group_parts= group_length= group_null_parts= 0;
1958
2330
quick_group= 1;
1959
2331
table_charset= 0;
1960
2332
precomputed_group_by= 0;
1961
2333
bit_fields_as_long= 0;
1965
void Tmp_Table_Param::cleanup(void)
1967
/* Fix for Intel compiler */
1970
delete [] copy_field;
1971
save_copy_field= copy_field= 0;
1976
void session_increment_bytes_sent(ulong length)
1978
Session *session=current_session;
1979
if (likely(session != 0))
1980
{ /* current_session==0 when close_connection() calls net_send_error() */
1981
session->status_var.bytes_sent+= length;
1986
void session_increment_bytes_received(ulong length)
1988
current_session->status_var.bytes_received+= length;
1992
void session_increment_net_big_packet_count(ulong length)
1994
current_session->status_var.net_big_packet_count+= length;
1997
void Session::send_kill_message() const
1999
int err= killed_errno();
2001
my_message(err, ER(err), MYF(0));
2004
void Session::set_status_var_init()
2006
memset(&status_var, 0, sizeof(status_var));
2338
void thd_increment_bytes_sent(ulong length)
2340
THD *thd=current_thd;
2341
if (likely(thd != 0))
2342
{ /* current_thd==0 when close_connection() calls net_send_error() */
2343
thd->status_var.bytes_sent+= length;
2348
void thd_increment_bytes_received(ulong length)
2350
current_thd->status_var.bytes_received+= length;
2354
void thd_increment_net_big_packet_count(ulong length)
2356
current_thd->status_var.net_big_packet_count+= length;
2360
void THD::set_status_var_init()
2362
bzero((char*) &status_var, sizeof(status_var));
2366
void Security_context::init()
2368
host= user= priv_user= ip= 0;
2369
host_or_ip= "connecting host";
2374
void Security_context::destroy()
2376
// If not pointer to constant
2377
if (host != my_localhost)
2009
2384
void Security_context::skip_grants()
2011
2386
/* privileges for the user are unknown everything is allowed */
2387
host_or_ip= (char *)"";
2388
priv_user= (char *)"";
2020
2398
access to mysql.proc table to find definitions of stored routines.
2021
2399
****************************************************************************/
2023
void Session::reset_n_backup_open_tables_state(Open_tables_state *backup)
2401
void THD::reset_n_backup_open_tables_state(Open_tables_state *backup)
2403
DBUG_ENTER("reset_n_backup_open_tables_state");
2025
2404
backup->set_open_tables_state(this);
2026
2405
reset_open_tables_state();
2027
2406
state_flags|= Open_tables_state::BACKUPS_AVAIL;
2032
void Session::restore_backup_open_tables_state(Open_tables_state *backup)
2411
void THD::restore_backup_open_tables_state(Open_tables_state *backup)
2413
DBUG_ENTER("restore_backup_open_tables_state");
2035
2415
Before we will throw away current open tables state we want
2036
2416
to be sure that it was properly cleaned up.
2038
assert(open_tables == 0 && temporary_tables == 0 &&
2418
DBUG_ASSERT(open_tables == 0 && temporary_tables == 0 &&
2039
2419
handler_tables == 0 && derived_tables == 0 &&
2040
2420
lock == 0 && locked_tables == 0);
2041
2421
set_open_tables_state(backup);
2046
bool Session::set_db(const char *new_db, size_t new_db_len)
2048
/* Do not reallocate memory if current chunk is big enough. */
2049
if (db && new_db && db_length >= new_db_len)
2050
memcpy(db, new_db, new_db_len+1);
2057
db= (char *)malloc(new_db_len + 1);
2060
memcpy(db, new_db, new_db_len);
2067
db_length= db ? new_db_len : 0;
2068
return new_db && !db;
2073
2426
Check the killed state of a user thread
2074
@param session user thread
2427
@param thd user thread
2075
2428
@retval 0 the user thread is active
2076
2429
@retval 1 the user thread has been killed
2078
extern "C" int session_killed(const Session *session)
2431
extern "C" int thd_killed(const MYSQL_THD thd)
2080
return(session->killed);
2433
return(thd->killed);
2084
2437
Return the thread id of a user thread
2085
@param session user thread
2438
@param thd user thread
2086
2439
@return thread id
2088
extern "C" unsigned long session_get_thread_id(const Session *session)
2090
return((unsigned long)session->thread_id);
2095
LEX_STRING *session_make_lex_string(Session *session, LEX_STRING *lex_str,
2096
const char *str, unsigned int size,
2097
int allocate_lex_string)
2099
return session->make_lex_string(lex_str, str, size,
2100
(bool) allocate_lex_string);
2103
extern "C" const struct charset_info_st *session_charset(Session *session)
2105
return(session->charset());
2108
extern "C" char **session_query(Session *session)
2110
return(&session->query);
2113
extern "C" int session_non_transactional_update(const Session *session)
2115
return(session->transaction.all.modified_non_trans_table);
2118
extern "C" void session_mark_transaction_to_rollback(Session *session, bool all)
2120
mark_transaction_to_rollback(session, all);
2441
extern "C" unsigned long thd_get_thread_id(const MYSQL_THD thd)
2443
return((unsigned long)thd->thread_id);
2447
#ifdef INNODB_COMPATIBILITY_HOOKS
2448
extern "C" struct charset_info_st *thd_charset(MYSQL_THD thd)
2450
return(thd->charset());
2453
extern "C" char **thd_query(MYSQL_THD thd)
2455
return(&thd->query);
2458
extern "C" int thd_slave_thread(const MYSQL_THD thd)
2460
return(thd->slave_thread);
2463
extern "C" int thd_non_transactional_update(const MYSQL_THD thd)
2465
return(thd->transaction.all.modified_non_trans_table);
2468
extern "C" int thd_binlog_format(const MYSQL_THD thd)
2470
return (int) thd->variables.binlog_format;
2473
extern "C" void thd_mark_transaction_to_rollback(MYSQL_THD thd, bool all)
2475
mark_transaction_to_rollback(thd, all);
2477
#endif // INNODB_COMPATIBILITY_HOOKS */
2125
2481
Mark transaction to rollback and mark error as fatal to a sub-statement.
2127
@param session Thread handle
2128
@param all true <=> rollback main transaction.
2483
@param thd Thread handle
2484
@param all TRUE <=> rollback main transaction.
2131
void mark_transaction_to_rollback(Session *session, bool all)
2487
void mark_transaction_to_rollback(THD *thd, bool all)
2135
session->is_fatal_sub_stmt_error= true;
2136
session->transaction_rollback_request= all;
2491
thd->is_fatal_sub_stmt_error= TRUE;
2492
thd->transaction_rollback_request= all;
2139
2495
/***************************************************************************
2219
2575
void xid_cache_delete(XID_STATE *xid_state)
2221
2577
pthread_mutex_lock(&LOCK_xid_cache);
2222
hash_delete(&xid_cache, (unsigned char *)xid_state);
2578
hash_delete(&xid_cache, (uchar *)xid_state);
2223
2579
pthread_mutex_unlock(&LOCK_xid_cache);
2583
Implementation of interface to write rows to the binary log through the
2584
thread. The thread is responsible for writing the rows it has
2585
inserted/updated/deleted.
2588
#ifndef MYSQL_CLIENT
2591
Template member function for ensuring that there is an rows log
2592
event of the apropriate type before proceeding.
2595
- Events of type 'RowEventT' have the type code 'type_code'.
2598
If a non-NULL pointer is returned, the pending event for thread 'thd' will
2599
be an event of type 'RowEventT' (which have the type code 'type_code')
2600
will either empty or have enough space to hold 'needed' bytes. In
2601
addition, the columns bitmap will be correct for the row, meaning that
2602
the pending event will be flushed if the columns in the event differ from
2603
the columns suppled to the function.
2606
If no error, a non-NULL pending event (either one which already existed or
2607
the newly created one).
2611
template <class RowsEventT> Rows_log_event*
2612
THD::binlog_prepare_pending_rows_event(TABLE* table, uint32 serv_id,
2614
bool is_transactional,
2615
RowsEventT *hint __attribute__((unused)))
2617
DBUG_ENTER("binlog_prepare_pending_rows_event");
2618
/* Pre-conditions */
2619
DBUG_ASSERT(table->s->table_map_id != ~0UL);
2621
/* Fetch the type code for the RowsEventT template parameter */
2622
int const type_code= RowsEventT::TYPE_CODE;
2625
There is no good place to set up the transactional data, so we
2628
if (binlog_setup_trx_data())
2631
Rows_log_event* pending= binlog_get_pending_rows_event();
2633
if (unlikely(pending && !pending->is_valid()))
2637
Check if the current event is non-NULL and a write-rows
2638
event. Also check if the table provided is mapped: if it is not,
2639
then we have switched to writing to a new table.
2640
If there is no pending event, we need to create one. If there is a pending
2641
event, but it's not about the same table id, or not of the same type
2642
(between Write, Update and Delete), or not the same affected columns, or
2643
going to be too big, flush this event to disk and create a new pending
2646
The last test is necessary for the Cluster injector to work
2647
correctly. The reason is that the Cluster can inject two write
2648
rows with different column bitmaps if there is an insert followed
2649
by an update in the same transaction, and these are grouped into a
2650
single epoch/transaction when fed to the injector.
2652
TODO: Fix the code so that the last test can be removed.
2655
pending->server_id != serv_id ||
2656
pending->get_table_id() != table->s->table_map_id ||
2657
pending->get_type_code() != type_code ||
2658
pending->get_data_size() + needed > opt_binlog_rows_event_max_size ||
2659
!bitmap_cmp(pending->get_cols(), table->write_set))
2661
/* Create a new RowsEventT... */
2662
Rows_log_event* const
2663
ev= new RowsEventT(this, table, table->s->table_map_id,
2667
ev->server_id= serv_id; // I don't like this, it's too easy to forget.
2669
flush the pending event and replace it with the newly created
2672
if (unlikely(mysql_bin_log.flush_and_set_pending_rows_event(this, ev)))
2678
DBUG_RETURN(ev); /* This is the new pending event */
2680
DBUG_RETURN(pending); /* This is the current pending event */
2683
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
2685
Instantiate the versions we need, we have -fno-implicit-template as
2688
template Rows_log_event*
2689
THD::binlog_prepare_pending_rows_event(TABLE*, uint32, size_t, bool,
2690
Write_rows_log_event*);
2692
template Rows_log_event*
2693
THD::binlog_prepare_pending_rows_event(TABLE*, uint32, size_t, bool,
2694
Delete_rows_log_event *);
2696
template Rows_log_event*
2697
THD::binlog_prepare_pending_rows_event(TABLE*, uint32, size_t, bool,
2698
Update_rows_log_event *);
2228
2703
Class to handle temporary allocation of memory for row data.
2319
2800
if (table->write_row_record == 0)
2320
2801
table->write_row_record=
2321
(unsigned char *) alloc_root(&table->mem_root, 2 * maxlen);
2802
(uchar *) alloc_root(&table->mem_root, 2 * maxlen);
2322
2803
m_memory= table->write_row_record;
2323
m_release_memory_on_destruction= false;
2804
m_release_memory_on_destruction= FALSE;
2327
m_memory= (unsigned char *) malloc(total_length);
2328
m_release_memory_on_destruction= true;
2808
m_memory= (uchar *) my_malloc(total_length, MYF(MY_WME));
2809
m_release_memory_on_destruction= TRUE;
2332
2814
mutable bool m_alloc_checked;
2333
2816
bool m_release_memory_on_destruction;
2334
unsigned char *m_memory;
2335
unsigned char *m_ptr[2];
2339
bool Discrete_intervals_list::append(uint64_t start, uint64_t val,
2823
int THD::binlog_write_row(TABLE* table, bool is_trans,
2824
uchar const *record)
2826
DBUG_ASSERT(current_stmt_binlog_row_based && mysql_bin_log.is_open());
2829
Pack records into format for transfer. We are allocating more
2830
memory than needed, but that doesn't matter.
2832
Row_data_memory memory(table, max_row_length(table, record));
2833
if (!memory.has_memory())
2834
return HA_ERR_OUT_OF_MEM;
2836
uchar *row_data= memory.slot(0);
2838
size_t const len= pack_row(table, table->write_set, row_data, record);
2840
Rows_log_event* const ev=
2841
binlog_prepare_pending_rows_event(table, server_id, len, is_trans,
2842
static_cast<Write_rows_log_event*>(0));
2844
if (unlikely(ev == 0))
2845
return HA_ERR_OUT_OF_MEM;
2847
return ev->add_row_data(row_data, len);
2850
int THD::binlog_update_row(TABLE* table, bool is_trans,
2851
const uchar *before_record,
2852
const uchar *after_record)
2854
DBUG_ASSERT(current_stmt_binlog_row_based && mysql_bin_log.is_open());
2856
size_t const before_maxlen = max_row_length(table, before_record);
2857
size_t const after_maxlen = max_row_length(table, after_record);
2859
Row_data_memory row_data(table, before_maxlen, after_maxlen);
2860
if (!row_data.has_memory())
2861
return HA_ERR_OUT_OF_MEM;
2863
uchar *before_row= row_data.slot(0);
2864
uchar *after_row= row_data.slot(1);
2866
size_t const before_size= pack_row(table, table->read_set, before_row,
2868
size_t const after_size= pack_row(table, table->write_set, after_row,
2872
Don't print debug messages when running valgrind since they can
2873
trigger false warnings.
2876
DBUG_DUMP("before_record", before_record, table->s->reclength);
2877
DBUG_DUMP("after_record", after_record, table->s->reclength);
2878
DBUG_DUMP("before_row", before_row, before_size);
2879
DBUG_DUMP("after_row", after_row, after_size);
2882
Rows_log_event* const ev=
2883
binlog_prepare_pending_rows_event(table, server_id,
2884
before_size + after_size, is_trans,
2885
static_cast<Update_rows_log_event*>(0));
2887
if (unlikely(ev == 0))
2888
return HA_ERR_OUT_OF_MEM;
2891
ev->add_row_data(before_row, before_size) ||
2892
ev->add_row_data(after_row, after_size);
2895
int THD::binlog_delete_row(TABLE* table, bool is_trans,
2896
uchar const *record)
2898
DBUG_ASSERT(current_stmt_binlog_row_based && mysql_bin_log.is_open());
2901
Pack records into format for transfer. We are allocating more
2902
memory than needed, but that doesn't matter.
2904
Row_data_memory memory(table, max_row_length(table, record));
2905
if (unlikely(!memory.has_memory()))
2906
return HA_ERR_OUT_OF_MEM;
2908
uchar *row_data= memory.slot(0);
2910
DBUG_DUMP("table->read_set", (uchar*) table->read_set->bitmap, (table->s->fields + 7) / 8);
2911
size_t const len= pack_row(table, table->read_set, row_data, record);
2913
Rows_log_event* const ev=
2914
binlog_prepare_pending_rows_event(table, server_id, len, is_trans,
2915
static_cast<Delete_rows_log_event*>(0));
2917
if (unlikely(ev == 0))
2918
return HA_ERR_OUT_OF_MEM;
2920
return ev->add_row_data(row_data, len);
2924
int THD::binlog_flush_pending_rows_event(bool stmt_end)
2926
DBUG_ENTER("THD::binlog_flush_pending_rows_event");
2928
We shall flush the pending event even if we are not in row-based
2929
mode: it might be the case that we left row-based mode before
2930
flushing anything (e.g., if we have explicitly locked tables).
2932
if (!mysql_bin_log.is_open())
2936
Mark the event as the last event of a statement if the stmt_end
2940
if (Rows_log_event *pending= binlog_get_pending_rows_event())
2944
pending->set_flags(Rows_log_event::STMT_END_F);
2945
pending->flags|= LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F;
2946
binlog_table_maps= 0;
2949
error= mysql_bin_log.flush_and_set_pending_rows_event(this, 0);
2957
Member function that will log query, either row-based or
2958
statement-based depending on the value of the 'current_stmt_binlog_row_based'
2959
the value of the 'qtype' flag.
2961
This function should be called after the all calls to ha_*_row()
2962
functions have been issued, but before tables are unlocked and
2966
There shall be no writes to any system table after calling
2967
binlog_query(), so these writes has to be moved to before the call
2968
of binlog_query() for correct functioning.
2970
This is necessesary not only for RBR, but the master might crash
2971
after binlogging the query but before changing the system tables.
2972
This means that the slave and the master are not in the same state
2973
(after the master has restarted), so therefore we have to
2974
eliminate this problem.
2977
Error code, or 0 if no error.
2979
int THD::binlog_query(THD::enum_binlog_query_type qtype, char const *query_arg,
2980
ulong query_len, bool is_trans, bool suppress_use,
2981
THD::killed_state killed_status_arg)
2983
DBUG_ENTER("THD::binlog_query");
2984
DBUG_PRINT("enter", ("qtype: %d query: '%s'", qtype, query_arg));
2985
DBUG_ASSERT(query_arg && mysql_bin_log.is_open());
2987
if (int error= binlog_flush_pending_rows_event(TRUE))
2991
If we are in statement mode and trying to log an unsafe statement,
2992
we should print a warning.
2994
if (lex->is_stmt_unsafe() &&
2995
variables.binlog_format == BINLOG_FORMAT_STMT)
2997
DBUG_ASSERT(this->query != NULL);
2998
push_warning(this, MYSQL_ERROR::WARN_LEVEL_WARN,
2999
ER_BINLOG_UNSAFE_STATEMENT,
3000
ER(ER_BINLOG_UNSAFE_STATEMENT));
3001
if (!(binlog_flags & BINLOG_FLAG_UNSAFE_STMT_PRINTED))
3003
char warn_buf[MYSQL_ERRMSG_SIZE];
3004
my_snprintf(warn_buf, MYSQL_ERRMSG_SIZE, "%s Statement: %s",
3005
ER(ER_BINLOG_UNSAFE_STATEMENT), this->query);
3006
sql_print_warning(warn_buf);
3007
binlog_flags|= BINLOG_FLAG_UNSAFE_STMT_PRINTED;
3012
case THD::ROW_QUERY_TYPE:
3013
if (current_stmt_binlog_row_based)
3015
/* Otherwise, we fall through */
3016
case THD::MYSQL_QUERY_TYPE:
3018
Using this query type is a conveniece hack, since we have been
3019
moving back and forth between using RBR for replication of
3020
system tables and not using it.
3022
Make sure to change in check_table_binlog_row_based() according
3023
to how you treat this.
3025
case THD::STMT_QUERY_TYPE:
3027
The MYSQL_LOG::write() function will set the STMT_END_F flag and
3028
flush the pending rows event if necessary.
3031
Query_log_event qinfo(this, query_arg, query_len, is_trans, suppress_use,
3033
qinfo.flags|= LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F;
3035
Binlog table maps will be irrelevant after a Query_log_event
3036
(they are just removed on the slave side) so after the query
3037
log event is written to the binary log, we pretend that no
3038
table maps were written.
3040
int error= mysql_bin_log.write(&qinfo);
3041
binlog_table_maps= 0;
3046
case THD::QUERY_TYPE_COUNT:
3048
DBUG_ASSERT(0 <= qtype && qtype < QUERY_TYPE_COUNT);
3053
bool Discrete_intervals_list::append(ulonglong start, ulonglong val,
3056
DBUG_ENTER("Discrete_intervals_list::append");
2342
3057
/* first, see if this can be merged with previous */
2343
3058
if ((head == NULL) || tail->merge_if_contiguous(start, val, incr))
2345
3060
/* it cannot, so need to add a new interval */
2346
3061
Discrete_interval *new_interval= new Discrete_interval(start, val, incr);
2347
return(append(new_interval));
3062
DBUG_RETURN(append(new_interval));
2352
3067
bool Discrete_intervals_list::append(Discrete_interval *new_interval)
3069
DBUG_ENTER("Discrete_intervals_list::append");
2354
3070
if (unlikely(new_interval == NULL))
3072
DBUG_PRINT("info",("adding new auto_increment interval"));
2356
3073
if (head == NULL)
2357
3074
head= current= new_interval;
2359
3076
tail->next= new_interval;
2360
3077
tail= new_interval;
2368
@param session Thread handle
2369
@param errcode Error code to print to console
2370
@param should_lock 1 if we have have to lock LOCK_thread_count
2373
For the connection that is doing shutdown, this is called twice
2375
void Session::close_connection(uint32_t errcode, bool should_lock)
2379
(void) pthread_mutex_lock(&LOCK_thread_count);
2380
killed= Session::KILL_CONNECTION;
2381
if ((vio= net.vio) != 0)
2384
net_send_error(this, errcode, ER(errcode)); /* purecov: inspected */
2385
drizzleclient_net_close(&net); /* vio is freed in delete session */
2388
(void) pthread_mutex_unlock(&LOCK_thread_count);
2394
Reset Session part responsible for command processing state.
2396
This needs to be called before execution of every statement
2397
(prepared or conventional).
2398
It is not called by substatements of routines.
2401
Make it a method of Session and align its name with the rest of
2402
reset/end/start/init methods.
2404
Call it after we use Session for queries, not before.
2407
void Session::reset_for_next_command()
2412
Those two lines below are theoretically unneeded as
2413
Session::cleanup_after_query() should take care of this already.
2415
auto_inc_intervals_in_cur_stmt_for_binlog.empty();
2418
server_status&= ~ (SERVER_MORE_RESULTS_EXISTS |
2419
SERVER_QUERY_NO_INDEX_USED |
2420
SERVER_QUERY_NO_GOOD_INDEX_USED);
2422
If in autocommit mode and not in a transaction, reset
2423
OPTION_STATUS_NO_TRANS_UPDATE | OPTION_KEEP_LOG to not get warnings
2424
in ha_rollback_trans() about some tables couldn't be rolled back.
2426
if (!(options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
2428
options&= ~OPTION_KEEP_LOG;
2429
transaction.all.modified_non_trans_table= false;
2431
thread_specific_used= false;
2434
main_da.reset_diagnostics_area();
2435
total_warn_count=0; // Warnings for this query
2436
sent_row_count= examined_row_count= 0;
2443
return true if the table was created explicitly.
2445
inline bool is_user_table(Table * table)
2447
const char *name= table->s->table_name.str;
2448
return strncmp(name, TMP_FILE_PREFIX, TMP_FILE_PREFIX_LENGTH);
2452
Close all temporary tables created by 'CREATE TEMPORARY TABLE' for thread
2453
creates one DROP TEMPORARY Table binlog event for each pseudo-thread
2456
void Session::close_temporary_tables()
2461
if (!temporary_tables)
2464
for (table= temporary_tables; table; table= tmp_next)
2466
tmp_next= table->next;
2467
close_temporary(table, 1, 1);
2469
temporary_tables= 0;
3082
#endif /* !defined(MYSQL_CLIENT) */