diff options
author | unknown <cbell/Chuck@mysql_cab_desk.> | 2007-03-16 09:56:57 -0400 |
---|---|---|
committer | unknown <cbell/Chuck@mysql_cab_desk.> | 2007-03-16 09:56:57 -0400 |
commit | 62b41b5fbcf3fe8bd680e28e0064d3194daf4157 (patch) | |
tree | 15f703b3b46120a527b00e8e328eb91286163cec /sql | |
parent | 9a14d8832246a78995657efc7f7564dbc65c0559 (diff) | |
download | mariadb-git-62b41b5fbcf3fe8bd680e28e0064d3194daf4157.tar.gz |
WL#3629 - Replication of Invocation and Invoked Features
This changeset adds replication of events and user-defined functions.
There are several bug reports involved in this change:
BUG#16421, BUG#17857, BUG#20384:
This patch modifies the mysql.events table to permit the addition of
another enum value for the status column. The column now has values
of ('DISABLED','SLAVESIDE_DISABLED','ENABLED'). A status of
SLAVESIDE_DISABLED is set on the slave during replication of events.
This enables users to determine which events werereplicated from the
master and to later enable them if they promote the slave to a master.
The CREATE, ALTER, and DROP statements are binlogged.
A new test was added for replication of events (rpl_events).
BUG#17671:
This patch modifies the code to permit logging of user-defined functions.
Note: this is the CREATE FUNCTION ... SONAME variety. A more friendly error
message to be displayed should a replicated user-defined function not be
found in the loadable library or if the library is missing from the
slave.The CREATE andDROP statements are binlogged. A new test was added
for replication of user-defined functions (rpl_udf).
The patch also adds a new column to the mysql.event table named
'originator' that is used to store the server_id of the server that
the event originated on. This enables users to promote a slave to a
master and later return the promoted slave to a slave and disable the
replicated events.
mysql-test/lib/init_db.sql:
WL#3629 - Replication of Invocation and Invoked Feature
This patch adds the SLAVESIDE_DISABLED to the list of enumerated
values for the mysql.event table.
This patch adds the column 'originator' to the mysql.event table.
mysql-test/r/events.result:
WL#3629 - Replication of Invocation and Invoked Feature
This patch adds the 'originator' column to the events test results.
This was necessary to ensure the manual insert into mysql.event table
succeeds because the originator column is set to NOT NULL.
mysql-test/r/events_grant.result:
WL#3629 - Replication of Invocation and Invoked Feature
This patch adds the 'originator' column to the events_grant test results.
This was necessary to ensure the manual insert into mysql.event table
succeeds because the originator column is set to NOT NULL.
mysql-test/r/events_restart_phase1.result:
WL#3629 - Replication of Invocation and Invoked Feature
This patch adds the 'originator' column to the events_restart_phase1
test results. This was necessary to ensure the manual insert into
mysql.event table succeeds because the originator column is set to
NOT NULL.
mysql-test/r/system_mysql_db.result:
WL#3629 - Replication of Invocation and Invoked Feature
This patch adds the SLAVESIDE_DISABLED to the list of enumerated
values for the mysql.event table.
This patch adds the column 'originator' to the mysql.event table.
These changes to the result file were necessary to ensure correct test
results.
mysql-test/t/events.test:
WL#3629 - Replication of Invocation and Invoked Feature
This patch adds the 'originator' column to the events
test. This was necessary to ensure the manual insert into
mysql.event table succeeds because the originator column is set to
NOT NULL.
mysql-test/t/events_restart_phase1.test:
WL#3629 - Replication of Invocation and Invoked Feature
This patch adds the 'originator' column to the events_restart_phase1
test. This was necessary to ensure the manual insert into
mysql.event table succeeds because the originator column is set to
NOT NULL.
scripts/mysql_create_system_tables.sh:
WL#3629 - Replication of Invocation and Invoked Feature
This patch adds the SLAVESIDE_DISABLED to the list of enumerated
values for the mysql.event table.
This patch adds the column 'originator' to the mysql.event table.
scripts/mysql_fix_privilege_tables.sql:
WL#3629 - Replication of Invocation and Invoked Feature
This patch adds the SLAVESIDE_DISABLED to the list of enumerated
values for the mysql.event table.
This patch adds the column 'originator' to the mysql.event table.
sql/event_data_objects.cc:
WL#3629 - Replication of Invocation and Invoked Features
This patch modifies the code to permit processing of the new enum
SLAVESIDE_DISABLED which is set on the slave during replication
of events.
This patch uses the new Event_basic:: enumerated values.
sql/event_data_objects.h:
WL#3629 - Replication of Invocation and Invoked Features
This patch moves the duplicated enumeration values for ENABLED,
SLAVESIDE_DISABLED, and DISABLED to the Event_basic class removing
them from the other Event_* classes.
sql/event_db_repository.cc:
WL#3629 - Replication of Invocation and Invoked Features
This patch modifies the code to permit processing of the new enum
SLAVESIDE_DISABLED which is set on the slave during replication
of events.
The patch also adds a new column to the mysql.event table named
'originator' that is used to store the server_id of the server that
the event originated on. This enables users to promote a slave to a
master and later return the promoted slave to a slave and disable the
replicated events.
sql/event_db_repository.h:
WL#3629 - Replication of Invocation and Invoked Features
This patch modifies the code to add a new field named 'originator'
to the enum_event_table_field and associated structure.
sql/event_queue.cc:
WL#3629 - Replication of Invocation and Invoked Features
This patch modifies the code to permit processing of the new enum
SLAVESIDE_DISABLED which is set on the slave during replication
of events.
sql/events.cc:
WL#3629 - Replication of Invocation and Invoked Features
This patch modifies the code to permit processing of the new enum
SLAVESIDE_DISABLED which is set on the slave during replication
of events.
sql/lex.h:
WL#3629 - Replication of Invocation and Invoked Features
This patch modifies the code to add the new SLAVESIDE_DISABLE symbol
to the lexical parser.
sql/slave.cc:
WL#3629 - Replication of Invocation and Invoked Features
This patch modifies the code to permit the capture of the error on
the slave when a UDF from a loadable library is not loaded on the server
when replicated from the master.
sql/sql_parse.cc:
WL#3629 - Replication of Invocation and Invoked Features
This patch removes the comment because drop functions commands
are replicated.
sql/sql_show.cc:
WL#3629 - Replication of Invocation and Invoked Features
This patch modifies the code to permit processing of the new enum
SLAVESIDE_DISABLED which is set on the slave during replication
of events. The code also adds changes the display width of the status
column for the schema table for the show events command and also adds
the new column 'originator' to the events_field_info structure.
sql/sql_udf.cc:
WL#3629 - Replication of Invocation and Invoked Features
This patch modifies the code to add the binlogging of the create and
drop function events.
sql/sql_yacc.yy:
WL#3629 - Replication of Invocation and Invoked Features
This patch modifies the code to change the enumeration of the status
column for the events in the parser. The code uses the Event_basic::
enumerations allowing the enums to be defined in one place.
mysql-test/t/rpl_events.test:
WL#3629 - Replication of Invocation and Invoked Features
This patch adds a new test for testing replication of events. The test
uses include files so that the test can test under both RBR and SBR.
mysql-test/r/rpl_events.result:
WL#3629 - Replication of Invocation and Invoked Features
This patch adds a new result file for testing replication of events.
mysql-test/r/rpl_udf.result:
WL#3629 - Replication of Invocation and Invoked Features
This patch adds a new result file for testing replication of UDFs.
mysql-test/t/rpl_udf.test:
WL#3629 - Replication of Invocation and Invoked Features
This patch adds a new test for testing replication of UDFs. The test
uses include files so that the test can test under both RBR and SBR.
mysql-test/include/rpl_events.inc:
WL#3629 - Replication of Invocation and Invoked Features
This patch adds a new include file for testing replication of events.
This file contains the core test procedures.
mysql-test/include/rpl_udf.inc:
WL#3629 - Replication of Invocation and Invoked Features
This patch adds a new include file for testing replication of UDFs.
This file contains the core test procedures.
Diffstat (limited to 'sql')
-rw-r--r-- | sql/event_data_objects.cc | 52 | ||||
-rw-r--r-- | sql/event_data_objects.h | 53 | ||||
-rw-r--r-- | sql/event_db_repository.cc | 13 | ||||
-rw-r--r-- | sql/event_db_repository.h | 3 | ||||
-rw-r--r-- | sql/event_queue.cc | 6 | ||||
-rw-r--r-- | sql/events.cc | 49 | ||||
-rw-r--r-- | sql/lex.h | 1 | ||||
-rw-r--r-- | sql/slave.cc | 19 | ||||
-rw-r--r-- | sql/sql_parse.cc | 1 | ||||
-rw-r--r-- | sql/sql_show.cc | 31 | ||||
-rw-r--r-- | sql/sql_udf.cc | 34 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 15 |
12 files changed, 222 insertions, 55 deletions
diff --git a/sql/event_data_objects.cc b/sql/event_data_objects.cc index 07575a6d33a..4c3524f47ac 100644 --- a/sql/event_data_objects.cc +++ b/sql/event_data_objects.cc @@ -58,7 +58,8 @@ Event_parse_data::new_instance(THD *thd) */ Event_parse_data::Event_parse_data() - :on_completion(ON_COMPLETION_DROP), status(ENABLED), + :on_completion(Event_basic::ON_COMPLETION_DROP), + status(Event_basic::ENABLED), item_starts(NULL), item_ends(NULL), item_execute_at(NULL), starts_null(TRUE), ends_null(TRUE), execute_at_null(TRUE), item_expression(NULL), expression(0) @@ -550,9 +551,9 @@ Event_parse_data::check_parse_data(THD *thd) init_name(thd, identifier); init_definer(thd); - ret= init_execute_at(thd) || init_interval(thd) || init_starts(thd) || init_ends(thd); + check_originator_id(thd); DBUG_RETURN(ret); } @@ -599,6 +600,30 @@ Event_parse_data::init_definer(THD *thd) /* + Set the originator id of the event to the server_id if executing on + the master or set to the server_id of the master if executing on + the slave. If executing on slave, also set status to SLAVESIDE_DISABLED. + + SYNOPSIS + Event_parse_data::check_originator_id() +*/ +void Event_parse_data::check_originator_id(THD *thd) +{ + /* Disable replicated events on slave. */ + if ((thd->system_thread == SYSTEM_THREAD_SLAVE_SQL) || + (thd->system_thread == SYSTEM_THREAD_SLAVE_IO)) + { + DBUG_PRINT("info", ("Invoked object status set to SLAVESIDE_DISABLED.")); + if (status == Event_basic::ENABLED) + status = Event_basic::SLAVESIDE_DISABLED; + originator = thd->server_id; + } + else + originator = server_id; +} + + +/* Constructor SYNOPSIS @@ -927,8 +952,23 @@ Event_queue_element::load_from_row(TABLE *table) goto error; DBUG_PRINT("load_from_row", ("Event [%s] is [%s]", name.str, ptr)); - status= (ptr[0]=='E'? Event_queue_element::ENABLED: - Event_queue_element::DISABLED); + + /* Set event status (ENABLED | SLAVESIDE_DISABLED | DISABLED) */ + switch (ptr[0]) + { + case 'E' : + status = Event_queue_element::ENABLED; + break; + case 'S' : + status = Event_queue_element::SLAVESIDE_DISABLED; + break; + case 'D' : + status = Event_queue_element::DISABLED; + break; + } + if ((ptr= get_field(&mem_root, table->field[ET_FIELD_ORIGINATOR])) == NullS) + goto error; + originator = table->field[ET_FIELD_ORIGINATOR]->val_int(); /* ToDo : Andrey . Find a way not to allocate ptr on event_mem_root */ if ((ptr= get_field(&mem_root, @@ -1199,7 +1239,7 @@ Event_queue_element::compute_next_execution_time() (long) TIME_to_ulonglong_datetime(&last_executed), (long) this)); - if (status == Event_queue_element::DISABLED) + if (status != Event_queue_element::ENABLED) { DBUG_PRINT("compute_next_execution_time", ("Event %s is DISABLED", name.str)); @@ -1601,6 +1641,8 @@ Event_timed::get_create_event(THD *thd, String *buf) if (status == Event_timed::ENABLED) buf->append(STRING_WITH_LEN("ENABLE")); + else if (status == Event_timed::SLAVESIDE_DISABLED) + buf->append(STRING_WITH_LEN("SLAVESIDE_DISABLE")); else buf->append(STRING_WITH_LEN("DISABLE")); diff --git a/sql/event_data_objects.h b/sql/event_data_objects.h index e00b0b94eaf..a63340e67c8 100644 --- a/sql/event_data_objects.h +++ b/sql/event_data_objects.h @@ -22,17 +22,33 @@ #define EVEX_BAD_PARAMS -5 #define EVEX_MICROSECOND_UNSUP -6 - class sp_head; class Sql_alloc; - class Event_basic { protected: MEM_ROOT mem_root; public: + /* + ENABLED = feature can function normally (is turned on) + SLAVESIDE_DISABLED = feature is turned off on slave + DISABLED = feature is turned off + */ + enum enum_status + { + ENABLED = 1, + DISABLED, + SLAVESIDE_DISABLED + }; + + enum enum_on_completion + { + ON_COMPLETION_DROP = 1, + ON_COMPLETION_PRESERVE + }; + LEX_STRING dbname; LEX_STRING name; LEX_STRING definer;// combination of user and host @@ -57,20 +73,9 @@ protected: bool last_executed_changed; public: - enum enum_status - { - ENABLED = 1, - DISABLED - }; - - enum enum_on_completion - { - ON_COMPLETION_DROP = 1, - ON_COMPLETION_PRESERVE - }; - - enum enum_on_completion on_completion; - enum enum_status status; + int on_completion; + int status; + longlong originator; TIME last_executed; TIME execute_at; @@ -194,19 +199,10 @@ private: class Event_parse_data : public Sql_alloc { public: - enum enum_status - { - ENABLED = 1, - DISABLED - }; - enum enum_on_completion - { - ON_COMPLETION_DROP = 1, - ON_COMPLETION_PRESERVE - }; - enum enum_on_completion on_completion; - enum enum_status status; + int on_completion; + int status; + longlong originator; const uchar *body_begin; @@ -268,6 +264,7 @@ private: report_bad_value(const char *item_name, Item *bad_item); Event_parse_data(const Event_parse_data &); /* Prevent use of these */ + void Event_parse_data::check_originator_id(THD *thd); void operator=(Event_parse_data &); }; diff --git a/sql/event_db_repository.cc b/sql/event_db_repository.cc index 940930ec4c6..1b001db984c 100644 --- a/sql/event_db_repository.cc +++ b/sql/event_db_repository.cc @@ -94,7 +94,7 @@ const TABLE_FIELD_W_TYPE event_table_fields[ET_FIELD_COUNT] = }, { { C_STRING_WITH_LEN("status") }, - { C_STRING_WITH_LEN("enum('ENABLED','DISABLED')") }, + { C_STRING_WITH_LEN("enum('ENABLED','DISABLED','SLAVESIDE_DISABLED')") }, {NULL, 0} }, { @@ -118,6 +118,11 @@ const TABLE_FIELD_W_TYPE event_table_fields[ET_FIELD_COUNT] = { C_STRING_WITH_LEN("comment") }, { C_STRING_WITH_LEN("char(64)") }, { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("originator") }, + { C_STRING_WITH_LEN("int(10)") }, + {NULL, 0} } }; @@ -170,6 +175,9 @@ mysql_event_fill_row(THD *thd, TABLE *table, Event_parse_data *et, fields[ET_FIELD_STATUS]->store((longlong)et->status, TRUE); + fields[ET_FIELD_ORIGINATOR]->store((longlong)et->originator, TRUE); + + /* Change the SQL_MODE only if body was present in an ALTER EVENT and of course always during CREATE EVENT. @@ -535,7 +543,6 @@ Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data, goto err; } - DBUG_PRINT("info", ("name: %.*s", parse_data->name.length, parse_data->name.str)); @@ -603,6 +610,8 @@ Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data, if ((ret= mysql_event_fill_row(thd, table, parse_data, FALSE))) goto err; + table->field[ET_FIELD_STATUS]->store((longlong)parse_data->status, TRUE); + /* Close active transaction only if We are going to modify disk */ if (end_active_trans(thd)) goto err; diff --git a/sql/event_db_repository.h b/sql/event_db_repository.h index 1457fb64e2e..ff23b1f5c85 100644 --- a/sql/event_db_repository.h +++ b/sql/event_db_repository.h @@ -19,7 +19,7 @@ enum enum_events_table_field { - ET_FIELD_DB = 0, + ET_FIELD_DB = 0, ET_FIELD_NAME, ET_FIELD_BODY, ET_FIELD_DEFINER, @@ -35,6 +35,7 @@ enum enum_events_table_field ET_FIELD_ON_COMPLETION, ET_FIELD_SQL_MODE, ET_FIELD_COMMENT, + ET_FIELD_ORIGINATOR, ET_FIELD_COUNT /* a cool trick to count the number of fields :) */ }; diff --git a/sql/event_queue.cc b/sql/event_queue.cc index 068abbe3408..d951e926901 100644 --- a/sql/event_queue.cc +++ b/sql/event_queue.cc @@ -218,7 +218,8 @@ Event_queue::create_event(THD *thd, LEX_STRING dbname, LEX_STRING name) new_element= new Event_queue_element(); res= db_repository->load_named_event(thd, dbname, name, new_element); - if (res || new_element->status == Event_queue_element::DISABLED) + if (res || new_element->status == Event_queue_element::DISABLED + || new_element->status == Event_queue_element::SLAVESIDE_DISABLED) delete new_element; else { @@ -231,7 +232,6 @@ Event_queue::create_event(THD *thd, LEX_STRING dbname, LEX_STRING name) pthread_cond_broadcast(&COND_queue_state); UNLOCK_QUEUE_DATA(); } - DBUG_RETURN(res); } @@ -271,7 +271,7 @@ Event_queue::update_event(THD *thd, LEX_STRING dbname, LEX_STRING name, delete new_element; goto end; } - else if (new_element->status == Event_queue_element::DISABLED) + else if (new_element->status != Event_queue_element::ENABLED) { DBUG_PRINT("info", ("The event is disabled.")); /* diff --git a/sql/events.cc b/sql/events.cc index e6224915d6b..80ee613a6b9 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -347,7 +347,15 @@ Events::create_event(THD *thd, Event_parse_data *parse_data, bool if_not_exists) DBUG_RETURN(TRUE); } + /* + Turn off row binlogging of this statement and use statement-based + so that all supporting tables are updated for CREATE EVENT command. + */ + if (thd->current_stmt_binlog_row_based) + thd->clear_current_stmt_binlog_row_based(); + pthread_mutex_lock(&LOCK_event_metadata); + /* On error conditions my_error() is called so no need to handle here */ if (!(ret= db_repository->create_event(thd, parse_data, if_not_exists))) { @@ -357,6 +365,15 @@ Events::create_event(THD *thd, Event_parse_data *parse_data, bool if_not_exists) DBUG_ASSERT(ret == OP_LOAD_ERROR); my_error(ER_EVENT_MODIFY_QUEUE_ERROR, MYF(0)); } + else /* Binlog the create event. */ + { + if (mysql_bin_log.is_open()) + { + thd->clear_error(); + thd->binlog_query(THD::MYSQL_QUERY_TYPE, + thd->query, thd->query_length, FALSE, FALSE); + } + } } pthread_mutex_unlock(&LOCK_event_metadata); @@ -396,7 +413,15 @@ Events::update_event(THD *thd, Event_parse_data *parse_data, sp_name *rename_to) DBUG_RETURN(TRUE); } + /* + Turn off row binlogging of this statement and use statement-based + so that all supporting tables are updated for UPDATE EVENT command. + */ + if (thd->current_stmt_binlog_row_based) + thd->clear_current_stmt_binlog_row_based(); + pthread_mutex_lock(&LOCK_event_metadata); + /* On error conditions my_error() is called so no need to handle here */ if (!(ret= db_repository->update_event(thd, parse_data, new_dbname, new_name))) { @@ -406,6 +431,15 @@ Events::update_event(THD *thd, Event_parse_data *parse_data, sp_name *rename_to) DBUG_ASSERT(ret == OP_LOAD_ERROR); my_error(ER_EVENT_MODIFY_QUEUE_ERROR, MYF(0)); } + else /* Binlog the alter event. */ + { + if (mysql_bin_log.is_open()) + { + thd->clear_error(); + thd->binlog_query(THD::MYSQL_QUERY_TYPE, + thd->query, thd->query_length, FALSE, FALSE); + } + } } pthread_mutex_unlock(&LOCK_event_metadata); @@ -445,12 +479,27 @@ Events::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists, DBUG_RETURN(TRUE); } + /* + Turn off row binlogging of this statement and use statement-based so + that all supporting tables are updated for DROP EVENT command. + */ + if (thd->current_stmt_binlog_row_based) + thd->clear_current_stmt_binlog_row_based(); + pthread_mutex_lock(&LOCK_event_metadata); /* On error conditions my_error() is called so no need to handle here */ if (!(ret= db_repository->drop_event(thd, dbname, name, if_exists))) { if (!only_from_disk) event_queue->drop_event(thd, dbname, name); + + /* Binlog the drop event. */ + if (mysql_bin_log.is_open()) + { + thd->clear_error(); + thd->binlog_query(THD::MYSQL_QUERY_TYPE, + thd->query, thd->query_length, FALSE, FALSE); + } } pthread_mutex_unlock(&LOCK_event_metadata); DBUG_RETURN(ret); diff --git a/sql/lex.h b/sql/lex.h index 45155da7692..6e0f1c711f2 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -467,6 +467,7 @@ static SYMBOL symbols[] = { { "SIGNED", SYM(SIGNED_SYM)}, { "SIMPLE", SYM(SIMPLE_SYM)}, { "SLAVE", SYM(SLAVE)}, + { "SLAVESIDE_DISABLE", SYM(SLAVESIDE_DISABLE_SYM)}, { "SNAPSHOT", SYM(SNAPSHOT_SYM)}, { "SMALLINT", SYM(SMALLINT)}, { "SOCKET", SYM(SOCKET_SYM)}, diff --git a/sql/slave.cc b/sql/slave.cc index 3a9cde42059..aa018f560ed 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -2387,10 +2387,25 @@ Slave SQL thread aborted. Can't execute init_slave query"); /* Print any warnings issued */ List_iterator_fast<MYSQL_ERROR> it(thd->warn_list); MYSQL_ERROR *err; + /* + Added controlled slave thread cancel for replication + of user-defined variables. + */ + bool udf_error = false; while ((err= it++)) + { + if (err->code == ER_CANT_OPEN_LIBRARY) + udf_error = true; sql_print_warning("Slave: %s Error_code: %d",err->msg, err->code); - - sql_print_error("\ + } + if (udf_error) + sql_print_error("Error loading user-defined library, slave SQL " + "thread aborted. Install the missing library, and restart the " + "slave SQL thread with \"SLAVE START\". We stopped at log '%s' " + "position %s", RPL_LOG_NAME, llstr(rli->group_master_log_pos, + llbuff)); + else + sql_print_error("\ Error running query, slave SQL thread aborted. Fix the problem, and restart \ the slave SQL thread with \"SLAVE START\". We stopped at log \ '%s' position %s", RPL_LOG_NAME, llstr(rli->group_master_log_pos, llbuff)); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index ce7f34e3a06..de304976c0d 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3866,7 +3866,6 @@ create_sp_error: if (check_access(thd, DELETE_ACL, "mysql", 0, 1, 0, 0)) goto error; - /* Does NOT write to binlog */ if (!(res = mysql_drop_function(thd, &lex->spname->m_name))) { send_ok(thd); diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 881cf7dc6c4..6a6e7ce3225 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -52,7 +52,8 @@ enum enum_i_s_events_fields ISE_CREATED, ISE_LAST_ALTERED, ISE_LAST_EXECUTED, - ISE_EVENT_COMMENT + ISE_EVENT_COMMENT, + ISE_ORIGINATOR }; @@ -4393,10 +4394,23 @@ copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table) } /* status */ - if (et.status == Event_timed::ENABLED) - sch_table->field[ISE_STATUS]->store(STRING_WITH_LEN("ENABLED"), scs); - else - sch_table->field[ISE_STATUS]->store(STRING_WITH_LEN("DISABLED"), scs); + + switch (et.status) + { + case Event_timed::ENABLED: + sch_table->field[ISE_STATUS]->store(STRING_WITH_LEN("ENABLED"), scs); + break; + case Event_timed::SLAVESIDE_DISABLED: + sch_table->field[ISE_STATUS]->store(STRING_WITH_LEN("SLAVESIDE_DISABLED"), + scs); + break; + case Event_timed::DISABLED: + sch_table->field[ISE_STATUS]->store(STRING_WITH_LEN("DISABLED"), scs); + break; + default: + DBUG_ASSERT(0); + } + sch_table->field[ISE_ORIGINATOR]->store(et.originator, TRUE); /* on_completion */ if (et.on_completion == Event_timed::ON_COMPLETION_DROP) @@ -4935,9 +4949,7 @@ int mysql_schema_table(THD *thd, LEX *lex, TABLE_LIST *table_list) TABLE *table; DBUG_ENTER("mysql_schema_table"); if (!(table= table_list->schema_table->create_table(thd, table_list))) - { DBUG_RETURN(1); - } table->s->tmp_table= SYSTEM_TMP_TABLE; table->grant.privilege= SELECT_ACL; /* @@ -5429,13 +5441,14 @@ ST_FIELD_INFO events_fields_info[]= {"SQL_MODE", 65535, MYSQL_TYPE_STRING, 0, 0, 0}, {"STARTS", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Starts"}, {"ENDS", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Ends"}, - {"STATUS", 8, MYSQL_TYPE_STRING, 0, 0, "Status"}, + {"STATUS", 18, MYSQL_TYPE_STRING, 0, 0, "Status"}, {"ON_COMPLETION", 12, MYSQL_TYPE_STRING, 0, 0, 0}, {"CREATED", 0, MYSQL_TYPE_TIMESTAMP, 0, 0, 0}, {"LAST_ALTERED", 0, MYSQL_TYPE_TIMESTAMP, 0, 0, 0}, {"LAST_EXECUTED", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, 0}, + {"ORIGINATOR", 10, MYSQL_TYPE_LONG, 0, 0, "Originator"}, {"EVENT_COMMENT", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, - {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} + {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} }; diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index 7dec58d9b6e..3ab161bb04f 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -403,6 +403,13 @@ int mysql_create_function(THD *thd,udf_func *udf) DBUG_RETURN(1); } + /* + Turn off row binlogging of this statement and use statement-based + so that all supporting tables are updated for CREATE FUNCTION command. + */ + if (thd->current_stmt_binlog_row_based) + thd->clear_current_stmt_binlog_row_based(); + rw_wrlock(&THR_LOCK_udf); if ((hash_search(&udf_hash,(byte*) udf->name.str, udf->name.length))) { @@ -466,6 +473,15 @@ int mysql_create_function(THD *thd,udf_func *udf) goto err; } rw_unlock(&THR_LOCK_udf); + + /* Binlog the create function. */ + if (mysql_bin_log.is_open()) + { + thd->clear_error(); + thd->binlog_query(THD::MYSQL_QUERY_TYPE, + thd->query, thd->query_length, FALSE, FALSE); + } + DBUG_RETURN(0); err: @@ -484,11 +500,20 @@ int mysql_drop_function(THD *thd,const LEX_STRING *udf_name) char *exact_name_str; uint exact_name_len; DBUG_ENTER("mysql_drop_function"); + if (!initialized) { my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0)); DBUG_RETURN(1); } + + /* + Turn off row binlogging of this statement and use statement-based + so that all supporting tables are updated for DROP FUNCTION command. + */ + if (thd->current_stmt_binlog_row_based) + thd->clear_current_stmt_binlog_row_based(); + rw_wrlock(&THR_LOCK_udf); if (!(udf=(udf_func*) hash_search(&udf_hash,(byte*) udf_name->str, (uint) udf_name->length))) @@ -525,6 +550,15 @@ int mysql_drop_function(THD *thd,const LEX_STRING *udf_name) close_thread_tables(thd); rw_unlock(&THR_LOCK_udf); + + /* Binlog the drop function. */ + if (mysql_bin_log.is_open()) + { + thd->clear_error(); + thd->binlog_query(THD::MYSQL_QUERY_TYPE, + thd->query, thd->query_length, FALSE, FALSE); + } + DBUG_RETURN(0); err: rw_unlock(&THR_LOCK_udf); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 9c062407921..67251159327 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -813,6 +813,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token SIGNED_SYM %token SIMPLE_SYM /* SQL-2003-N */ %token SLAVE +%token SLAVESIDE_DISABLE_SYM %token SMALLINT /* SQL-2003-R */ %token SNAPSHOT_SYM %token SOCKET_SYM @@ -1632,12 +1633,17 @@ ev_schedule_time: EVERY_SYM expr interval opt_ev_status: /* empty */ { $$= 0; } | ENABLE_SYM { - Lex->event_parse_data->status= Event_parse_data::ENABLED; + Lex->event_parse_data->status= Event_basic::ENABLED; + $$= 1; + } + | SLAVESIDE_DISABLE_SYM + { + Lex->event_parse_data->status= Event_basic::SLAVESIDE_DISABLED; $$= 1; } | DISABLE_SYM { - Lex->event_parse_data->status= Event_parse_data::DISABLED; + Lex->event_parse_data->status= Event_basic::DISABLED; $$= 1; } ; @@ -1667,13 +1673,13 @@ ev_on_completion: ON COMPLETION_SYM PRESERVE_SYM { Lex->event_parse_data->on_completion= - Event_parse_data::ON_COMPLETION_PRESERVE; + Event_basic::ON_COMPLETION_PRESERVE; $$= 1; } | ON COMPLETION_SYM NOT_SYM PRESERVE_SYM { Lex->event_parse_data->on_completion= - Event_parse_data::ON_COMPLETION_DROP; + Event_basic::ON_COMPLETION_DROP; $$= 1; } ; @@ -9832,6 +9838,7 @@ keyword_sp: | SIMPLE_SYM {} | SHARE_SYM {} | SHUTDOWN {} + | SLAVESIDE_DISABLE_SYM {} | SNAPSHOT_SYM {} | SOUNDS_SYM {} | SQL_CACHE_SYM {} |