diff options
author | Mikael Ronström <mikael@dator9> | 2011-05-12 14:29:32 +0200 |
---|---|---|
committer | Mikael Ronström <mikael@dator9> | 2011-05-12 14:29:32 +0200 |
commit | 43c55e9a01fed3babab6e53eac2aed388f3ed2dc (patch) | |
tree | b38b221786a2d3d9fc1ff6572ad859f7aeacde27 /sql | |
parent | 385551271556a8a4f1c9b669a91cb08adf33a89f (diff) | |
parent | 30265fd178745430101cfe6e15e02fa3dbc28797 (diff) | |
download | mariadb-git-43c55e9a01fed3babab6e53eac2aed388f3ed2dc.tar.gz |
merge
Diffstat (limited to 'sql')
-rw-r--r-- | sql/event_db_repository.cc | 22 | ||||
-rw-r--r-- | sql/field.cc | 6 | ||||
-rw-r--r-- | sql/handler.h | 14 | ||||
-rw-r--r-- | sql/item.cc | 93 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 4 | ||||
-rw-r--r-- | sql/item_func.cc | 2 | ||||
-rw-r--r-- | sql/item_row.cc | 2 | ||||
-rw-r--r-- | sql/item_strfunc.cc | 2 | ||||
-rw-r--r-- | sql/item_timefunc.cc | 13 | ||||
-rw-r--r-- | sql/my_decimal.cc | 11 | ||||
-rw-r--r-- | sql/my_decimal.h | 3 | ||||
-rw-r--r-- | sql/rpl_handler.h | 3 | ||||
-rw-r--r-- | sql/slave.cc | 6 | ||||
-rw-r--r-- | sql/sql_acl.cc | 178 | ||||
-rw-r--r-- | sql/sql_base.cc | 15 | ||||
-rw-r--r-- | sql/sql_class.h | 18 | ||||
-rw-r--r-- | sql/sql_load.cc | 5 | ||||
-rw-r--r-- | sql/sql_parse.cc | 6 | ||||
-rw-r--r-- | sql/sql_partition.cc | 2 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 20 |
20 files changed, 342 insertions, 83 deletions
diff --git a/sql/event_db_repository.cc b/sql/event_db_repository.cc index 3a25324db52..75d1c8ef8e8 100644 --- a/sql/event_db_repository.cc +++ b/sql/event_db_repository.cc @@ -534,6 +534,13 @@ Event_db_repository::fill_schema_events(THD *thd, TABLE_LIST *i_s_table, if (open_system_tables_for_read(thd, &event_table, &open_tables_backup)) DBUG_RETURN(TRUE); + if (table_intact.check(event_table.table, &event_table_def)) + { + close_system_tables(thd, &open_tables_backup); + my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0)); + DBUG_RETURN(TRUE); + } + /* 1. SELECT I_S => use table scan. I_S.EVENTS does not guarantee order thus we won't order it. OTOH, SHOW EVENTS will be @@ -591,6 +598,14 @@ Event_db_repository::open_event_table(THD *thd, enum thr_lock_type lock_type, *table= tables.table; tables.table->use_all_columns(); + + if (table_intact.check(*table, &event_table_def)) + { + close_thread_tables(thd); + my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0)); + DBUG_RETURN(TRUE); + } + DBUG_RETURN(FALSE); } @@ -1035,6 +1050,13 @@ Event_db_repository::load_named_event(THD *thd, LEX_STRING dbname, */ if (!(ret= open_system_tables_for_read(thd, &event_table, &open_tables_backup))) { + if (table_intact.check(event_table.table, &event_table_def)) + { + close_system_tables(thd, &open_tables_backup); + my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0)); + DBUG_RETURN(TRUE); + } + if ((ret= find_named_event(dbname, name, event_table.table))) my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), name.str); else if ((ret= etn->load_from_row(thd, event_table.table))) diff --git a/sql/field.cc b/sql/field.cc index 7ffc399718c..d273f26306d 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -2608,7 +2608,7 @@ bool Field_new_decimal::store_value(const my_decimal *decimal_value) DBUG_ENTER("Field_new_decimal::store_value"); #ifndef DBUG_OFF { - char dbug_buff[DECIMAL_MAX_STR_LENGTH+1]; + char dbug_buff[DECIMAL_MAX_STR_LENGTH+2]; DBUG_PRINT("enter", ("value: %s", dbug_decimal_as_string(dbug_buff, decimal_value))); } #endif @@ -2623,7 +2623,7 @@ bool Field_new_decimal::store_value(const my_decimal *decimal_value) } #ifndef DBUG_OFF { - char dbug_buff[DECIMAL_MAX_STR_LENGTH+1]; + char dbug_buff[DECIMAL_MAX_STR_LENGTH+2]; DBUG_PRINT("info", ("saving with precision %d scale: %d value %s", (int)precision, (int)dec, dbug_decimal_as_string(dbug_buff, decimal_value))); @@ -2692,7 +2692,7 @@ int Field_new_decimal::store(const char *from, uint length, } #ifndef DBUG_OFF - char dbug_buff[DECIMAL_MAX_STR_LENGTH+1]; + char dbug_buff[DECIMAL_MAX_STR_LENGTH+2]; DBUG_PRINT("enter", ("value: %s", dbug_decimal_as_string(dbug_buff, &decimal_value))); #endif diff --git a/sql/handler.h b/sql/handler.h index 1250388f459..fbc52170297 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -3,18 +3,20 @@ /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + 02110-1301 USA */ /* Definitions for parameters to do with handler-routines */ @@ -60,7 +62,7 @@ a table with rnd_next() - We will see all rows (including deleted ones) - Row positions are 'table->s->db_record_offset' apart - If this flag is not set, filesort will do a postion() call for each matched + If this flag is not set, filesort will do a position() call for each matched row to be able to find the row later. */ #define HA_REC_NOT_IN_SEQ (1 << 3) diff --git a/sql/item.cc b/sql/item.cc index af3917c09c1..2c0da80b43b 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -581,7 +581,7 @@ void Item::rename(char *new_name) Item* Item::transform(Item_transformer transformer, uchar *arg) { - DBUG_ASSERT(!current_thd->is_stmt_prepare()); + DBUG_ASSERT(!current_thd->stmt_arena->is_stmt_prepare()); return (this->*transformer)(arg); } @@ -1781,14 +1781,17 @@ bool agg_item_set_converter(DTCollation &coll, const char *fname, } THD *thd= current_thd; - Query_arena *arena, backup; bool res= FALSE; uint i; + /* In case we're in statement prepare, create conversion item in its memory: it will be reused on each execute. */ - arena= thd->activate_stmt_arena_if_needed(&backup); + Query_arena backup; + Query_arena *arena= thd->stmt_arena->is_stmt_prepare() ? + thd->activate_stmt_arena_if_needed(&backup) : + NULL; for (i= 0, arg= args; i < nargs; i++, arg+= item_sep) { @@ -1845,7 +1848,7 @@ bool agg_item_set_converter(DTCollation &coll, const char *fname, been created in prepare. In this case register the change for rollback. */ - if (thd->is_stmt_prepare()) + if (thd->stmt_arena->is_stmt_prepare()) *arg= conv; else thd->change_item_tree(arg, conv); @@ -2008,6 +2011,61 @@ Item_field::Item_field(THD *thd, Item_field *item) collation.set(DERIVATION_IMPLICIT); } + +/** + Calculate the max column length not taking into account the + limitations over integer types. + + When storing data into fields the server currently just ignores the + limits specified on integer types, e.g. 1234 can safely be stored in + an int(2) and will not cause an error. + Thus when creating temporary tables and doing transformations + we must adjust the maximum field length to reflect this fact. + We take the un-restricted maximum length and adjust it similarly to + how the declared length is adjusted wrt unsignedness etc. + TODO: this all needs to go when we disable storing 1234 in int(2). + + @param field_par Original field the use to calculate the lengths + @param max_length Item's calculated explicit max length + @return The adjusted max length +*/ + +inline static uint32 +adjust_max_effective_column_length(Field *field_par, uint32 max_length) +{ + uint32 new_max_length= field_par->max_display_length(); + uint32 sign_length= (field_par->flags & UNSIGNED_FLAG) ? 0 : 1; + + switch (field_par->type()) + { + case MYSQL_TYPE_INT24: + /* + Compensate for MAX_MEDIUMINT_WIDTH being 1 too long (8) + compared to the actual number of digits that can fit into + the column. + */ + new_max_length+= 1; + /* fall through */ + case MYSQL_TYPE_LONG: + case MYSQL_TYPE_TINY: + case MYSQL_TYPE_SHORT: + + /* Take out the sign and add a conditional sign */ + new_max_length= new_max_length - 1 + sign_length; + break; + + /* BINGINT is always 20 no matter the sign */ + case MYSQL_TYPE_LONGLONG: + /* make gcc happy */ + default: + break; + } + + /* Adjust only if the actual precision based one is bigger than specified */ + return new_max_length > max_length ? new_max_length : max_length; +} + + void Item_field::set_field(Field *field_par) { field=result_field=field_par; // for easy coding with fields @@ -2021,6 +2079,9 @@ void Item_field::set_field(Field *field_par) collation.set(field_par->charset(), field_par->derivation(), field_par->repertoire()); fix_char_length(field_par->char_length()); + + max_length= adjust_max_effective_column_length(field_par, max_length); + fixed= 1; if (field->table->s->tmp_table == SYSTEM_TMP_TABLE) any_privileges= 0; @@ -6965,7 +7026,7 @@ int Item_default_value::save_in_field(Field *field_arg, bool no_conversions) Item *Item_default_value::transform(Item_transformer transformer, uchar *args) { - DBUG_ASSERT(!current_thd->is_stmt_prepare()); + DBUG_ASSERT(!current_thd->stmt_arena->is_stmt_prepare()); /* If the value of arg is NULL, then this object represents a constant, @@ -7131,8 +7192,26 @@ bool Item_trigger_field::set_value(THD *thd, sp_rcontext * /*ctx*/, Item **it) { Item *item= sp_prepare_func_item(thd, it); - return (!item || (!fixed && fix_fields(thd, 0)) || - (item->save_in_field(field, 0) < 0)); + if (!item) + return true; + + if (!fixed) + { + if (fix_fields(thd, NULL)) + return true; + } + + // NOTE: field->table->copy_blobs should be false here, but let's + // remember the value at runtime to avoid subtle bugs. + bool copy_blobs_saved= field->table->copy_blobs; + + field->table->copy_blobs= true; + + int err_code= item->save_in_field(field, 0); + + field->table->copy_blobs= copy_blobs_saved; + + return err_code < 0; } diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index cf5da5313d9..e0057d1550b 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -4345,7 +4345,7 @@ bool Item_cond::walk(Item_processor processor, bool walk_subquery, uchar *arg) Item *Item_cond::transform(Item_transformer transformer, uchar *arg) { - DBUG_ASSERT(!current_thd->is_stmt_prepare()); + DBUG_ASSERT(!current_thd->stmt_arena->is_stmt_prepare()); List_iterator<Item> li(list); Item *item; @@ -5718,7 +5718,7 @@ bool Item_equal::walk(Item_processor processor, bool walk_subquery, uchar *arg) Item *Item_equal::transform(Item_transformer transformer, uchar *arg) { - DBUG_ASSERT(!current_thd->is_stmt_prepare()); + DBUG_ASSERT(!current_thd->stmt_arena->is_stmt_prepare()); List_iterator<Item_field> it(fields); Item *item; diff --git a/sql/item_func.cc b/sql/item_func.cc index 9035d644962..a7e9ed43cb4 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -295,7 +295,7 @@ void Item_func::traverse_cond(Cond_traverser traverser, Item *Item_func::transform(Item_transformer transformer, uchar *argument) { - DBUG_ASSERT(!current_thd->is_stmt_prepare()); + DBUG_ASSERT(!current_thd->stmt_arena->is_stmt_prepare()); if (arg_count) { diff --git a/sql/item_row.cc b/sql/item_row.cc index 94515640625..0f5d6f27823 100644 --- a/sql/item_row.cc +++ b/sql/item_row.cc @@ -170,7 +170,7 @@ bool Item_row::walk(Item_processor processor, bool walk_subquery, uchar *arg) Item *Item_row::transform(Item_transformer transformer, uchar *arg) { - DBUG_ASSERT(!current_thd->is_stmt_prepare()); + DBUG_ASSERT(!current_thd->stmt_arena->is_stmt_prepare()); for (uint i= 0; i < arg_count; i++) { diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index e5c47c110f4..e1a4fcc8def 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -2536,7 +2536,7 @@ String *Item_func_make_set::val_str(String *str) Item *Item_func_make_set::transform(Item_transformer transformer, uchar *arg) { - DBUG_ASSERT(!current_thd->is_stmt_prepare()); + DBUG_ASSERT(!current_thd->stmt_arena->is_stmt_prepare()); Item *new_item= item->transform(transformer, arg); if (!new_item) diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 68e75a262dc..0952a5448e4 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -2524,6 +2524,19 @@ String *Item_char_typecast::val_str(String *str) String *res; uint32 length; + if (cast_length >= 0 && + ((unsigned) cast_length) > current_thd->variables.max_allowed_packet) + { + push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_WARN_ALLOWED_PACKET_OVERFLOWED, + ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), + cast_cs == &my_charset_bin ? + "cast_as_binary" : func_name(), + current_thd->variables.max_allowed_packet); + null_value= 1; + return 0; + } + if (!charset_conversion) { if (!(res= args[0]->val_str(str))) diff --git a/sql/my_decimal.cc b/sql/my_decimal.cc index a5b60739b26..3b5fa81eab9 100644 --- a/sql/my_decimal.cc +++ b/sql/my_decimal.cc @@ -99,10 +99,11 @@ int my_decimal2string(uint mask, const my_decimal *d, UNSIGNED. Hence the buffer for a ZEROFILLed value is the length the user requested, plus one for a possible decimal point, plus one if the user only wanted decimal places, but we force a leading - zero on them. Because the type is implicitly UNSIGNED, we do not - need to reserve a character for the sign. For all other cases, - fixed_prec will be 0, and my_decimal_string_length() will be called - instead to calculate the required size of the buffer. + zero on them, plus one for the '\0' terminator. Because the type + is implicitly UNSIGNED, we do not need to reserve a character for + the sign. For all other cases, fixed_prec will be 0, and + my_decimal_string_length() will be called instead to calculate the + required size of the buffer. */ int length= (fixed_prec ? (fixed_prec + ((fixed_prec == fixed_dec) ? 1 : 0) + 1) @@ -332,7 +333,7 @@ print_decimal_buff(const my_decimal *dec, const uchar* ptr, int length) const char *dbug_decimal_as_string(char *buff, const my_decimal *val) { - int length= DECIMAL_MAX_STR_LENGTH; + int length= DECIMAL_MAX_STR_LENGTH + 1; /* minimum size for buff */ if (!val) return "NULL"; (void)decimal2string((decimal_t*) val, buff, &length, 0,0,0); diff --git a/sql/my_decimal.h b/sql/my_decimal.h index f3fd39f5721..6ac9d25b87d 100644 --- a/sql/my_decimal.h +++ b/sql/my_decimal.h @@ -62,7 +62,7 @@ typedef struct st_mysql_time MYSQL_TIME; /** maximum length of string representation (number of maximum decimal - digits + 1 position for sign + 1 position for decimal point) + digits + 1 position for sign + 1 position for decimal point, no terminator) */ #define DECIMAL_MAX_STR_LENGTH (DECIMAL_MAX_POSSIBLE_PRECISION + 2) @@ -243,6 +243,7 @@ inline uint32 my_decimal_precision_to_length(uint precision, uint8 scale, inline int my_decimal_string_length(const my_decimal *d) { + /* length of string representation including terminating '\0' */ return decimal_string_size(d); } diff --git a/sql/rpl_handler.h b/sql/rpl_handler.h index bf207e53e2d..9a181250efc 100644 --- a/sql/rpl_handler.h +++ b/sql/rpl_handler.h @@ -73,7 +73,10 @@ public: while (info && info->observer != observer) info= iter++; if (info) + { iter.remove(); + delete info; + } else ret= TRUE; unlock(); diff --git a/sql/slave.cc b/sql/slave.cc index c676c89b369..223ea21851a 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -113,7 +113,7 @@ static const char *reconnect_messages[SLAVE_RECON_ACT_MAX][SLAVE_RECON_MSG_MAX]= registration on master", "Reconnecting after a failed registration on master", "failed registering on master, reconnecting to try again, \ -log '%s' at postion %s", +log '%s' at position %s", "COM_REGISTER_SLAVE", "Slave I/O thread killed during or after reconnect" }, @@ -121,7 +121,7 @@ log '%s' at postion %s", "Waiting to reconnect after a failed binlog dump request", "Slave I/O thread killed while retrying master dump", "Reconnecting after a failed binlog dump request", - "failed dump request, reconnecting to try again, log '%s' at postion %s", + "failed dump request, reconnecting to try again, log '%s' at position %s", "COM_BINLOG_DUMP", "Slave I/O thread killed during or after reconnect" }, @@ -130,7 +130,7 @@ log '%s' at postion %s", "Slave I/O thread killed while waiting to reconnect after a failed read", "Reconnecting after a failed master event read", "Slave I/O thread: Failed reading log event, reconnecting to retry, \ -log '%s' at postion %s", +log '%s' at position %s", "", "Slave I/O thread killed during or after a reconnect done to recover from \ failed read" diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index a269d5a1eef..18758130767 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -8399,6 +8399,94 @@ static bool parse_com_change_user_packet(MPVIO_EXT *mpvio, uint packet_length) DBUG_RETURN (0); } +#ifndef EMBEDDED_LIBRARY +/** + Get a null character terminated string from a user-supplied buffer. + + @param buffer[in, out] Pointer to the buffer to be scanned. + @param max_bytes_available[in, out] Limit the bytes to scan. + @param string_length[out] The number of characters scanned not including + the null character. + + @remark The string_length does not include the terminating null character. + However, after the call, the buffer is increased by string_length+1 + bytes, beyond the null character if there still available bytes to + scan. + + @return pointer to beginning of the string scanned. + @retval NULL The buffer content is malformed +*/ + +static +char *get_null_terminated_string(char **buffer, + size_t *max_bytes_available, + size_t *string_length) +{ + char *str= (char *)memchr(*buffer, '\0', *max_bytes_available); + + if (str == NULL) + return NULL; + + *string_length= (size_t)(str - *buffer); + *max_bytes_available-= *string_length + 1; + str= *buffer; + *buffer += *string_length + 1; + + return str; +} + +/** + Get a length encoded string from a user-supplied buffer. + + @param buffer[in, out] The buffer to scan; updates position after scan. + @param max_bytes_available[in, out] Limit the number of bytes to scan + @param string_length[out] Number of characters scanned + + @remark In case the length is zero, then the total size of the string is + considered to be 1 byte; the size byte. + + @return pointer to first byte after the header in buffer. + @retval NULL The buffer content is malformed +*/ + +static +char *get_length_encoded_string(char **buffer, + size_t *max_bytes_available, + size_t *string_length) +{ + if (*max_bytes_available == 0) + return NULL; + + /* Do double cast to prevent overflow from signed / unsigned conversion */ + size_t str_len= (size_t)(unsigned char)**buffer; + + /* + If the length encoded string has the length 0 + the total size of the string is only one byte long (the size byte) + */ + if (str_len == 0) + { + ++*buffer; + *string_length= 0; + /* + Return a pointer to the 0 character so the return value will be + an empty string. + */ + return *buffer-1; + } + + if (str_len >= *max_bytes_available) + return NULL; + + char *str= *buffer+1; + *string_length= str_len; + *max_bytes_available-= *string_length + 1; + *buffer+= *string_length + 1; + return str; +} +#endif + + /* the packet format is described in send_client_reply_packet() */ static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio, uchar **buff, ulong pkt_len) @@ -8463,50 +8551,76 @@ static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio, } #endif - if (end >= (char*) net->read_pos + pkt_len + 2) + if (end > (char *)net->read_pos + pkt_len) return packet_error; if ((mpvio->client_capabilities & CLIENT_TRANSACTIONS) && opt_using_transactions) net->return_status= mpvio->server_status; + + /* + In order to safely scan a head for '\0' string terminators + we must keep track of how many bytes remain in the allocated + buffer or we might read past the end of the buffer. + */ + size_t bytes_remaining_in_packet= pkt_len - (end - (char *)net->read_pos); - char *user= end; - char *passwd= strend(user) + 1; - uint user_len= passwd - user - 1, db_len; - char *db= passwd; - char db_buff[NAME_LEN + 1]; // buffer to store db in utf8 - char user_buff[USERNAME_LENGTH + 1]; // buffer to store user in utf8 - uint dummy_errors; + size_t user_len; + char *user= get_null_terminated_string(&end, &bytes_remaining_in_packet, + &user_len); + if (user == NULL) + return packet_error; /* - Old clients send null-terminated string as password; new clients send + Old clients send a null-terminated string as password; new clients send the size (1 byte) + string (not null-terminated). Hence in case of empty password both send '\0'. - - This strlen() can't be easily deleted without changing protocol. - - Cast *passwd to an unsigned char, so that it doesn't extend the sign for - *passwd > 127 and become 2**32-127+ after casting to uint. */ - uint passwd_len= mpvio->client_capabilities & CLIENT_SECURE_CONNECTION ? - (uchar) (*passwd++) : strlen(passwd); - - if (mpvio->client_capabilities & CLIENT_CONNECT_WITH_DB) + size_t passwd_len= 0; + char *passwd= NULL; + + if (mpvio->client_capabilities & CLIENT_SECURE_CONNECTION) { - db= db + passwd_len + 1; - /* strlen() can't be easily deleted without changing protocol */ - db_len= strlen(db); + /* + 4.1+ password. First byte is password length. + */ + passwd= get_length_encoded_string(&end, &bytes_remaining_in_packet, + &passwd_len); } else { - db= 0; - db_len= 0; + /* + Old passwords are zero terminated strings. + */ + passwd= get_null_terminated_string(&end, &bytes_remaining_in_packet, + &passwd_len); } - if (passwd + passwd_len + db_len > (char *) net->read_pos + pkt_len) + if (passwd == NULL) return packet_error; - char *client_plugin= passwd + passwd_len + (db ? db_len + 1 : 0); + size_t db_len= 0; + char *db= NULL; + + if (mpvio->client_capabilities & CLIENT_CONNECT_WITH_DB) + { + db= get_null_terminated_string(&end, &bytes_remaining_in_packet, + &db_len); + if (db == NULL) + return packet_error; + } + + size_t client_plugin_len= 0; + char *client_plugin= get_null_terminated_string(&end, + &bytes_remaining_in_packet, + &client_plugin_len); + if (client_plugin == NULL) + client_plugin= &empty_c_string[0]; + + char db_buff[NAME_LEN + 1]; // buffer to store db in utf8 + char user_buff[USERNAME_LENGTH + 1]; // buffer to store user in utf8 + uint dummy_errors; + /* Since 4.1 all database names are stored in utf8 */ if (db) @@ -8552,18 +8666,18 @@ static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio, if (find_mpvio_user(mpvio)) return packet_error; - if (mpvio->client_capabilities & CLIENT_PLUGIN_AUTH) - { - if ((client_plugin + strlen(client_plugin)) > - (char *) net->read_pos + pkt_len) - return packet_error; - } - else + if (!(mpvio->client_capabilities & CLIENT_PLUGIN_AUTH)) { + /* + An old client is connecting + */ if (mpvio->client_capabilities & CLIENT_SECURE_CONNECTION) client_plugin= native_password_plugin_name.str; else { + /* + A really old client is connecting + */ client_plugin= old_password_plugin_name.str; /* For a passwordless accounts we use native_password_plugin. diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 628e3b49719..f9d85b1e024 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -7602,9 +7602,10 @@ static bool setup_natural_join_row_types(THD *thd, List<TABLE_LIST> *from_clause, Name_resolution_context *context) { + DBUG_ENTER("setup_natural_join_row_types"); thd->where= "from clause"; if (from_clause->elements == 0) - return FALSE; /* We come here in the case of UNIONs. */ + DBUG_RETURN(false); /* We come here in the case of UNIONs. */ List_iterator_fast<TABLE_LIST> table_ref_it(*from_clause); TABLE_LIST *table_ref; /* Current table reference. */ @@ -7612,10 +7613,6 @@ static bool setup_natural_join_row_types(THD *thd, TABLE_LIST *left_neighbor; /* Table reference to the right of the current. */ TABLE_LIST *right_neighbor= NULL; - bool save_first_natural_join_processing= - context->select_lex->first_natural_join_processing; - - context->select_lex->first_natural_join_processing= FALSE; /* Note that tables in the list are in reversed order */ for (left_neighbor= table_ref_it++; left_neighbor ; ) @@ -7627,12 +7624,11 @@ static bool setup_natural_join_row_types(THD *thd, 1) for stored procedures, 2) for multitable update after lock failure and table reopening. */ - if (save_first_natural_join_processing) + if (context->select_lex->first_natural_join_processing) { - context->select_lex->first_natural_join_processing= FALSE; if (store_top_level_join_columns(thd, table_ref, left_neighbor, right_neighbor)) - return TRUE; + DBUG_RETURN(true); if (left_neighbor) { TABLE_LIST *first_leaf_on_the_right; @@ -7652,8 +7648,9 @@ static bool setup_natural_join_row_types(THD *thd, DBUG_ASSERT(right_neighbor); context->first_name_resolution_table= right_neighbor->first_leaf_for_name_resolution(); + context->select_lex->first_natural_join_processing= false; - return FALSE; + DBUG_RETURN (false); } diff --git a/sql/sql_class.h b/sql/sql_class.h index 060f2ef77f5..71b1a7d4c1c 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -655,15 +655,10 @@ public: virtual ~Query_arena() {}; inline bool is_stmt_prepare() const { return state == STMT_INITIALIZED; } - inline bool is_first_sp_execute() const - { return state == STMT_INITIALIZED_FOR_SP; } inline bool is_stmt_prepare_or_first_sp_execute() const { return (int)state < (int)STMT_PREPARED; } inline bool is_stmt_prepare_or_first_stmt_execute() const { return (int)state <= (int)STMT_PREPARED; } - inline bool is_first_stmt_execute() const { return state == STMT_PREPARED; } - inline bool is_stmt_execute() const - { return state == STMT_PREPARED || state == STMT_EXECUTED; } inline bool is_conventional() const { return state == STMT_CONVENTIONAL_EXECUTION; } @@ -1434,6 +1429,19 @@ extern "C" void my_message_sql(uint error, const char *str, myf MyFlags); class THD :public Statement, public Open_tables_state { +private: + inline bool is_stmt_prepare() const + { DBUG_ASSERT(0); return Statement::is_stmt_prepare(); } + + inline bool is_stmt_prepare_or_first_sp_execute() const + { DBUG_ASSERT(0); return Statement::is_stmt_prepare_or_first_sp_execute(); } + + inline bool is_stmt_prepare_or_first_stmt_execute() const + { DBUG_ASSERT(0); return Statement::is_stmt_prepare_or_first_stmt_execute(); } + + inline bool is_conventional() const + { DBUG_ASSERT(0); return Statement::is_conventional(); } + public: MDL_context mdl_context; diff --git a/sql/sql_load.cc b/sql/sql_load.cc index ae708178097..35c26f9bb89 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2010 Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2011 Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -743,8 +743,7 @@ static bool write_execute_load_query_log_event(THD *thd, sql_exchange* ex, pfields.append("`"); pfields.append(item->name); pfields.append("`"); - pfields.append("="); - val->print(&pfields, QT_ORDINARY); + pfields.append(val->name); } } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index d9d99de2911..24f7fdb8e61 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -4434,7 +4434,11 @@ static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables) return 1; /* purecov: inspected */ thd->send_explain_fields(result); res= mysql_explain_union(thd, &thd->lex->unit, result); - if (lex->describe & DESCRIBE_EXTENDED) + /* + The code which prints the extended description is not robust + against malformed queries, so skip it if we have an error. + */ + if (!res && (lex->describe & DESCRIBE_EXTENDED)) { char buff[1024]; String str(buff,(uint32) sizeof(buff), system_charset_info); diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 5c2c0bb95d6..776ce01cc54 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -3979,7 +3979,7 @@ void get_partition_set(const TABLE *table, uchar *buf, const uint index, part_spec->start_part= 0; part_spec->end_part= num_parts - 1; if ((index < MAX_KEY) && - key_spec->flag == (uint)HA_READ_KEY_EXACT && + key_spec && key_spec->flag == (uint)HA_READ_KEY_EXACT && part_info->some_fields_in_PF.is_set(index)) { key_info= table->key_info+index; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 13a1b8029f2..5ab1a648d09 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2010 Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2011 Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -11574,7 +11574,23 @@ field_or_var: opt_load_data_set_spec: /* empty */ {} - | SET insert_update_list {} + | SET load_data_set_list {} + ; + +load_data_set_list: + load_data_set_list ',' load_data_set_elem + | load_data_set_elem + ; + +load_data_set_elem: + simple_ident_nospvar equal remember_name expr_or_default remember_end + { + LEX *lex= Lex; + if (lex->update_list.push_back($1) || + lex->value_list.push_back($4)) + MYSQL_YYABORT; + $4->set_name($3, (uint) ($5 - $3), YYTHD->charset()); + } ; /* Common definitions */ |