From: Marc Alff Date: May 18 2010 5:58am Subject: bzr commit into mysql-next-mr-bugfixing branch (marc.alff:3177) List-Archive: http://lists.mysql.com/commits/108469 Message-Id: <201005180558.o4I5DXeL010356@rcsinet15.oracle.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============8602379007330771984==" --===============8602379007330771984== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #At file:///Users/malff/BZR_TREE/mysql-next-mr-bugfixing-53617/ based on revid:marc.alff@stripped 3177 Marc Alff 2010-05-17 [merge] local merge added: mysql-test/suite/funcs_1/r/row_count_func.result mysql-test/suite/funcs_1/t/row_count_func-master.opt mysql-test/suite/funcs_1/t/row_count_func.test modified: mysql-test/include/ctype_numconv.inc mysql-test/include/mysqld--help.inc mysql-test/r/ctype_binary.result mysql-test/r/ctype_cp1251.result mysql-test/r/ctype_latin1.result mysql-test/r/ctype_ucs.result mysql-test/r/sp.result mysql-test/suite/funcs_1/r/innodb_storedproc_10.result mysql-test/suite/funcs_1/r/memory_storedproc_10.result mysql-test/suite/funcs_1/r/myisam_storedproc_10.result mysql-test/suite/funcs_1/r/ndb_storedproc_10.result mysql-test/t/parser_stack.test sql/ha_ndbcluster_binlog.cc sql/item_func.cc sql/log_event.cc sql/protocol.cc sql/sql_class.cc sql/sql_class.h sql/sql_delete.cc sql/sql_insert.cc sql/sql_lex.cc sql/sql_lex.h sql/sql_parse.cc sql/sql_parse.h sql/sql_signal.cc sql/sql_update.cc storage/perfschema/pfs_engine_table.cc storage/perfschema/pfs_global.cc storage/perfschema/pfs_global.h === modified file 'mysql-test/include/ctype_numconv.inc' --- a/mysql-test/include/ctype_numconv.inc 2010-02-11 14:28:28 +0000 +++ b/mysql-test/include/ctype_numconv.inc 2010-05-14 05:28:51 +0000 @@ -457,6 +457,8 @@ select * from t1; show create table t1; drop table t1; +# Ensure that row_count() value is reset after drop table. +select 1; select hex(concat(row_count())); create table t1 as select concat(row_count()) as c1; show create table t1; === modified file 'mysql-test/include/mysqld--help.inc' --- a/mysql-test/include/mysqld--help.inc 2010-01-26 21:05:41 +0000 +++ b/mysql-test/include/mysqld--help.inc 2010-05-17 15:28:50 +0000 @@ -23,7 +23,7 @@ perl; while () { next if 1../The following groups are read/; # formatting, skip line consisting entirely of dashes and blanks - next if /^[\- ]+$/; + next if /^[\- ]+\s?$/; next if /Value \(after reading options\)/; # skip table header next if /^($re1) /; next if /^($re2)-/; === modified file 'mysql-test/r/ctype_binary.result' --- a/mysql-test/r/ctype_binary.result 2010-02-11 14:28:28 +0000 +++ b/mysql-test/r/ctype_binary.result 2010-05-14 05:28:51 +0000 @@ -772,6 +772,9 @@ t1 CREATE TABLE `t1` ( `c1` varbinary(31) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; +select 1; +1 +1 select hex(concat(row_count())); hex(concat(row_count())) 2D31 === modified file 'mysql-test/r/ctype_cp1251.result' --- a/mysql-test/r/ctype_cp1251.result 2010-02-11 14:28:28 +0000 +++ b/mysql-test/r/ctype_cp1251.result 2010-05-14 05:28:51 +0000 @@ -854,6 +854,9 @@ t1 CREATE TABLE `t1` ( `c1` varchar(31) CHARACTER SET cp1251 DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; +select 1; +1 +1 select hex(concat(row_count())); hex(concat(row_count())) 2D31 === modified file 'mysql-test/r/ctype_latin1.result' --- a/mysql-test/r/ctype_latin1.result 2010-02-11 14:28:28 +0000 +++ b/mysql-test/r/ctype_latin1.result 2010-05-14 05:28:51 +0000 @@ -1182,6 +1182,9 @@ t1 CREATE TABLE `t1` ( `c1` varchar(31) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; +select 1; +1 +1 select hex(concat(row_count())); hex(concat(row_count())) 2D31 === modified file 'mysql-test/r/ctype_ucs.result' --- a/mysql-test/r/ctype_ucs.result 2010-02-11 14:28:28 +0000 +++ b/mysql-test/r/ctype_ucs.result 2010-05-14 05:28:51 +0000 @@ -2006,6 +2006,9 @@ t1 CREATE TABLE `t1` ( `c1` varchar(31) CHARACTER SET ucs2 DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; +select 1; +1 +1 select hex(concat(row_count())); hex(concat(row_count())) 002D0031 === modified file 'mysql-test/r/sp.result' --- a/mysql-test/r/sp.result 2010-04-19 08:29:52 +0000 +++ b/mysql-test/r/sp.result 2010-05-14 05:29:47 +0000 @@ -2590,11 +2590,11 @@ row_count() call bug4905()| select row_count()| row_count() --1 +0 call bug4905()| select row_count()| row_count() --1 +0 select * from t3| s1 1 === modified file 'mysql-test/suite/funcs_1/r/innodb_storedproc_10.result' --- a/mysql-test/suite/funcs_1/r/innodb_storedproc_10.result 2009-01-31 19:22:59 +0000 +++ b/mysql-test/suite/funcs_1/r/innodb_storedproc_10.result 2010-05-14 05:28:51 +0000 @@ -375,7 +375,7 @@ row_count() after delete 2 SELECT row_count(); row_count() --1 +0 SELECT * FROM temp; f1 f2 f3 f4 f5 f6 qwe xyz 1998-03-26 100 uvw 1000 === modified file 'mysql-test/suite/funcs_1/r/memory_storedproc_10.result' --- a/mysql-test/suite/funcs_1/r/memory_storedproc_10.result 2009-01-31 19:22:59 +0000 +++ b/mysql-test/suite/funcs_1/r/memory_storedproc_10.result 2010-05-14 05:28:51 +0000 @@ -376,7 +376,7 @@ row_count() after delete 2 SELECT row_count(); row_count() --1 +0 SELECT * FROM temp; f1 f2 f3 f4 f5 f6 qwe xyz 1998-03-26 100 uvw 1000 === modified file 'mysql-test/suite/funcs_1/r/myisam_storedproc_10.result' --- a/mysql-test/suite/funcs_1/r/myisam_storedproc_10.result 2009-01-31 19:22:59 +0000 +++ b/mysql-test/suite/funcs_1/r/myisam_storedproc_10.result 2010-05-14 05:28:51 +0000 @@ -376,7 +376,7 @@ row_count() after delete 2 SELECT row_count(); row_count() --1 +0 SELECT * FROM temp; f1 f2 f3 f4 f5 f6 qwe xyz 1998-03-26 100 uvw 1000 === modified file 'mysql-test/suite/funcs_1/r/ndb_storedproc_10.result' --- a/mysql-test/suite/funcs_1/r/ndb_storedproc_10.result 2009-01-31 19:22:59 +0000 +++ b/mysql-test/suite/funcs_1/r/ndb_storedproc_10.result 2010-05-14 05:28:51 +0000 @@ -375,7 +375,7 @@ row_count() after delete 2 SELECT row_count(); row_count() --1 +0 SELECT * FROM temp; f1 f2 f3 f4 f5 f6 qwe xyz 1998-03-26 100 uvw 1000 === added file 'mysql-test/suite/funcs_1/r/row_count_func.result' --- a/mysql-test/suite/funcs_1/r/row_count_func.result 1970-01-01 00:00:00 +0000 +++ b/mysql-test/suite/funcs_1/r/row_count_func.result 2010-05-14 05:28:51 +0000 @@ -0,0 +1,79 @@ + +# -- +# -- Test case for Bug#21818. +# -- + +DROP TABLE IF EXISTS t1; +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES (1), (2), (3); + +# -- Check 1. +SELECT * FROM t1 INTO OUTFILE "MYSQL_TMP_DIR/bug21818.txt"; +affected rows: 3 + +SELECT ROW_COUNT(); +ROW_COUNT() +3 + +# -- Check 2. +SELECT a FROM t1 LIMIT 1 INTO @a; +affected rows: 1 + +SELECT ROW_COUNT(); +ROW_COUNT() +1 + +# -- Check 3. +DROP DATABASE IF EXISTS mysqltest1; +CREATE DATABASE mysqltest1; +affected rows: 1 + +SELECT ROW_COUNT(); +ROW_COUNT() +1 +DROP DATABASE mysqltest1; + +# -- Check 4. +DELETE FROM t1; +LOAD DATA INFILE 'MYSQL_TMP_DIR/bug21818.txt' INTO TABLE t1(a); +affected rows: 3 +info: Records: 3 Deleted: 0 Skipped: 0 Warnings: 0 + +SELECT ROW_COUNT(); +ROW_COUNT() +3 + +# -- Check 5. +ALTER TABLE t1 ADD COLUMN b VARCHAR(255); +affected rows: 3 +info: Records: 3 Duplicates: 0 Warnings: 0 + +SELECT ROW_COUNT(); +ROW_COUNT() +3 + +DROP TABLE t1; + +# -- Check 6. +DROP TABLE IF EXISTS t2; +CREATE TABLE t1(a INT); +CREATE TABLE t2(a INT); +INSERT INTO t1 VALUES (1), (2), (3); +INSERT INTO t2 VALUES (ROW_COUNT()); +SELECT * FROM t2; +a +3 +DROP TABLE t1; +DROP TABLE t2; + +# -- Check 7 (check that SQL errors reset row_count to -1). +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES (1), (2), (3); +SELECT f1(); +ERROR 42000: FUNCTION test.f1 does not exist +SELECT ROW_COUNT(); +ROW_COUNT() +-1 +DROP TABLE t1; + +# -- End of test case for Bug#21818. === added file 'mysql-test/suite/funcs_1/t/row_count_func-master.opt' --- a/mysql-test/suite/funcs_1/t/row_count_func-master.opt 1970-01-01 00:00:00 +0000 +++ b/mysql-test/suite/funcs_1/t/row_count_func-master.opt 2010-05-14 05:28:51 +0000 @@ -0,0 +1 @@ +--secure-file-priv=$MYSQL_TMP_DIR === added file 'mysql-test/suite/funcs_1/t/row_count_func.test' --- a/mysql-test/suite/funcs_1/t/row_count_func.test 1970-01-01 00:00:00 +0000 +++ b/mysql-test/suite/funcs_1/t/row_count_func.test 2010-05-14 05:28:51 +0000 @@ -0,0 +1,115 @@ +--echo +--echo # -- +--echo # -- Test case for Bug#21818. +--echo # -- +--echo + +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES (1), (2), (3); + +--echo +--echo # -- Check 1. + +--enable_info +--echo SELECT * FROM t1 INTO OUTFILE "MYSQL_TMP_DIR/bug21818.txt"; +--disable_query_log # to avoid $MYSQL_TMP_DIR in query log +--eval SELECT * FROM t1 INTO OUTFILE "$MYSQL_TMP_DIR/bug21818.txt" +--enable_query_log +--disable_info + +--echo +SELECT ROW_COUNT(); + +--echo +--echo # -- Check 2. + +--enable_info +SELECT a FROM t1 LIMIT 1 INTO @a; +--disable_info + +--echo +SELECT ROW_COUNT(); + +--echo +--echo # -- Check 3. + +--disable_warnings +DROP DATABASE IF EXISTS mysqltest1; +--enable_warnings + +--enable_info +CREATE DATABASE mysqltest1; +--disable_info + +--echo +SELECT ROW_COUNT(); + +DROP DATABASE mysqltest1; + +--echo +--echo # -- Check 4. + +DELETE FROM t1; + +--enable_info +--echo LOAD DATA INFILE 'MYSQL_TMP_DIR/bug21818.txt' INTO TABLE t1(a); +--disable_query_log # to avoid $MYSQL_TMP_DIR in query log +--eval LOAD DATA INFILE '$MYSQL_TMP_DIR/bug21818.txt' INTO TABLE t1(a) +--enable_query_log +--disable_info + +--echo +SELECT ROW_COUNT(); + +--remove_file $MYSQL_TMP_DIR/bug21818.txt + +--echo +--echo # -- Check 5. + +--enable_info +ALTER TABLE t1 ADD COLUMN b VARCHAR(255); +--disable_info + +--echo +SELECT ROW_COUNT(); + +--echo +DROP TABLE t1; + +--echo +--echo # -- Check 6. + +--disable_warnings +DROP TABLE IF EXISTS t2; +--enable_warnings + +CREATE TABLE t1(a INT); +CREATE TABLE t2(a INT); + +INSERT INTO t1 VALUES (1), (2), (3); +INSERT INTO t2 VALUES (ROW_COUNT()); + +SELECT * FROM t2; + +DROP TABLE t1; +DROP TABLE t2; + +--echo +--echo # -- Check 7 (check that SQL errors reset row_count to -1). + +CREATE TABLE t1(a INT); + +INSERT INTO t1 VALUES (1), (2), (3); +--error ER_SP_DOES_NOT_EXIST +SELECT f1(); + +SELECT ROW_COUNT(); + +DROP TABLE t1; + +--echo +--echo # -- End of test case for Bug#21818. === modified file 'mysql-test/t/parser_stack.test' --- a/mysql-test/t/parser_stack.test 2008-07-14 21:41:30 +0000 +++ b/mysql-test/t/parser_stack.test 2010-05-14 18:11:25 +0000 @@ -399,4 +399,12 @@ delimiter ;$$ drop procedure p_37228; +# +# Bug#27863 (excessive memory usage for many small queries in a multiquery +# packet). +# +let $i=`select repeat("set @a=1;", 65535)`; +--disable_query_log +eval $i; +--enable_query_log === modified file 'sql/ha_ndbcluster_binlog.cc' --- a/sql/ha_ndbcluster_binlog.cc 2010-03-31 14:05:33 +0000 +++ b/sql/ha_ndbcluster_binlog.cc 2010-05-17 12:10:26 +0000 @@ -263,7 +263,6 @@ static void run_query(THD *thd, char *bu ulonglong save_thd_options= thd->variables.option_bits; DBUG_ASSERT(sizeof(save_thd_options) == sizeof(thd->variables.option_bits)); NET save_thd_net= thd->net; - const char* found_semicolon= NULL; bzero((char*) &thd->net, sizeof(NET)); thd->set_query(buf, (uint) (end - buf)); @@ -277,7 +276,10 @@ static void run_query(THD *thd, char *bu DBUG_ASSERT(!thd->in_sub_stmt); DBUG_ASSERT(!thd->locked_tables_mode); - mysql_parse(thd, thd->query(), thd->query_length(), &found_semicolon); + { + Parser_state parser_state(thd, thd->query(), thd->query_length()); + mysql_parse(thd, thd->query(), thd->query_length(), &parser_state); + } if (no_print_error && thd->is_slave_error) { === modified file 'sql/item_func.cc' --- a/sql/item_func.cc 2010-04-07 11:58:40 +0000 +++ b/sql/item_func.cc 2010-05-14 05:28:51 +0000 @@ -6030,7 +6030,7 @@ longlong Item_func_row_count::val_int() DBUG_ASSERT(fixed == 1); THD *thd= current_thd; - return thd->row_count_func; + return thd->get_row_count_func(); } === modified file 'sql/log_event.cc' --- a/sql/log_event.cc 2010-04-29 11:20:36 +0000 +++ b/sql/log_event.cc 2010-05-14 18:38:28 +0000 @@ -3290,8 +3290,8 @@ int Query_log_event::do_apply_event(Rela thd->table_map_for_update= (table_map)table_map_for_update; /* Execute the query (note that we bypass dispatch_command()) */ - const char* found_semicolon= NULL; - mysql_parse(thd, thd->query(), thd->query_length(), &found_semicolon); + Parser_state parser_state(thd, thd->query(), thd->query_length()); + mysql_parse(thd, thd->query(), thd->query_length(), &parser_state); log_slow_statement(thd); /* === modified file 'sql/protocol.cc' --- a/sql/protocol.cc 2010-03-31 14:05:33 +0000 +++ b/sql/protocol.cc 2010-05-14 05:28:51 +0000 @@ -210,7 +210,7 @@ net_send_ok(THD *thd, NET *net= &thd->net; uchar buff[MYSQL_ERRMSG_SIZE+10],*pos; bool error= FALSE; - DBUG_ENTER("my_ok"); + DBUG_ENTER("net_send_ok"); if (! net->vio) // hack for re-parsing queries { === modified file 'sql/sql_class.cc' --- a/sql/sql_class.cc 2010-04-29 11:20:36 +0000 +++ b/sql/sql_class.cc 2010-05-14 05:29:47 +0000 @@ -512,7 +512,7 @@ THD::THD() cuted_fields= 0L; sent_row_count= 0L; limit_found_rows= 0; - row_count_func= -1; + m_row_count_func= -1; statement_id_counter= 0UL; // Must be reset to handle error with THD's created for init of mysqld lex->current_select= 0; @@ -804,7 +804,10 @@ MYSQL_ERROR* THD::raise_condition(uint s else { if (! stmt_da->is_error()) + { + set_row_count_func(-1); stmt_da->set_error_status(this, sql_errno, msg, sqlstate); + } } } @@ -1805,11 +1808,6 @@ bool select_to_file::send_eof() error= 1; if (!error) { - /* - In order to remember the value of affected rows for ROW_COUNT() - function, SELECT INTO has to have an own SQLCOM. - TODO: split from SQLCOM_SELECT - */ ::my_ok(thd,row_count); } file= -1; @@ -2830,11 +2828,6 @@ bool select_dumpvar::send_eof() if (! row_count) push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_SP_FETCH_NO_DATA, ER(ER_SP_FETCH_NO_DATA)); - /* - In order to remember the value of affected rows for ROW_COUNT() - function, SELECT INTO has to have an own SQLCOM. - TODO: split from SQLCOM_SELECT - */ ::my_ok(thd,row_count); return 0; } === modified file 'sql/sql_class.h' --- a/sql/sql_class.h 2010-04-26 09:06:35 +0000 +++ b/sql/sql_class.h 2010-05-14 05:29:47 +0000 @@ -1994,7 +1994,50 @@ public: } ulonglong limit_found_rows; - longlong row_count_func; /* For the ROW_COUNT() function */ + +private: + /** + Stores the result of ROW_COUNT() function. + + ROW_COUNT() function is a MySQL extention, but we try to keep it + similar to ROW_COUNT member of the GET DIAGNOSTICS stack of the SQL + standard (see SQL99, part 2, search for ROW_COUNT). It's value is + implementation defined for anything except INSERT, DELETE, UPDATE. + + ROW_COUNT is assigned according to the following rules: + + - In my_ok(): + - for DML statements: to the number of affected rows; + - for DDL statements: to 0. + + - In my_eof(): to -1 to indicate that there was a result set. + + We derive this semantics from the JDBC specification, where int + java.sql.Statement.getUpdateCount() is defined to (sic) "return the + current result as an update count; if the result is a ResultSet + object or there are no more results, -1 is returned". + + - In my_error(): to -1 to be compatible with the MySQL C API and + MySQL ODBC driver. + + - For SIGNAL statements: to 0 per WL#2110 specification (see also + sql_signal.cc comment). Zero is used since that's the "default" + value of ROW_COUNT in the diagnostics area. + */ + + longlong m_row_count_func; /* For the ROW_COUNT() function */ + +public: + inline longlong get_row_count_func() const + { + return m_row_count_func; + } + + inline void set_row_count_func(longlong row_count_func) + { + m_row_count_func= row_count_func; + } + ha_rows cuted_fields; /* @@ -2781,6 +2824,7 @@ inline void my_ok(THD *thd, ulonglong affected_rows= 0, ulonglong id= 0, const char *message= NULL) { + thd->set_row_count_func(affected_rows); thd->stmt_da->set_ok_status(thd, affected_rows, id, message); } @@ -2790,6 +2834,7 @@ my_ok(THD *thd, ulonglong affected_rows= inline void my_eof(THD *thd) { + thd->set_row_count_func(-1); thd->stmt_da->set_eof_status(thd); } @@ -3451,7 +3496,7 @@ public: /* Bits in sql_command_flags */ #define CF_CHANGES_DATA (1U << 0) -#define CF_HAS_ROW_COUNT (1U << 1) +/* The 2nd bit is unused -- it used to be CF_HAS_ROW_COUNT. */ #define CF_STATUS_COMMAND (1U << 2) #define CF_SHOW_TABLE_COMMAND (1U << 3) #define CF_WRITE_LOGS_COMMAND (1U << 4) === modified file 'sql/sql_delete.cc' --- a/sql/sql_delete.cc 2010-04-01 19:34:09 +0000 +++ b/sql/sql_delete.cc 2010-05-14 05:29:47 +0000 @@ -187,8 +187,8 @@ bool mysql_delete(THD *thd, TABLE_LIST * if (prune_partitions(thd, table, conds)) { free_underlaid_joins(thd, select_lex); - thd->row_count_func= 0; - my_ok(thd, (ha_rows) thd->row_count_func); // No matching records + // No matching record + my_ok(thd, 0); DBUG_RETURN(0); } #endif @@ -204,7 +204,6 @@ bool mysql_delete(THD *thd, TABLE_LIST * { delete select; free_underlaid_joins(thd, select_lex); - thd->row_count_func= 0; /* Error was already created by quick select evaluation (check_quick()). TODO: Add error code output parameter to Item::val_xxx() methods. @@ -213,7 +212,7 @@ bool mysql_delete(THD *thd, TABLE_LIST * */ if (thd->is_error()) DBUG_RETURN(TRUE); - my_ok(thd, (ha_rows) thd->row_count_func); + my_ok(thd, 0); /* We don't need to call reset_auto_increment in this case, because mysql_truncate always gives a NULL conds argument, hence we never @@ -460,8 +459,7 @@ cleanup: If a TRUNCATE TABLE was issued, the number of rows should be reported as zero since the exact number is unknown. */ - thd->row_count_func= reset_auto_increment ? 0 : deleted; - my_ok(thd, (ha_rows) thd->row_count_func); + my_ok(thd, reset_auto_increment ? 0 : deleted); DBUG_PRINT("info",("%ld records deleted",(long) deleted)); } DBUG_RETURN(error >= 0 || thd->is_error()); @@ -1058,8 +1056,7 @@ bool multi_delete::send_eof() if (!local_error) { - thd->row_count_func= deleted; - ::my_ok(thd, (ha_rows) thd->row_count_func); + ::my_ok(thd, deleted); } return 0; } === modified file 'sql/sql_insert.cc' --- a/sql/sql_insert.cc 2010-04-07 12:02:19 +0000 +++ b/sql/sql_insert.cc 2010-05-14 05:29:47 +0000 @@ -1005,10 +1005,10 @@ bool mysql_insert(THD *thd,TABLE_LIST *t if (values_list.elements == 1 && (!(thd->variables.option_bits & OPTION_WARNINGS) || !thd->cuted_fields)) { - thd->row_count_func= info.copied + info.deleted + - ((thd->client_capabilities & CLIENT_FOUND_ROWS) ? - info.touched : info.updated); - my_ok(thd, (ulong) thd->row_count_func, id); + my_ok(thd, info.copied + info.deleted + + ((thd->client_capabilities & CLIENT_FOUND_ROWS) ? + info.touched : info.updated), + id); } else { @@ -1024,8 +1024,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *t sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records, (ulong) (info.deleted + updated), (ulong) thd->warning_info->statement_warn_count()); - thd->row_count_func= info.copied + info.deleted + updated; - ::my_ok(thd, (ulong) thd->row_count_func, id, buff); + ::my_ok(thd, info.copied + info.deleted + updated, id, buff); } thd->abort_on_warning= 0; DBUG_RETURN(FALSE); @@ -3337,7 +3336,7 @@ bool select_insert::send_eof() { int error; bool const trans_table= table->file->has_transactions(); - ulonglong id; + ulonglong id, row_count; bool changed; THD::killed_state killed_status= thd->killed; DBUG_ENTER("select_insert::send_eof"); @@ -3403,16 +3402,15 @@ bool select_insert::send_eof() sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records, (ulong) (info.deleted+info.updated), (ulong) thd->warning_info->statement_warn_count()); - thd->row_count_func= info.copied + info.deleted + - ((thd->client_capabilities & CLIENT_FOUND_ROWS) ? - info.touched : info.updated); - + row_count= info.copied + info.deleted + + ((thd->client_capabilities & CLIENT_FOUND_ROWS) ? + info.touched : info.updated); id= (thd->first_successful_insert_id_in_cur_stmt > 0) ? thd->first_successful_insert_id_in_cur_stmt : (thd->arg_of_last_insert_id_function ? thd->first_successful_insert_id_in_prev_stmt : (info.copied ? autoinc_value_of_last_inserted_row : 0)); - ::my_ok(thd, (ulong) thd->row_count_func, id, buff); + ::my_ok(thd, row_count, id, buff); DBUG_RETURN(0); } === modified file 'sql/sql_lex.cc' --- a/sql/sql_lex.cc 2010-04-19 15:12:28 +0000 +++ b/sql/sql_lex.cc 2010-05-14 18:38:28 +0000 @@ -142,37 +142,64 @@ st_parsing_options::reset() allows_derived= TRUE; } + +/** + Perform initialization of Lex_input_stream instance. + + Basically, a buffer for pre-processed query. This buffer should be large + enough to keep multi-statement query. The allocation is done once in the + Lex_input_stream constructor in order to prevent memory pollution when + the server is processing large multi-statement queries. + + @todo Check return value of THD::alloc(). +*/ + Lex_input_stream::Lex_input_stream(THD *thd, const char* buffer, unsigned int length) -: m_thd(thd), - yylineno(1), - yytoklen(0), - yylval(NULL), - lookahead_token(-1), - lookahead_yylval(NULL), - m_ptr(buffer), - m_tok_start(NULL), - m_tok_end(NULL), - m_end_of_query(buffer + length), - m_tok_start_prev(NULL), - m_buf(buffer), - m_buf_length(length), - m_echo(TRUE), - m_cpp_tok_start(NULL), - m_cpp_tok_start_prev(NULL), - m_cpp_tok_end(NULL), - m_body_utf8(NULL), - m_cpp_utf8_processed_ptr(NULL), - next_state(MY_LEX_START), - found_semicolon(NULL), - ignore_space(test(thd->variables.sql_mode & MODE_IGNORE_SPACE)), - stmt_prepare_mode(FALSE), - multi_statements(TRUE), - in_comment(NO_COMMENT), - m_underscore_cs(NULL) + :m_thd(thd) { m_cpp_buf= (char*) thd->alloc(length + 1); + reset(buffer, length); +} + + +/** + Prepare Lex_input_stream instance state for use for handling next SQL statement. + + It should be called between two statements in a multi-statement query. + The operation resets the input stream to the beginning-of-parse state, + but does not reallocate m_cpp_buf. +*/ + +void +Lex_input_stream::reset(const char *buffer, unsigned int length) +{ + yylineno= 1; + yytoklen= 0; + yylval= NULL; + lookahead_token= -1; + lookahead_yylval= NULL; + m_ptr= buffer; + m_tok_start= NULL; + m_tok_end= NULL; + m_end_of_query= buffer + length; + m_tok_start_prev= NULL; + m_buf= buffer; + m_buf_length= length; + m_echo= TRUE; + m_cpp_tok_start= NULL; + m_cpp_tok_start_prev= NULL; + m_cpp_tok_end= NULL; + m_body_utf8= NULL; + m_cpp_utf8_processed_ptr= NULL; + next_state= MY_LEX_START; + found_semicolon= NULL; + ignore_space= test(m_thd->variables.sql_mode & MODE_IGNORE_SPACE); + stmt_prepare_mode= FALSE; + multi_statements= TRUE; + in_comment=NO_COMMENT; + m_underscore_cs= NULL; m_cpp_ptr= m_cpp_buf; } === modified file 'sql/sql_lex.h' --- a/sql/sql_lex.h 2010-04-19 15:12:28 +0000 +++ b/sql/sql_lex.h 2010-05-14 18:38:28 +0000 @@ -1378,6 +1378,8 @@ public: Lex_input_stream(THD *thd, const char* buff, unsigned int length); ~Lex_input_stream(); + void reset(const char *buff, unsigned int length); + /** Set the echo mode. @@ -2207,8 +2209,8 @@ struct LEX: public Query_tables_list class Set_signal_information { public: - /** Constructor. */ - Set_signal_information(); + /** Empty default constructor, use clear() */ + Set_signal_information() {} /** Copy constructor. */ Set_signal_information(const Set_signal_information& set); @@ -2221,7 +2223,7 @@ public: void clear(); /** - For each contition item assignment, m_item[] contains the parsed tree + For each condition item assignment, m_item[] contains the parsed tree that represents the expression assigned, if any. m_item[] is an array indexed by Diag_condition_item_name. */ @@ -2238,8 +2240,16 @@ class Yacc_state { public: Yacc_state() - : yacc_yyss(NULL), yacc_yyvs(NULL) - {} + { + reset(); + } + + void reset() + { + yacc_yyss= NULL; + yacc_yyvs= NULL; + m_set_signal_info.clear(); + } ~Yacc_state(); @@ -2284,6 +2294,12 @@ public: Lex_input_stream m_lip; Yacc_state m_yacc; + + void reset(const char *found_semicolon, unsigned int length) + { + m_lip.reset(found_semicolon, length); + m_yacc.reset(); + } }; === modified file 'sql/sql_parse.cc' --- a/sql/sql_parse.cc 2010-04-26 09:06:35 +0000 +++ b/sql/sql_parse.cc 2010-05-14 18:38:28 +0000 @@ -274,22 +274,20 @@ void init_update_queries(void) sql_command_flags[SQLCOM_CREATE_TRIGGER]= CF_AUTO_COMMIT_TRANS; sql_command_flags[SQLCOM_DROP_TRIGGER]= CF_AUTO_COMMIT_TRANS; - sql_command_flags[SQLCOM_UPDATE]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT | - CF_REEXECUTION_FRAGILE | CF_PROTECT_AGAINST_GRL; - sql_command_flags[SQLCOM_UPDATE_MULTI]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT | - CF_REEXECUTION_FRAGILE | CF_PROTECT_AGAINST_GRL; - sql_command_flags[SQLCOM_INSERT]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT | - CF_REEXECUTION_FRAGILE | CF_PROTECT_AGAINST_GRL; - sql_command_flags[SQLCOM_INSERT_SELECT]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT | - CF_REEXECUTION_FRAGILE | CF_PROTECT_AGAINST_GRL; - sql_command_flags[SQLCOM_DELETE]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT | - CF_REEXECUTION_FRAGILE | CF_PROTECT_AGAINST_GRL; - sql_command_flags[SQLCOM_DELETE_MULTI]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT | - CF_REEXECUTION_FRAGILE | CF_PROTECT_AGAINST_GRL; - sql_command_flags[SQLCOM_REPLACE]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT | - CF_REEXECUTION_FRAGILE; - sql_command_flags[SQLCOM_REPLACE_SELECT]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT | - CF_REEXECUTION_FRAGILE; + sql_command_flags[SQLCOM_UPDATE]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE | + CF_PROTECT_AGAINST_GRL; + sql_command_flags[SQLCOM_UPDATE_MULTI]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE | + CF_PROTECT_AGAINST_GRL; + sql_command_flags[SQLCOM_INSERT]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE | + CF_PROTECT_AGAINST_GRL; + sql_command_flags[SQLCOM_INSERT_SELECT]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE | + CF_PROTECT_AGAINST_GRL; + sql_command_flags[SQLCOM_DELETE]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE | + CF_PROTECT_AGAINST_GRL; + sql_command_flags[SQLCOM_DELETE_MULTI]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE | + CF_PROTECT_AGAINST_GRL; + sql_command_flags[SQLCOM_REPLACE]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE; + sql_command_flags[SQLCOM_REPLACE_SELECT]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE; sql_command_flags[SQLCOM_SELECT]= CF_REEXECUTION_FRAGILE; sql_command_flags[SQLCOM_SET_OPTION]= CF_REEXECUTION_FRAGILE | CF_AUTO_COMMIT_TRANS; sql_command_flags[SQLCOM_DO]= CF_REEXECUTION_FRAGILE; @@ -367,8 +365,7 @@ void init_update_queries(void) last called (or executed) statement is preserved. See mysql_execute_command() for how CF_ROW_COUNT is used. */ - sql_command_flags[SQLCOM_CALL]= CF_HAS_ROW_COUNT | CF_REEXECUTION_FRAGILE; - sql_command_flags[SQLCOM_EXECUTE]= CF_HAS_ROW_COUNT; + sql_command_flags[SQLCOM_CALL]= CF_REEXECUTION_FRAGILE; /* The following admin table operations are allowed @@ -461,7 +458,6 @@ static void handle_bootstrap_impl(THD *t { MYSQL_FILE *file= bootstrap_file; char *buff; - const char* found_semicolon= NULL; DBUG_ENTER("handle_bootstrap"); @@ -534,7 +530,8 @@ static void handle_bootstrap_impl(THD *t mode we have only one thread. */ thd->set_time(); - mysql_parse(thd, thd->query(), length, & found_semicolon); + Parser_state parser_state(thd, thd->query(), length); + mysql_parse(thd, thd->query(), length, &parser_state); close_thread_tables(thd); // Free tables bootstrap_error= thd->is_error(); @@ -1077,19 +1074,21 @@ bool dispatch_command(enum enum_server_c (char *) thd->security_ctx->host_or_ip); char *packet_end= thd->query() + thd->query_length(); /* 'b' stands for 'buffer' parameter', special for 'my_snprintf' */ - const char* end_of_stmt= NULL; general_log_write(thd, command, thd->query(), thd->query_length()); DBUG_PRINT("query",("%-.4096s",thd->query())); #if defined(ENABLED_PROFILING) thd->profiling.set_query_source(thd->query(), thd->query_length()); #endif + Parser_state parser_state(thd, thd->query(), thd->query_length()); - mysql_parse(thd, thd->query(), thd->query_length(), &end_of_stmt); + mysql_parse(thd, thd->query(), thd->query_length(), &parser_state); - while (!thd->killed && (end_of_stmt != NULL) && ! thd->is_error()) + while (!thd->killed && (parser_state.m_lip.found_semicolon != NULL) && + ! thd->is_error()) { - char *beginning_of_next_stmt= (char*) end_of_stmt; + char *beginning_of_next_stmt= (char*) + parser_state.m_lip.found_semicolon; thd->protocol->end_statement(); query_cache_end_of_result(thd); @@ -1130,8 +1129,9 @@ bool dispatch_command(enum enum_server_c */ statistic_increment(thd->status_var.questions, &LOCK_status); thd->set_time(); /* Reset the query start time. */ + parser_state.reset(beginning_of_next_stmt, length); /* TODO: set thd->lex->sql_command to SQLCOM_END here */ - mysql_parse(thd, beginning_of_next_stmt, length, &end_of_stmt); + mysql_parse(thd, beginning_of_next_stmt, length, &parser_state); } DBUG_PRINT("info",("query ready")); @@ -3184,7 +3184,7 @@ end_with_restore_list: res= mysql_insert(thd, all_tables, lex->field_list, lex->many_values, lex->update_list, lex->value_list, lex->duplicates, lex->ignore); - MYSQL_INSERT_DONE(res, (ulong) thd->row_count_func); + MYSQL_INSERT_DONE(res, (ulong) thd->get_row_count_func()); /* If we have inserted into a VIEW, and the base table has AUTO_INCREMENT column, but this column is not accessible through @@ -3250,7 +3250,7 @@ end_with_restore_list: delete sel_result; } /* revert changes for SP */ - MYSQL_INSERT_SELECT_DONE(res, (ulong) thd->row_count_func); + MYSQL_INSERT_SELECT_DONE(res, (ulong) thd->get_row_count_func()); select_lex->table_list.first= (uchar*) first_table; } /* @@ -3296,7 +3296,7 @@ end_with_restore_list: &select_lex->order_list, unit->select_limit_cnt, select_lex->options, FALSE); - MYSQL_DELETE_DONE(res, (ulong) thd->row_count_func); + MYSQL_DELETE_DONE(res, (ulong) thd->get_row_count_func()); break; } case SQLCOM_DELETE_MULTI: @@ -4299,8 +4299,9 @@ create_sp_error: thd->server_status&= ~bits_to_be_cleared; if (!res) - my_ok(thd, (ulong) (thd->row_count_func < 0 ? 0 : - thd->row_count_func)); + { + my_ok(thd, (thd->get_row_count_func() < 0) ? 0 : thd->get_row_count_func()); + } else { DBUG_ASSERT(thd->is_error() || thd->killed); @@ -4687,15 +4688,6 @@ create_sp_error: if (thd->one_shot_set && lex->sql_command != SQLCOM_SET_OPTION) reset_one_shot_variables(thd); - /* - The return value for ROW_COUNT() is "implementation dependent" if the - statement is not DELETE, INSERT or UPDATE, but -1 is what JDBC and ODBC - wants. We also keep the last value in case of SQLCOM_CALL or - SQLCOM_EXECUTE. - */ - if (!(sql_command_flags[lex->sql_command] & CF_HAS_ROW_COUNT)) - thd->row_count_func= -1; - goto finish; error: @@ -5732,7 +5724,7 @@ void mysql_init_multi_delete(LEX *lex) */ void mysql_parse(THD *thd, const char *inBuf, uint length, - const char ** found_semicolon) + Parser_state *parser_state) { int error; DBUG_ENTER("mysql_parse"); @@ -5762,10 +5754,7 @@ void mysql_parse(THD *thd, const char *i { LEX *lex= thd->lex; - Parser_state parser_state(thd, inBuf, length); - - bool err= parse_sql(thd, & parser_state, NULL); - *found_semicolon= parser_state.m_lip.found_semicolon; + bool err= parse_sql(thd, parser_state, NULL); if (!err) { @@ -5780,6 +5769,7 @@ void mysql_parse(THD *thd, const char *i { if (! thd->is_error()) { + const char *found_semicolon= parser_state->m_lip.found_semicolon; /* Binlog logs a string starting from thd->query and having length thd->query_length; so we set thd->query_length correctly (to not @@ -5790,12 +5780,12 @@ void mysql_parse(THD *thd, const char *i PROCESSLIST. Note that we don't need LOCK_thread_count to modify query_length. */ - if (*found_semicolon && (ulong) (*found_semicolon - thd->query())) + if (found_semicolon && (ulong) (found_semicolon - thd->query())) thd->set_query_inner(thd->query(), - (uint32) (*found_semicolon - + (uint32) (found_semicolon - thd->query() - 1)); /* Actually execute the query */ - if (*found_semicolon) + if (found_semicolon) { lex->safe_to_cache_query= 0; thd->server_status|= SERVER_MORE_RESULTS_EXISTS; @@ -5832,11 +5822,6 @@ void mysql_parse(THD *thd, const char *i thd->cleanup_after_query(); DBUG_ASSERT(thd->change_list.is_empty()); } - else - { - /* There are no multi queries in the cache. */ - *found_semicolon= NULL; - } DBUG_VOID_RETURN; } === modified file 'sql/sql_parse.h' --- a/sql/sql_parse.h 2010-04-12 13:17:37 +0000 +++ b/sql/sql_parse.h 2010-05-14 18:11:25 +0000 @@ -84,7 +84,7 @@ bool is_log_table_write_query(enum enum_ bool alloc_query(THD *thd, const char *packet, uint packet_length); void mysql_init_select(LEX *lex); void mysql_parse(THD *thd, const char *inBuf, uint length, - const char ** semicolon); + Parser_state *parser_state); void mysql_reset_thd_for_next_command(THD *thd); bool mysql_new_select(LEX *lex, bool move_down); void create_select_for_variable(const char *var_name); === modified file 'sql/sql_signal.cc' --- a/sql/sql_signal.cc 2010-03-31 14:05:33 +0000 +++ b/sql/sql_signal.cc 2010-05-14 18:11:25 +0000 @@ -75,10 +75,6 @@ const LEX_STRING Diag_statement_item_nam { C_STRING_WITH_LEN("TRANSACTION_ACTIVE") } }; -Set_signal_information::Set_signal_information() -{ - clear(); -} Set_signal_information::Set_signal_information( const Set_signal_information& set) @@ -458,8 +454,20 @@ bool Signal_statement::execute(THD *thd) DBUG_ENTER("Signal_statement::execute"); + /* + WL#2110 SIGNAL specification says: + + When SIGNAL is executed, it has five effects, in the following order: + + (1) First, the diagnostics area is completely cleared. So if the + SIGNAL is in a DECLARE HANDLER then any pending errors or warnings + are gone. So is 'row count'. + + This has roots in the SQL standard specification for SIGNAL. + */ + thd->stmt_da->reset_diagnostics_area(); - thd->row_count_func= 0; + thd->set_row_count_func(0); thd->warning_info->clear_warning_info(thd->query_id); result= raise_condition(thd, &cond); === modified file 'sql/sql_update.cc' --- a/sql/sql_update.cc 2010-04-21 07:35:37 +0000 +++ b/sql/sql_update.cc 2010-05-14 05:29:47 +0000 @@ -843,9 +843,8 @@ int mysql_update(THD *thd, my_snprintf(buff, sizeof(buff), ER(ER_UPDATE_INFO), (ulong) found, (ulong) updated, (ulong) thd->warning_info->statement_warn_count()); - thd->row_count_func= - (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated; - my_ok(thd, (ulong) thd->row_count_func, id, buff); + my_ok(thd, (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated, + id, buff); DBUG_PRINT("info",("%ld records updated", (long) updated)); } thd->count_cuted_fields= CHECK_FIELD_IGNORE; /* calc cuted fields */ @@ -2150,8 +2149,7 @@ bool multi_update::send_eof() thd->first_successful_insert_id_in_prev_stmt : 0; my_snprintf(buff, sizeof(buff), ER(ER_UPDATE_INFO), (ulong) found, (ulong) updated, (ulong) thd->cuted_fields); - thd->row_count_func= - (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated; - ::my_ok(thd, (ulong) thd->row_count_func, id, buff); + ::my_ok(thd, (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated, + id, buff); DBUG_RETURN(FALSE); } === modified file 'storage/perfschema/pfs_engine_table.cc' --- a/storage/perfschema/pfs_engine_table.cc 2010-05-13 14:23:08 +0000 +++ b/storage/perfschema/pfs_engine_table.cc 2010-05-18 05:58:04 +0000 @@ -36,6 +36,7 @@ /* For show status */ #include "pfs_column_values.h" #include "pfs_instr.h" +#include "pfs_global.h" #include "sql_base.h" // close_thread_tables #include "lock.h" // MYSQL_LOCK_IGNORE_TIMEOUT @@ -701,6 +702,7 @@ bool pfs_show_status(handlerton *hton, T case 40: name= "(PFS_FILE_HANDLE).MEMORY"; size= file_handle_max * sizeof(PFS_file*); + total_memory+= size; break; case 41: name= "EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME.ROW_SIZE"; @@ -715,13 +717,41 @@ bool pfs_show_status(handlerton *hton, T size= thread_max * instr_class_per_thread * sizeof(PFS_single_stat_chain); total_memory+= size; break; + case 44: + name= "(PFS_TABLE_SHARE).ROW_SIZE"; + size= sizeof(PFS_table_share); + break; + case 45: + name= "(PFS_TABLE_SHARE).ROW_COUNT"; + size= table_share_max; + break; + case 46: + name= "(PFS_TABLE_SHARE).MEMORY"; + size= table_share_max * sizeof(PFS_table_share); + total_memory+= size; + break; + case 47: + name= "(PFS_TABLE).ROW_SIZE"; + size= sizeof(PFS_table); + break; + case 48: + name= "(PFS_TABLE).ROW_COUNT"; + size= table_max; + break; + case 49: + name= "(PFS_TABLE).MEMORY"; + size= table_max * sizeof(PFS_table); + total_memory+= size; + break; /* This case must be last, for aggregation in total_memory. */ - case 44: + case 50: name= "PERFORMANCE_SCHEMA.MEMORY"; size= total_memory; + /* This will fail if something is not advertised here */ + DBUG_ASSERT(size == pfs_allocated_memory); break; default: goto end; === modified file 'storage/perfschema/pfs_global.cc' --- a/storage/perfschema/pfs_global.cc 2010-04-19 12:26:29 +0000 +++ b/storage/perfschema/pfs_global.cc 2010-05-11 14:19:09 +0000 @@ -26,6 +26,7 @@ #include bool pfs_initialized= false; +ulonglong pfs_allocated_memory= 0; /** Memory allocation for the performance schema. @@ -38,7 +39,9 @@ void *pfs_malloc(size_t size, myf flags) DBUG_ASSERT(size > 0); void *ptr= malloc(size); - if (ptr && (flags & MY_ZEROFILL)) + if (likely(ptr != NULL)) + pfs_allocated_memory+= size; + if (likely((ptr != NULL) && (flags & MY_ZEROFILL))) memset(ptr, 0, size); return ptr; } === modified file 'storage/perfschema/pfs_global.h' --- a/storage/perfschema/pfs_global.h 2010-04-14 09:54:35 +0000 +++ b/storage/perfschema/pfs_global.h 2010-05-11 14:19:09 +0000 @@ -22,6 +22,7 @@ */ extern bool pfs_initialized; +extern ulonglong pfs_allocated_memory; void *pfs_malloc(size_t size, myf flags); #define PFS_MALLOC_ARRAY(n, T, f) \ --===============8602379007330771984== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/marc.alff@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: marc.alff@stripped # target_branch: file:///Users/malff/BZR_TREE/mysql-next-mr-bugfixing-\ # 53617/ # testament_sha1: 83039109e4a2a5c30eae0d471a27a49b9f3e4b42 # timestamp: 2010-05-17 23:58:15 -0600 # base_revision_id: marc.alff@stripped\ # h7c50ztzathdt2ej # # Begin bundle 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 ViBlP+P/4u5IpwoSEbs/2uA= --===============8602379007330771984==--