diff options
Diffstat (limited to 'sql')
-rwxr-xr-x | sql/CMakeLists.txt | 3 | ||||
-rw-r--r-- | sql/ha_ndbcluster_binlog.cc | 6 | ||||
-rw-r--r-- | sql/item_func.cc | 2 | ||||
-rw-r--r-- | sql/log_event.cc | 4 | ||||
-rw-r--r-- | sql/protocol.cc | 2 | ||||
-rw-r--r-- | sql/rpl_mi.cc | 22 | ||||
-rw-r--r-- | sql/rpl_mi.h | 1 | ||||
-rw-r--r-- | sql/slave.cc | 4 | ||||
-rw-r--r-- | sql/sql_class.cc | 15 | ||||
-rw-r--r-- | sql/sql_class.h | 49 | ||||
-rw-r--r-- | sql/sql_delete.cc | 13 | ||||
-rw-r--r-- | sql/sql_insert.cc | 22 | ||||
-rw-r--r-- | sql/sql_lex.cc | 79 | ||||
-rw-r--r-- | sql/sql_lex.h | 27 | ||||
-rw-r--r-- | sql/sql_parse.cc | 89 | ||||
-rw-r--r-- | sql/sql_parse.h | 2 | ||||
-rw-r--r-- | sql/sql_signal.cc | 18 | ||||
-rw-r--r-- | sql/sql_update.cc | 10 |
18 files changed, 221 insertions, 147 deletions
diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index 253d546d4a4..357575c5b47 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/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 4caf23232c5..d5ae1c954ff 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -3290,8 +3290,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 e036f255960..fd01e4a8885 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/rpl_mi.cc b/sql/rpl_mi.cc index 10bf752e140..34051f1e74e 100644 --- a/sql/rpl_mi.cc +++ b/sql/rpl_mi.cc @@ -143,7 +143,6 @@ int init_master_info(Master_info* mi, const char* master_info_fname, int thread_mask) { int fd,error; - char fname[FN_REFLEN+128]; DBUG_ENTER("init_master_info"); if (mi->inited) @@ -169,7 +168,8 @@ int init_master_info(Master_info* mi, const char* master_info_fname, mi->mysql=0; mi->file_id=1; - fn_format(fname, master_info_fname, mysql_data_home, "", 4+32); + fn_format(mi->info_file_name, master_info_fname, mysql_data_home, "", + MYF(MY_UNPACK_FILENAME|MY_RETURN_REAL_PATH)); /* We need a mutex while we are changing master info parameters to @@ -181,7 +181,7 @@ int init_master_info(Master_info* mi, const char* master_info_fname, /* does master.info exist ? */ - if (access(fname,F_OK)) + if (access(mi->info_file_name, F_OK)) { if (abort_if_no_master_info_file) { @@ -194,18 +194,18 @@ int init_master_info(Master_info* mi, const char* master_info_fname, */ if (fd >= 0) mysql_file_close(fd, MYF(MY_WME)); - if ((fd= mysql_file_open(key_file_master_info, - fname, O_CREAT|O_RDWR|O_BINARY, MYF(MY_WME))) < 0 ) + if ((fd= mysql_file_open(key_file_master_info, mi->info_file_name, + O_CREAT|O_RDWR|O_BINARY, MYF(MY_WME))) < 0 ) { sql_print_error("Failed to create a new master info file (\ -file '%s', errno %d)", fname, my_errno); +file '%s', errno %d)", mi->info_file_name, my_errno); goto err; } if (init_io_cache(&mi->file, fd, IO_SIZE*2, READ_CACHE, 0L,0, MYF(MY_WME))) { sql_print_error("Failed to create a cache on master info file (\ -file '%s')", fname); +file '%s')", mi->info_file_name); goto err; } @@ -220,17 +220,17 @@ file '%s')", fname); else { if ((fd= mysql_file_open(key_file_master_info, - fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0 ) + mi->info_file_name, O_RDWR|O_BINARY, MYF(MY_WME))) < 0 ) { sql_print_error("Failed to open the existing master info file (\ -file '%s', errno %d)", fname, my_errno); +file '%s', errno %d)", mi->info_file_name, my_errno); goto err; } if (init_io_cache(&mi->file, fd, IO_SIZE*2, READ_CACHE, 0L, 0, MYF(MY_WME))) { sql_print_error("Failed to create a cache on master info file (\ -file '%s')", fname); +file '%s')", mi->info_file_name); goto err; } } @@ -344,7 +344,7 @@ file '%s')", fname); if (ssl) sql_print_warning("SSL information in the master info file " "('%s') are ignored because this MySQL slave was " - "compiled without SSL support.", fname); + "compiled without SSL support.", mi->info_file_name); #endif /* HAVE_OPENSSL */ /* diff --git a/sql/rpl_mi.h b/sql/rpl_mi.h index c3734fdf59e..89bab16b63b 100644 --- a/sql/rpl_mi.h +++ b/sql/rpl_mi.h @@ -112,6 +112,7 @@ class Master_info : public Slave_reporting_capability ulonglong received_heartbeats; // counter of received heartbeat events DYNAMIC_ARRAY ignore_server_ids; ulong master_id; + char info_file_name[FN_REFLEN + 128]; }; void init_master_log_pos(Master_info* mi); int init_master_info(Master_info* mi, const char* master_info_fname, diff --git a/sql/slave.cc b/sql/slave.cc index e23763696df..2ecfd7be5b2 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1802,7 +1802,8 @@ bool show_master_info(THD* thd, Master_info* mi) FN_REFLEN)); field_list.push_back(new Item_return_int("Master_Server_Id", sizeof(ulong), MYSQL_TYPE_LONG)); - + field_list.push_back(new Item_empty_string("Master_Info_File", + sizeof(mi->info_file_name))); if (protocol->send_result_set_metadata(&field_list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) DBUG_RETURN(TRUE); @@ -1950,6 +1951,7 @@ bool show_master_info(THD* thd, Master_info* mi) } // Master_Server_id protocol->store((uint32) mi->master_id); + protocol->store(mi->info_file_name, &my_charset_bin); mysql_mutex_unlock(&mi->rli.err_lock); mysql_mutex_unlock(&mi->err_lock); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 3144192a971..789b01443f7 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -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 sql_errno, 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; } diff --git a/sql/sql_class.h b/sql/sql_class.h index ac1a10f57b9..916b79f8353 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -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; /* @@ -2826,6 +2869,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); } @@ -2835,6 +2879,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); } @@ -3496,7 +3541,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 103be4c851f..1f9d69a798e 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 6bd6a374883..1795bc272f1 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 6f7acc4a609..2ce6bdeed42 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1379,6 +1379,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. @@ -2206,8 +2208,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); @@ -2220,7 +2222,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. */ @@ -2237,8 +2239,17 @@ class Yacc_state { public: Yacc_state() - : yacc_yyss(NULL), yacc_yyvs(NULL), m_lock_type(TL_READ_DEFAULT) - {} + { + reset(); + } + + void reset() + { + yacc_yyss= NULL; + yacc_yyvs= NULL; + m_set_signal_info.clear(); + m_lock_type= TL_READ_DEFAULT; + } ~Yacc_state(); @@ -2311,6 +2322,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 c8faac7c91d..60b2ffa4179 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")); @@ -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: @@ -5734,7 +5726,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"); @@ -5764,10 +5756,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) { @@ -5782,6 +5771,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 @@ -5792,12 +5782,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; @@ -5834,11 +5824,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 412a053014f..300ca1098fb 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 */ @@ -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); } |