Commit a820c732 authored by Georgi Kodinov's avatar Georgi Kodinov

merge

parents 88aa7af8 adab17b9
...@@ -270,3 +270,42 @@ INSERT INTO test.t1 VALUES (1), (2); ...@@ -270,3 +270,42 @@ INSERT INTO test.t1 VALUES (1), (2);
CREATE TABLE test.t2 SELECT * FROM test.t1; CREATE TABLE test.t2 SELECT * FROM test.t1;
USE test; USE test;
DROP TABLES t1, t2; DROP TABLES t1, t2;
#
# Bug#46640
# This test verifies if the server_id stored in the "format
# description BINLOG statement" will override the server_id
# of the server executing the statements.
#
connect (fresh,localhost,root,,test);
connection fresh;
RESET MASTER;
CREATE TABLE t1 (a INT PRIMARY KEY);
# Format description event, with server_id = 10;
BINLOG '
3u9kSA8KAAAAZgAAAGoAAAABAAQANS4xLjM1LW1hcmlhLWJldGExLWRlYnVnLWxvZwAAAAAAAAAA
AAAAAAAAAAAAAAAAAADe72RIEzgNAAgAEgAEBAQEEgAAUwAEGggAAAAICAgC
';
# What server_id is logged for a statement? Should be our own, not the
# one from the format description event.
INSERT INTO t1 VALUES (1);
# INSERT INTO t1 VALUES (2), with server_id=20. Check that this is logged
# with our own server id, not the 20 from the BINLOG statement.
BINLOG '
3u9kSBMUAAAAKQAAAJEBAAAAABoAAAAAAAAABHRlc3QAAnQxAAEDAAA=
3u9kSBcUAAAAIgAAALMBAAAQABoAAAAAAAEAAf/+AgAAAA==
';
# Show binlog events to check that server ids are correct.
--replace_column 1 # 2 # 5 #
--replace_regex /Server ver: .*, Binlog ver: .*/Server ver: #, Binlog ver: #/ /table_id: [0-9]+/table_id: #/
SHOW BINLOG EVENTS;
DROP TABLE t1;
disconnect fresh;
...@@ -1477,3 +1477,47 @@ COUNT(*) ...@@ -1477,3 +1477,47 @@ COUNT(*)
SET SQL_MODE=default; SET SQL_MODE=default;
DROP TABLE t1; DROP TABLE t1;
End of 5.0 tests End of 5.0 tests
#
# BUG#47280 - strange results from count(*) with order by multiple
# columns without where/group
#
#
# Initialize test
#
CREATE TABLE t1 (
pk INT NOT NULL,
i INT,
PRIMARY KEY (pk)
);
INSERT INTO t1 VALUES (1,11),(2,12),(3,13);
#
# Start test
# All the following queries shall return 1 record
#
# Masking all correct values {11...13} for column i in this result.
SELECT MAX(pk) as max, i
FROM t1
ORDER BY max;
max i
3 #
EXPLAIN
SELECT MAX(pk) as max, i
FROM t1
ORDER BY max;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using temporary
# Only 11 is correct for collumn i in this result
SELECT MAX(pk) as max, i
FROM t1
WHERE pk<2
ORDER BY max;
max i
1 11
#
# Cleanup
#
DROP TABLE t1;
End of 5.1 tests
...@@ -1309,3 +1309,27 @@ INSERT INTO test.t1 VALUES (1), (2); ...@@ -1309,3 +1309,27 @@ INSERT INTO test.t1 VALUES (1), (2);
CREATE TABLE test.t2 SELECT * FROM test.t1; CREATE TABLE test.t2 SELECT * FROM test.t1;
USE test; USE test;
DROP TABLES t1, t2; DROP TABLES t1, t2;
RESET MASTER;
CREATE TABLE t1 (a INT PRIMARY KEY);
BINLOG '
3u9kSA8KAAAAZgAAAGoAAAABAAQANS4xLjM1LW1hcmlhLWJldGExLWRlYnVnLWxvZwAAAAAAAAAA
AAAAAAAAAAAAAAAAAADe72RIEzgNAAgAEgAEBAQEEgAAUwAEGggAAAAICAgC
';
INSERT INTO t1 VALUES (1);
BINLOG '
3u9kSBMUAAAAKQAAAJEBAAAAABoAAAAAAAAABHRlc3QAAnQxAAEDAAA=
3u9kSBcUAAAAIgAAALMBAAAQABoAAAAAAAEAAf/+AgAAAA==
';
SHOW BINLOG EVENTS;
Log_name Pos Event_type Server_id End_log_pos Info
# # Format_desc 1 # Server ver: #, Binlog ver: #
# # Query 1 # use `test`; CREATE TABLE t1 (a INT PRIMARY KEY)
# # Query 1 # BEGIN
# # Table_map 1 # table_id: # (test.t1)
# # Write_rows 1 # table_id: # flags: STMT_END_F
# # Query 1 # COMMIT
# # Query 1 # BEGIN
# # Table_map 1 # table_id: # (test.t1)
# # Write_rows 1 # table_id: # flags: STMT_END_F
# # Query 1 # COMMIT
DROP TABLE t1;
Verbose statements from : write-partial-row.binlog Verbose statements from : write-partial-row.binlog
select txt from raw_binlog_rows where txt like '###%'; select replace(txt,'\r', '') as stmt from raw_binlog_rows where txt like '###%';
txt stmt
### INSERT INTO mysql.ndb_apply_status ### INSERT INTO mysql.ndb_apply_status
### SET ### SET
### @1=1 ### @1=1
...@@ -37,8 +37,8 @@ txt ...@@ -37,8 +37,8 @@ txt
### @1=2 ### @1=2
drop table raw_binlog_rows; drop table raw_binlog_rows;
Verbose statements from : write-full-row.binlog Verbose statements from : write-full-row.binlog
select txt from raw_binlog_rows where txt like '###%'; select replace(txt,'\r', '') as stmt from raw_binlog_rows where txt like '###%';
txt stmt
### INSERT INTO mysql.ndb_apply_status ### INSERT INTO mysql.ndb_apply_status
### SET ### SET
### @1=2 ### @1=2
...@@ -76,8 +76,8 @@ txt ...@@ -76,8 +76,8 @@ txt
### @1=2 ### @1=2
drop table raw_binlog_rows; drop table raw_binlog_rows;
Verbose statements from : update-partial-row.binlog Verbose statements from : update-partial-row.binlog
select txt from raw_binlog_rows where txt like '###%'; select replace(txt,'\r', '') as stmt from raw_binlog_rows where txt like '###%';
txt stmt
### INSERT INTO mysql.ndb_apply_status ### INSERT INTO mysql.ndb_apply_status
### SET ### SET
### @1=3 ### @1=3
...@@ -117,8 +117,8 @@ txt ...@@ -117,8 +117,8 @@ txt
### @1=2 ### @1=2
drop table raw_binlog_rows; drop table raw_binlog_rows;
Verbose statements from : update-full-row.binlog Verbose statements from : update-full-row.binlog
select txt from raw_binlog_rows where txt like '###%'; select replace(txt,'\r', '') as stmt from raw_binlog_rows where txt like '###%';
txt stmt
### INSERT INTO mysql.ndb_apply_status ### INSERT INTO mysql.ndb_apply_status
### SET ### SET
### @1=4 ### @1=4
......
...@@ -784,3 +784,24 @@ INSERT INTO test.t1 VALUES (1), (2); ...@@ -784,3 +784,24 @@ INSERT INTO test.t1 VALUES (1), (2);
CREATE TABLE test.t2 SELECT * FROM test.t1; CREATE TABLE test.t2 SELECT * FROM test.t1;
USE test; USE test;
DROP TABLES t1, t2; DROP TABLES t1, t2;
RESET MASTER;
CREATE TABLE t1 (a INT PRIMARY KEY);
BINLOG '
3u9kSA8KAAAAZgAAAGoAAAABAAQANS4xLjM1LW1hcmlhLWJldGExLWRlYnVnLWxvZwAAAAAAAAAA
AAAAAAAAAAAAAAAAAADe72RIEzgNAAgAEgAEBAQEEgAAUwAEGggAAAAICAgC
';
INSERT INTO t1 VALUES (1);
BINLOG '
3u9kSBMUAAAAKQAAAJEBAAAAABoAAAAAAAAABHRlc3QAAnQxAAEDAAA=
3u9kSBcUAAAAIgAAALMBAAAQABoAAAAAAAEAAf/+AgAAAA==
';
SHOW BINLOG EVENTS;
Log_name Pos Event_type Server_id End_log_pos Info
# # Format_desc 1 # Server ver: #, Binlog ver: #
# # Query 1 # use `test`; CREATE TABLE t1 (a INT PRIMARY KEY)
# # Query 1 # use `test`; INSERT INTO t1 VALUES (1)
# # Query 1 # BEGIN
# # Table_map 1 # table_id: # (test.t1)
# # Write_rows 1 # table_id: # flags: STMT_END_F
# # Query 1 # COMMIT
DROP TABLE t1;
...@@ -45,7 +45,8 @@ create table raw_binlog_rows (txt varchar(1000)); ...@@ -45,7 +45,8 @@ create table raw_binlog_rows (txt varchar(1000));
--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql --remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql
--enable_query_log --enable_query_log
--echo Verbose statements from : $binlog_file --echo Verbose statements from : $binlog_file
select txt from raw_binlog_rows where txt like '###%'; # Output --verbose lines, with extra Windows CR's trimmed
select replace(txt,'\r', '') as stmt from raw_binlog_rows where txt like '###%';
drop table raw_binlog_rows; drop table raw_binlog_rows;
--disable_query_log --disable_query_log
...@@ -56,7 +57,8 @@ create table raw_binlog_rows (txt varchar(1000)); ...@@ -56,7 +57,8 @@ create table raw_binlog_rows (txt varchar(1000));
--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql --remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql
--enable_query_log --enable_query_log
--echo Verbose statements from : $binlog_file --echo Verbose statements from : $binlog_file
select txt from raw_binlog_rows where txt like '###%'; # Output --verbose lines, with extra Windows CR's trimmed
select replace(txt,'\r', '') as stmt from raw_binlog_rows where txt like '###%';
drop table raw_binlog_rows; drop table raw_binlog_rows;
--disable_query_log --disable_query_log
...@@ -67,7 +69,8 @@ create table raw_binlog_rows (txt varchar(1000)); ...@@ -67,7 +69,8 @@ create table raw_binlog_rows (txt varchar(1000));
--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql --remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql
--enable_query_log --enable_query_log
--echo Verbose statements from : $binlog_file --echo Verbose statements from : $binlog_file
select txt from raw_binlog_rows where txt like '###%'; # Output --verbose lines, with extra Windows CR's trimmed
select replace(txt,'\r', '') as stmt from raw_binlog_rows where txt like '###%';
drop table raw_binlog_rows; drop table raw_binlog_rows;
--disable_query_log --disable_query_log
...@@ -78,5 +81,6 @@ create table raw_binlog_rows (txt varchar(1000)); ...@@ -78,5 +81,6 @@ create table raw_binlog_rows (txt varchar(1000));
--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql --remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql
--enable_query_log --enable_query_log
--echo Verbose statements from : $binlog_file --echo Verbose statements from : $binlog_file
select txt from raw_binlog_rows where txt like '###%'; # Output --verbose lines, with extra Windows CR's trimmed
select replace(txt,'\r', '') as stmt from raw_binlog_rows where txt like '###%';
drop table raw_binlog_rows; drop table raw_binlog_rows;
...@@ -1006,3 +1006,51 @@ DROP TABLE t1; ...@@ -1006,3 +1006,51 @@ DROP TABLE t1;
### ###
--echo End of 5.0 tests --echo End of 5.0 tests
--echo #
--echo # BUG#47280 - strange results from count(*) with order by multiple
--echo # columns without where/group
--echo #
--echo #
--echo # Initialize test
--echo #
CREATE TABLE t1 (
pk INT NOT NULL,
i INT,
PRIMARY KEY (pk)
);
INSERT INTO t1 VALUES (1,11),(2,12),(3,13);
--echo #
--echo # Start test
--echo # All the following queries shall return 1 record
--echo #
--echo
--echo # Masking all correct values {11...13} for column i in this result.
--replace_column 2 #
SELECT MAX(pk) as max, i
FROM t1
ORDER BY max;
--echo
EXPLAIN
SELECT MAX(pk) as max, i
FROM t1
ORDER BY max;
--echo
--echo # Only 11 is correct for collumn i in this result
SELECT MAX(pk) as max, i
FROM t1
WHERE pk<2
ORDER BY max;
--echo #
--echo # Cleanup
--echo #
DROP TABLE t1;
--echo End of 5.1 tests
...@@ -3859,6 +3859,7 @@ bool Format_description_log_event::write(IO_CACHE* file) ...@@ -3859,6 +3859,7 @@ bool Format_description_log_event::write(IO_CACHE* file)
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
int Format_description_log_event::do_apply_event(Relay_log_info const *rli) int Format_description_log_event::do_apply_event(Relay_log_info const *rli)
{ {
int ret= 0;
DBUG_ENTER("Format_description_log_event::do_apply_event"); DBUG_ENTER("Format_description_log_event::do_apply_event");
#ifdef USING_TRANSACTIONS #ifdef USING_TRANSACTIONS
...@@ -3900,17 +3901,21 @@ int Format_description_log_event::do_apply_event(Relay_log_info const *rli) ...@@ -3900,17 +3901,21 @@ int Format_description_log_event::do_apply_event(Relay_log_info const *rli)
0, then 96, then jump to first really asked event (which is 0, then 96, then jump to first really asked event (which is
>96). So this is ok. >96). So this is ok.
*/ */
DBUG_RETURN(Start_log_event_v3::do_apply_event(rli)); ret= Start_log_event_v3::do_apply_event(rli);
} }
DBUG_RETURN(0);
if (!ret)
{
/* Save the information describing this binlog */
delete rli->relay_log.description_event_for_exec;
const_cast<Relay_log_info *>(rli)->relay_log.description_event_for_exec= this;
}
DBUG_RETURN(ret);
} }
int Format_description_log_event::do_update_pos(Relay_log_info *rli) int Format_description_log_event::do_update_pos(Relay_log_info *rli)
{ {
/* save the information describing this binlog */
delete rli->relay_log.description_event_for_exec;
rli->relay_log.description_event_for_exec= this;
if (server_id == (uint32) ::server_id) if (server_id == (uint32) ::server_id)
{ {
/* /*
...@@ -7506,6 +7511,7 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli) ...@@ -7506,6 +7511,7 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli)
thd->reset_current_stmt_binlog_row_based(); thd->reset_current_stmt_binlog_row_based();
const_cast<Relay_log_info*>(rli)->cleanup_context(thd, error); const_cast<Relay_log_info*>(rli)->cleanup_context(thd, error);
thd->is_slave_error= 1; thd->is_slave_error= 1;
DBUG_RETURN(error);
} }
/* /*
This code would ideally be placed in do_update_pos() instead, but This code would ideally be placed in do_update_pos() instead, but
...@@ -7534,6 +7540,14 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli) ...@@ -7534,6 +7540,14 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli)
const_cast<Relay_log_info*>(rli)->last_event_start_time= my_time(0); const_cast<Relay_log_info*>(rli)->last_event_start_time= my_time(0);
} }
if (get_flags(STMT_END_F))
if (error= rows_event_stmt_cleanup(rli, thd))
rli->report(ERROR_LEVEL, error,
"Error in %s event: commit of row events failed, "
"table `%s`.`%s`",
get_type_str(), m_table->s->db.str,
m_table->s->table_name.str);
DBUG_RETURN(error); DBUG_RETURN(error);
} }
...@@ -7632,33 +7646,19 @@ Rows_log_event::do_update_pos(Relay_log_info *rli) ...@@ -7632,33 +7646,19 @@ Rows_log_event::do_update_pos(Relay_log_info *rli)
if (get_flags(STMT_END_F)) if (get_flags(STMT_END_F))
{ {
if ((error= rows_event_stmt_cleanup(rli, thd)) == 0) /*
{ Indicate that a statement is finished.
/* Step the group log position if we are not in a transaction,
Indicate that a statement is finished. otherwise increase the event log position.
Step the group log position if we are not in a transaction, */
otherwise increase the event log position. rli->stmt_done(log_pos, when);
*/ /*
rli->stmt_done(log_pos, when); Clear any errors in thd->net.last_err*. It is not known if this is
needed or not. It is believed that any errors that may exist in
/* thd->net.last_err* are allowed. Examples of errors are "key not
Clear any errors pushed in thd->net.last_err* if for example "no key found", which is produced in the test case rpl_row_conflicts.test
found" (as this is allowed). This is a safety measure; apparently */
those errors (e.g. when executing a Delete_rows_log_event of a thd->clear_error();
non-existing row, like in rpl_row_mystery22.test,
thd->net.last_error = "Can't find record in 't1'" and last_errno=1032)
do not become visible. We still prefer to wipe them out.
*/
thd->clear_error();
}
else
{
rli->report(ERROR_LEVEL, error,
"Error in %s event: commit of row events failed, "
"table `%s`.`%s`",
get_type_str(), m_table->s->db.str,
m_table->s->table_name.str);
}
} }
else else
{ {
......
...@@ -1814,33 +1814,6 @@ int Old_rows_log_event::do_apply_event(Relay_log_info const *rli) ...@@ -1814,33 +1814,6 @@ int Old_rows_log_event::do_apply_event(Relay_log_info const *rli)
const_cast<Relay_log_info*>(rli)->last_event_start_time= my_time(0); const_cast<Relay_log_info*>(rli)->last_event_start_time= my_time(0);
} }
DBUG_RETURN(0);
}
Log_event::enum_skip_reason
Old_rows_log_event::do_shall_skip(Relay_log_info *rli)
{
/*
If the slave skip counter is 1 and this event does not end a
statement, then we should not start executing on the next event.
Otherwise, we defer the decision to the normal skipping logic.
*/
if (rli->slave_skip_counter == 1 && !get_flags(STMT_END_F))
return Log_event::EVENT_SKIP_IGNORE;
else
return Log_event::do_shall_skip(rli);
}
int
Old_rows_log_event::do_update_pos(Relay_log_info *rli)
{
DBUG_ENTER("Old_rows_log_event::do_update_pos");
int error= 0;
DBUG_PRINT("info", ("flags: %s",
get_flags(STMT_END_F) ? "STMT_END_F " : ""));
if (get_flags(STMT_END_F)) if (get_flags(STMT_END_F))
{ {
/* /*
...@@ -1869,7 +1842,12 @@ Old_rows_log_event::do_update_pos(Relay_log_info *rli) ...@@ -1869,7 +1842,12 @@ Old_rows_log_event::do_update_pos(Relay_log_info *rli)
are involved, commit the transaction and flush the pending event to the are involved, commit the transaction and flush the pending event to the
binlog. binlog.
*/ */
error= ha_autocommit_or_rollback(thd, 0); if (error= ha_autocommit_or_rollback(thd, 0))
rli->report(ERROR_LEVEL, error,
"Error in %s event: commit of row events failed, "
"table `%s`.`%s`",
get_type_str(), m_table->s->db.str,
m_table->s->table_name.str);
/* /*
Now what if this is not a transactional engine? we still need to Now what if this is not a transactional engine? we still need to
...@@ -1882,33 +1860,51 @@ Old_rows_log_event::do_update_pos(Relay_log_info *rli) ...@@ -1882,33 +1860,51 @@ Old_rows_log_event::do_update_pos(Relay_log_info *rli)
*/ */
thd->reset_current_stmt_binlog_row_based(); thd->reset_current_stmt_binlog_row_based();
rli->cleanup_context(thd, 0); const_cast<Relay_log_info*>(rli)->cleanup_context(thd, 0);
if (error == 0) }
{
/*
Indicate that a statement is finished.
Step the group log position if we are not in a transaction,
otherwise increase the event log position.
*/
rli->stmt_done(log_pos, when);
/* DBUG_RETURN(error);
Clear any errors pushed in thd->net.client_last_err* if for }
example "no key found" (as this is allowed). This is a safety
measure; apparently those errors (e.g. when executing a
Delete_rows_log_event_old of a non-existing row, like in Log_event::enum_skip_reason
rpl_row_mystery22.test, thd->net.last_error = "Can't Old_rows_log_event::do_shall_skip(Relay_log_info *rli)
find record in 't1'" and last_errno=1032) do not become {
visible. We still prefer to wipe them out. /*
*/ If the slave skip counter is 1 and this event does not end a
thd->clear_error(); statement, then we should not start executing on the next event.
} Otherwise, we defer the decision to the normal skipping logic.
else */
rli->report(ERROR_LEVEL, error, if (rli->slave_skip_counter == 1 && !get_flags(STMT_END_F))
"Error in %s event: commit of row events failed, " return Log_event::EVENT_SKIP_IGNORE;
"table `%s`.`%s`", else
get_type_str(), m_table->s->db.str, return Log_event::do_shall_skip(rli);
m_table->s->table_name.str); }
int
Old_rows_log_event::do_update_pos(Relay_log_info *rli)
{
DBUG_ENTER("Old_rows_log_event::do_update_pos");
int error= 0;
DBUG_PRINT("info", ("flags: %s",
get_flags(STMT_END_F) ? "STMT_END_F " : ""));
if (get_flags(STMT_END_F))
{
/*
Indicate that a statement is finished.
Step the group log position if we are not in a transaction,
otherwise increase the event log position.
*/
rli->stmt_done(log_pos, when);
/*
Clear any errors in thd->net.last_err*. It is not known if this is
needed or not. It is believed that any errors that may exist in
thd->net.last_err* are allowed. Examples of errors are "key not
found", which is produced in the test case rpl_row_conflicts.test
*/
thd->clear_error();
} }
else else
{ {
......
...@@ -97,7 +97,8 @@ static ulonglong get_exact_record_count(TABLE_LIST *tables) ...@@ -97,7 +97,8 @@ static ulonglong get_exact_record_count(TABLE_LIST *tables)
@note @note
This function is only called for queries with sum functions and no This function is only called for queries with sum functions and no
GROUP BY part. GROUP BY part. This means that the result set shall contain a single
row only
@retval @retval
0 no errors 0 no errors
......
...@@ -2082,8 +2082,7 @@ static int has_temporary_error(THD *thd) ...@@ -2082,8 +2082,7 @@ static int has_temporary_error(THD *thd)
@retval 2 No error calling ev->apply_event(), but error calling @retval 2 No error calling ev->apply_event(), but error calling
ev->update_pos(). ev->update_pos().
*/ */
int apply_event_and_update_pos(Log_event* ev, THD* thd, Relay_log_info* rli, int apply_event_and_update_pos(Log_event* ev, THD* thd, Relay_log_info* rli)
bool skip)
{ {
int exec_res= 0; int exec_res= 0;
...@@ -2128,37 +2127,33 @@ int apply_event_and_update_pos(Log_event* ev, THD* thd, Relay_log_info* rli, ...@@ -2128,37 +2127,33 @@ int apply_event_and_update_pos(Log_event* ev, THD* thd, Relay_log_info* rli,
ev->when= my_time(0); ev->when= my_time(0);
ev->thd = thd; // because up to this point, ev->thd == 0 ev->thd = thd; // because up to this point, ev->thd == 0
if (skip) int reason= ev->shall_skip(rli);
{ if (reason == Log_event::EVENT_SKIP_COUNT)
int reason= ev->shall_skip(rli); --rli->slave_skip_counter;
if (reason == Log_event::EVENT_SKIP_COUNT) pthread_mutex_unlock(&rli->data_lock);
--rli->slave_skip_counter; if (reason == Log_event::EVENT_SKIP_NOT)
pthread_mutex_unlock(&rli->data_lock); exec_res= ev->apply_event(rli);
if (reason == Log_event::EVENT_SKIP_NOT)
exec_res= ev->apply_event(rli);
#ifndef DBUG_OFF #ifndef DBUG_OFF
/* /*
This only prints information to the debug trace. This only prints information to the debug trace.
TODO: Print an informational message to the error log? TODO: Print an informational message to the error log?
*/ */
static const char *const explain[] = { static const char *const explain[] = {
// EVENT_SKIP_NOT, // EVENT_SKIP_NOT,
"not skipped", "not skipped",
// EVENT_SKIP_IGNORE, // EVENT_SKIP_IGNORE,
"skipped because event should be ignored", "skipped because event should be ignored",
// EVENT_SKIP_COUNT // EVENT_SKIP_COUNT
"skipped because event skip counter was non-zero" "skipped because event skip counter was non-zero"
}; };
DBUG_PRINT("info", ("OPTION_BEGIN: %d; IN_STMT: %d", DBUG_PRINT("info", ("OPTION_BEGIN: %d; IN_STMT: %d",
thd->options & OPTION_BEGIN ? 1 : 0, thd->options & OPTION_BEGIN ? 1 : 0,
rli->get_flag(Relay_log_info::IN_STMT))); rli->get_flag(Relay_log_info::IN_STMT)));
DBUG_PRINT("skip_event", ("%s event was %s", DBUG_PRINT("skip_event", ("%s event was %s",
ev->get_type_str(), explain[reason])); ev->get_type_str(), explain[reason]));
#endif #endif
}
else
exec_res= ev->apply_event(rli);
DBUG_PRINT("info", ("apply_event error = %d", exec_res)); DBUG_PRINT("info", ("apply_event error = %d", exec_res));
if (exec_res == 0) if (exec_res == 0)
...@@ -2278,7 +2273,7 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli) ...@@ -2278,7 +2273,7 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli)
delete ev; delete ev;
DBUG_RETURN(1); DBUG_RETURN(1);
} }
exec_res= apply_event_and_update_pos(ev, thd, rli, TRUE); exec_res= apply_event_and_update_pos(ev, thd, rli);
/* /*
Format_description_log_event should not be deleted because it will be Format_description_log_event should not be deleted because it will be
......
...@@ -190,8 +190,7 @@ int purge_relay_logs(Relay_log_info* rli, THD *thd, bool just_reset, ...@@ -190,8 +190,7 @@ int purge_relay_logs(Relay_log_info* rli, THD *thd, bool just_reset,
void set_slave_thread_options(THD* thd); void set_slave_thread_options(THD* thd);
void set_slave_thread_default_charset(THD *thd, Relay_log_info const *rli); void set_slave_thread_default_charset(THD *thd, Relay_log_info const *rli);
void rotate_relay_log(Master_info* mi); void rotate_relay_log(Master_info* mi);
int apply_event_and_update_pos(Log_event* ev, THD* thd, Relay_log_info* rli, int apply_event_and_update_pos(Log_event* ev, THD* thd, Relay_log_info* rli);
bool skip);
pthread_handler_t handle_slave_io(void *arg); pthread_handler_t handle_slave_io(void *arg);
pthread_handler_t handle_slave_sql(void *arg); pthread_handler_t handle_slave_sql(void *arg);
......
...@@ -56,17 +56,20 @@ void mysql_client_binlog_statement(THD* thd) ...@@ -56,17 +56,20 @@ void mysql_client_binlog_statement(THD* thd)
Format_description_event. Format_description_event.
*/ */
my_bool have_fd_event= TRUE; my_bool have_fd_event= TRUE;
if (!thd->rli_fake) int err;
Relay_log_info *rli;
rli= thd->rli_fake;
if (!rli)
{ {
thd->rli_fake= new Relay_log_info; rli= thd->rli_fake= new Relay_log_info;
#ifdef HAVE_purify #ifdef HAVE_purify
thd->rli_fake->is_fake= TRUE; rli->is_fake= TRUE;
#endif #endif
have_fd_event= FALSE; have_fd_event= FALSE;
} }
if (thd->rli_fake && !thd->rli_fake->relay_log.description_event_for_exec) if (rli && !rli->relay_log.description_event_for_exec)
{ {
thd->rli_fake->relay_log.description_event_for_exec= rli->relay_log.description_event_for_exec=
new Format_description_log_event(4); new Format_description_log_event(4);
have_fd_event= FALSE; have_fd_event= FALSE;
} }
...@@ -78,16 +81,16 @@ void mysql_client_binlog_statement(THD* thd) ...@@ -78,16 +81,16 @@ void mysql_client_binlog_statement(THD* thd)
/* /*
Out of memory check Out of memory check
*/ */
if (!(thd->rli_fake && if (!(rli &&
thd->rli_fake->relay_log.description_event_for_exec && rli->relay_log.description_event_for_exec &&
buf)) buf))
{ {
my_error(ER_OUTOFMEMORY, MYF(0), 1); /* needed 1 bytes */ my_error(ER_OUTOFMEMORY, MYF(0), 1); /* needed 1 bytes */
goto end; goto end;
} }
thd->rli_fake->sql_thd= thd; rli->sql_thd= thd;
thd->rli_fake->no_storage= TRUE; rli->no_storage= TRUE;
for (char const *strptr= thd->lex->comment.str ; for (char const *strptr= thd->lex->comment.str ;
strptr < thd->lex->comment.str + thd->lex->comment.length ; ) strptr < thd->lex->comment.str + thd->lex->comment.length ; )
...@@ -170,8 +173,7 @@ void mysql_client_binlog_statement(THD* thd) ...@@ -170,8 +173,7 @@ void mysql_client_binlog_statement(THD* thd)
} }
ev= Log_event::read_log_event(bufptr, event_len, &error, ev= Log_event::read_log_event(bufptr, event_len, &error,
thd->rli_fake->relay_log. rli->relay_log.description_event_for_exec);
description_event_for_exec);
DBUG_PRINT("info",("binlog base64 err=%s", error)); DBUG_PRINT("info",("binlog base64 err=%s", error));
if (!ev) if (!ev)
...@@ -209,18 +211,10 @@ void mysql_client_binlog_statement(THD* thd) ...@@ -209,18 +211,10 @@ void mysql_client_binlog_statement(THD* thd)
reporting. reporting.
*/ */
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
if (apply_event_and_update_pos(ev, thd, thd->rli_fake, FALSE)) err= ev->apply_event(rli);
{ #else
delete ev; err= 0;
/*
TODO: Maybe a better error message since the BINLOG statement
now contains several events.
*/
my_error(ER_UNKNOWN_ERROR, MYF(0), "Error executing BINLOG statement");
goto end;
}
#endif #endif
/* /*
Format_description_log_event should not be deleted because it Format_description_log_event should not be deleted because it
will be used to read info about the relay log's format; it will be used to read info about the relay log's format; it
...@@ -228,8 +222,17 @@ void mysql_client_binlog_statement(THD* thd) ...@@ -228,8 +222,17 @@ void mysql_client_binlog_statement(THD* thd)
i.e. when this thread terminates. i.e. when this thread terminates.
*/ */
if (ev->get_type_code() != FORMAT_DESCRIPTION_EVENT) if (ev->get_type_code() != FORMAT_DESCRIPTION_EVENT)
delete ev; delete ev;
ev= 0; ev= 0;
if (err)
{
/*
TODO: Maybe a better error message since the BINLOG statement
now contains several events.
*/
my_error(ER_UNKNOWN_ERROR, MYF(0), "Error executing BINLOG statement");
goto end;
}
} }
} }
...@@ -238,7 +241,7 @@ void mysql_client_binlog_statement(THD* thd) ...@@ -238,7 +241,7 @@ void mysql_client_binlog_statement(THD* thd)
my_ok(thd); my_ok(thd);
end: end:
thd->rli_fake->clear_tables_to_lock(); rli->clear_tables_to_lock();
my_free(buf, MYF(MY_ALLOW_ZERO_PTR)); my_free(buf, MYF(MY_ALLOW_ZERO_PTR));
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -2647,7 +2647,32 @@ class TMP_TABLE_PARAM :public Sql_alloc ...@@ -2647,7 +2647,32 @@ class TMP_TABLE_PARAM :public Sql_alloc
MI_COLUMNDEF *recinfo,*start_recinfo; MI_COLUMNDEF *recinfo,*start_recinfo;
KEY *keyinfo; KEY *keyinfo;
ha_rows end_write_records; ha_rows end_write_records;
uint field_count,sum_func_count,func_count; /**
Number of normal fields in the query, including those referred to
from aggregate functions. Hence, "SELECT `field1`,
SUM(`field2`) from t1" sets this counter to 2.
@see count_field_types
*/
uint field_count;
/**
Number of fields in the query that have functions. Includes both
aggregate functions (e.g., SUM) and non-aggregates (e.g., RAND).
Also counts functions referred to from aggregate functions, i.e.,
"SELECT SUM(RAND())" sets this counter to 2.
@see count_field_types
*/
uint func_count;
/**
Number of fields in the query that have aggregate functions. Note
that the optimizer may choose to optimize away these fields by
replacing them with constants, in which case sum_func_count will
need to be updated.
@see opt_sum_query, count_field_types
*/
uint sum_func_count;
uint hidden_field_count; uint hidden_field_count;
uint group_parts,group_length,group_null_parts; uint group_parts,group_length,group_null_parts;
uint quick_group; uint quick_group;
......
...@@ -644,8 +644,11 @@ JOIN::prepare(Item ***rref_pointer_array, ...@@ -644,8 +644,11 @@ JOIN::prepare(Item ***rref_pointer_array,
this->group= group_list != 0; this->group= group_list != 0;
unit= unit_arg; unit= unit_arg;
if (tmp_table_param.sum_func_count && !group_list)
implicit_grouping= TRUE;
#ifdef RESTRICTED_GROUP #ifdef RESTRICTED_GROUP
if (sum_func_count && !group_list && (func_count || field_count)) if (implicit_grouping)
{ {
my_message(ER_WRONG_SUM_SELECT,ER(ER_WRONG_SUM_SELECT),MYF(0)); my_message(ER_WRONG_SUM_SELECT,ER(ER_WRONG_SUM_SELECT),MYF(0));
goto err; goto err;
...@@ -881,15 +884,23 @@ JOIN::optimize() ...@@ -881,15 +884,23 @@ JOIN::optimize()
} }
#endif #endif
/* Optimize count(*), min() and max() */ /*
if (tables_list && tmp_table_param.sum_func_count && ! group_list) Try to optimize count(*), min() and max() to const fields if
there is implicit grouping (aggregate functions but no
group_list). In this case, the result set shall only contain one
row.
*/
if (tables_list && implicit_grouping)
{ {
int res; int res;
/* /*
opt_sum_query() returns HA_ERR_KEY_NOT_FOUND if no rows match opt_sum_query() returns HA_ERR_KEY_NOT_FOUND if no rows match
to the WHERE conditions, to the WHERE conditions,
or 1 if all items were resolved, or 1 if all items were resolved (optimized away),
or 0, or an error number HA_ERR_... or 0, or an error number HA_ERR_...
If all items were resolved by opt_sum_query, there is no need to
open any tables.
*/ */
if ((res=opt_sum_query(select_lex->leaf_tables, all_fields, conds))) if ((res=opt_sum_query(select_lex->leaf_tables, all_fields, conds)))
{ {
...@@ -2024,7 +2035,7 @@ JOIN::exec() ...@@ -2024,7 +2035,7 @@ JOIN::exec()
count_field_types(select_lex, &curr_join->tmp_table_param, count_field_types(select_lex, &curr_join->tmp_table_param,
*curr_all_fields, 0); *curr_all_fields, 0);
if (curr_join->group || curr_join->tmp_table_param.sum_func_count || if (curr_join->group || curr_join->implicit_grouping ||
(procedure && (procedure->flags & PROC_GROUP))) (procedure && (procedure->flags & PROC_GROUP)))
{ {
if (make_group_fields(this, curr_join)) if (make_group_fields(this, curr_join))
...@@ -10811,6 +10822,12 @@ Next_select_func setup_end_select_func(JOIN *join) ...@@ -10811,6 +10822,12 @@ Next_select_func setup_end_select_func(JOIN *join)
} }
else else
{ {
/*
Choose method for presenting result to user. Use end_send_group
if the query requires grouping (has a GROUP BY clause and/or one or
more aggregate functions). Use end_send if the query should not
be grouped.
*/
if ((join->sort_and_group || if ((join->sort_and_group ||
(join->procedure && join->procedure->flags & PROC_GROUP)) && (join->procedure && join->procedure->flags & PROC_GROUP)) &&
!tmp_tbl->precomputed_group_by) !tmp_tbl->precomputed_group_by)
......
...@@ -278,7 +278,14 @@ class JOIN :public Sql_alloc ...@@ -278,7 +278,14 @@ class JOIN :public Sql_alloc
TABLE **table,**all_tables,*sort_by_table; TABLE **table,**all_tables,*sort_by_table;
uint tables,const_tables; uint tables,const_tables;
uint send_group_parts; uint send_group_parts;
bool sort_and_group,first_record,full_join,group, no_field_update; /**
Indicates that grouping will be performed on the result set during
query execution. This field belongs to query execution.
@see make_group_fields, alloc_group_fields, JOIN::exec
*/
bool sort_and_group;
bool first_record,full_join,group, no_field_update;
bool do_send_rows; bool do_send_rows;
/** /**
TRUE when we want to resume nested loop iterations when TRUE when we want to resume nested loop iterations when
...@@ -428,6 +435,7 @@ class JOIN :public Sql_alloc ...@@ -428,6 +435,7 @@ class JOIN :public Sql_alloc
tables= 0; tables= 0;
const_tables= 0; const_tables= 0;
join_list= 0; join_list= 0;
implicit_grouping= FALSE;
sort_and_group= 0; sort_and_group= 0;
first_record= 0; first_record= 0;
do_send_rows= 1; do_send_rows= 1;
...@@ -533,6 +541,11 @@ class JOIN :public Sql_alloc ...@@ -533,6 +541,11 @@ class JOIN :public Sql_alloc
select_lex == unit->fake_select_lex)); select_lex == unit->fake_select_lex));
} }
private: private:
/**
TRUE if the query contains an aggregate function but has no GROUP
BY clause.
*/
bool implicit_grouping;
bool make_simple_join(JOIN *join, TABLE *tmp_table); bool make_simple_join(JOIN *join, TABLE *tmp_table);
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment