summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorAlexander Nozdrin <alik@sun.com>2010-05-20 16:35:28 +0400
committerAlexander Nozdrin <alik@sun.com>2010-05-20 16:35:28 +0400
commitdabd4a1c55cabbe73350c7c9b4c2bd6ab2db2b5c (patch)
tree2b0d3650bb46050bc0438cfd5228e52e89aa3895 /sql
parenta08c47a3ace44229e8683108bd1ce4a45471b491 (diff)
parenta18861e4adab138553da6b55a7b1d7286acbe23d (diff)
downloadmariadb-git-dabd4a1c55cabbe73350c7c9b4c2bd6ab2db2b5c.tar.gz
Manual merge from mysql-trunk.
Conflicts: - mysql-test/r/partition.result - mysql-test/r/variables_debug.result - mysql-test/t/partition.test - mysql-test/t/variables_debug.test
Diffstat (limited to 'sql')
-rwxr-xr-xsql/CMakeLists.txt3
-rw-r--r--sql/Makefile.am3
-rw-r--r--sql/ha_ndbcluster_binlog.cc6
-rw-r--r--sql/item_func.cc2
-rw-r--r--sql/log_event.cc4
-rw-r--r--sql/protocol.cc2
-rw-r--r--sql/share/Makefile.am3
-rw-r--r--sql/sql_class.cc15
-rw-r--r--sql/sql_class.h49
-rw-r--r--sql/sql_delete.cc13
-rw-r--r--sql/sql_insert.cc22
-rw-r--r--sql/sql_lex.cc79
-rw-r--r--sql/sql_lex.h26
-rw-r--r--sql/sql_parse.cc89
-rw-r--r--sql/sql_parse.h2
-rw-r--r--sql/sql_signal.cc18
-rw-r--r--sql/sql_update.cc10
17 files changed, 205 insertions, 141 deletions
diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt
index 47aa4892cbb..a0e157b7806 100755
--- a/sql/CMakeLists.txt
+++ b/sql/CMakeLists.txt
@@ -280,7 +280,8 @@ IF(WIN32 AND MYSQLD_EXECUTABLE)
ALL
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/data/mysql/user.frm
)
- INSTALL(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/data/mysql DESTINATION data)
+ INSTALL(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/data DESTINATION .
+ PATTERN "bootstrap.sql" EXCLUDE)
ELSE()
# Not windows or cross compiling, just install an empty directory
INSTALL(FILES ${DUMMY_FILE} DESTINATION data/mysql)
diff --git a/sql/Makefile.am b/sql/Makefile.am
index 93595a964eb..f57d1f3bc34 100644
--- a/sql/Makefile.am
+++ b/sql/Makefile.am
@@ -271,6 +271,3 @@ probes_libndb.o: probes_mysql.d libndb_la-ha_ndbcluster.lo
fi
endif
-
-# Don't update the files from bitkeeper
-%::SCCS/s.%
diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc
index edb6aeebb5c..d38544f9b9f 100644
--- a/sql/ha_ndbcluster_binlog.cc
+++ b/sql/ha_ndbcluster_binlog.cc
@@ -263,7 +263,6 @@ static void run_query(THD *thd, char *buf, char *end,
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 *buf, char *end,
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)
{
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 4d0dec25e64..26c802b8057 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -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();
}
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 5a1ab7cdc94..7d60328381d 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -3287,8 +3287,8 @@ int Query_log_event::do_apply_event(Relay_log_info const *rli,
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);
/*
diff --git a/sql/protocol.cc b/sql/protocol.cc
index 1903ab0c864..eeb248012ab 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -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
{
diff --git a/sql/share/Makefile.am b/sql/share/Makefile.am
index 03f9a1652b7..73f2ca13bb6 100644
--- a/sql/share/Makefile.am
+++ b/sql/share/Makefile.am
@@ -58,6 +58,3 @@ distclean-local:
# Do nothing
link_sources:
-
-# Don't update the files from bitkeeper
-%::SCCS/s.%
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 5859b6e5fd7..049975bccd9 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -543,7 +543,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;
@@ -835,7 +835,10 @@ MYSQL_ERROR* THD::raise_condition(uint sql_errno,
else
{
if (! stmt_da->is_error())
+ {
+ set_row_count_func(-1);
stmt_da->set_error_status(this, sql_errno, msg, sqlstate);
+ }
}
}
@@ -1836,11 +1839,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;
@@ -2881,11 +2879,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;
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 3a1f83fc9e5..950ef83b237 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -1999,7 +1999,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;
/*
@@ -2786,6 +2829,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);
}
@@ -2795,6 +2839,7 @@ my_ok(THD *thd, ulonglong affected_rows= 0, ulonglong id= 0,
inline void
my_eof(THD *thd)
{
+ thd->set_row_count_func(-1);
thd->stmt_da->set_eof_status(thd);
}
@@ -3456,7 +3501,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)
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 2a8503077aa..10bdb8a22a6 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -187,8 +187,8 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
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 *table_list, COND *conds,
{
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 *table_list, COND *conds,
*/
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;
}
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 2d2564a515c..d40f0dcb410 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -1005,10 +1005,10 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
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 *table_list,
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);
}
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index f44edfdf6fb..b8971811f15 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -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;
}
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index a65c4da9962..e9b5ca00953 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -1377,6 +1377,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();
+ }
};
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 33688e3bfb1..b4ad5e2c2f9 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -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 *thd)
{
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 *thd)
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_command command, THD *thd,
(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_command command, THD *thd,
*/
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"));
@@ -3199,7 +3199,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
@@ -3265,7 +3265,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;
}
/*
@@ -3311,7 +3311,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:
@@ -4314,8 +4314,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);
@@ -4702,15 +4703,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:
@@ -5747,7 +5739,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");
@@ -5777,10 +5769,7 @@ void mysql_parse(THD *thd, const char *inBuf, uint length,
{
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)
{
@@ -5795,6 +5784,7 @@ void mysql_parse(THD *thd, const char *inBuf, uint length,
{
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
@@ -5805,12 +5795,12 @@ void mysql_parse(THD *thd, const char *inBuf, uint length,
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;
@@ -5847,11 +5837,6 @@ void mysql_parse(THD *thd, const char *inBuf, uint length,
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;
}
diff --git a/sql/sql_parse.h b/sql/sql_parse.h
index 3c34b063d91..e1543a09549 100644
--- a/sql/sql_parse.h
+++ b/sql/sql_parse.h
@@ -84,7 +84,7 @@ bool is_log_table_write_query(enum enum_sql_command command);
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);
diff --git a/sql/sql_signal.cc b/sql/sql_signal.cc
index 8ae77f3645b..f340da373e8 100644
--- a/sql/sql_signal.cc
+++ b/sql/sql_signal.cc
@@ -75,10 +75,6 @@ const LEX_STRING Diag_statement_item_names[]=
{ 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);
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index a4c7d665b8a..2abd307deba 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -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 */
@@ -2160,8 +2159,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);
}