diff options
author | Michael Widenius <monty@askmonty.org> | 2013-06-18 02:01:34 +0300 |
---|---|---|
committer | Michael Widenius <monty@askmonty.org> | 2013-06-18 02:01:34 +0300 |
commit | 2534521f9a7d66b48cb9ca9402e82a0c58b156d8 (patch) | |
tree | 920207a20892d748bd6b04a6699f07a5f3f1fae5 | |
parent | 0b7f8ed9738546f57d9159b52894e5abc99086fc (diff) | |
download | mariadb-git-2534521f9a7d66b48cb9ca9402e82a0c58b156d8.tar.gz |
Fixed some merge issues:
- temporary tables now works
- mysql-system_tables updated to not use temporary tables
- PASSWORD() function fixed
- Support for STATS_AUTO_RECALC, STATS_PERSISTENT and STATS_SAMPLE_PAGES table options
-rwxr-xr-x | mysql-test/mysql-test-run.pl | 2 | ||||
-rw-r--r-- | scripts/mysql_system_tables.sql | 7 | ||||
-rw-r--r-- | scripts/mysql_system_tables_data.sql | 8 | ||||
-rw-r--r-- | sql/item_strfunc.cc | 125 | ||||
-rw-r--r-- | sql/item_strfunc.h | 17 | ||||
-rw-r--r-- | sql/lex.h | 3 | ||||
-rw-r--r-- | sql/lock.cc | 1 | ||||
-rw-r--r-- | sql/log_event.cc | 3 | ||||
-rw-r--r-- | sql/mysqld.cc | 2 | ||||
-rw-r--r-- | sql/sp_head.cc | 3 | ||||
-rw-r--r-- | sql/sql_acl.cc | 20 | ||||
-rw-r--r-- | sql/sql_acl.h | 10 | ||||
-rw-r--r-- | sql/sql_admin.cc | 12 | ||||
-rw-r--r-- | sql/sql_base.cc | 23 | ||||
-rw-r--r-- | sql/sql_handler.cc | 3 | ||||
-rw-r--r-- | sql/sql_lex.cc | 1 | ||||
-rw-r--r-- | sql/sql_lex.h | 2 | ||||
-rw-r--r-- | sql/sql_parse.cc | 72 | ||||
-rw-r--r-- | sql/sql_prepare.cc | 31 | ||||
-rw-r--r-- | sql/sql_show.cc | 48 | ||||
-rw-r--r-- | sql/sql_table.cc | 35 | ||||
-rw-r--r-- | sql/sql_update.cc | 2 | ||||
-rw-r--r-- | sql/sql_view.cc | 3 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 102 |
24 files changed, 473 insertions, 62 deletions
diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 46f2215ffb8..ea22f9577e9 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -552,7 +552,7 @@ sub main { } } - if ( not defined @$completed ) { + if ( not @$completed ) { mtr_error("Test suite aborted"); } diff --git a/scripts/mysql_system_tables.sql b/scripts/mysql_system_tables.sql index d0535dce584..6ed9e22f748 100644 --- a/scripts/mysql_system_tables.sql +++ b/scripts/mysql_system_tables.sql @@ -79,10 +79,10 @@ CREATE TABLE IF NOT EXISTS proc (db char(64) collate utf8_bin DEFAULT '' NOT NUL CREATE TABLE IF NOT EXISTS procs_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Routine_name char(64) COLLATE utf8_general_ci DEFAULT '' NOT NULL, Routine_type enum('FUNCTION','PROCEDURE') NOT NULL, Grantor char(77) DEFAULT '' NOT NULL, Proc_priv set('Execute','Alter Routine','Grant') COLLATE utf8_general_ci DEFAULT '' NOT NULL, Timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (Host,Db,User,Routine_name,Routine_type), KEY Grantor (Grantor) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Procedure privileges'; --- Create general_log if CSV is enabled. -- Create general_log if CSV is enabled. -SET @have_csv = (SELECT support FROM information_schema.engines WHERE engine = 'CSV'); +SET @have_csv = 'NO'; +SET @have_csv = (SELECT @@have_csv); SET @str = IF (@have_csv = 'YES', 'CREATE TABLE IF NOT EXISTS general_log (event_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, user_host MEDIUMTEXT NOT NULL, thread_id BIGINT(21) UNSIGNED NOT NULL, server_id INTEGER UNSIGNED NOT NULL, command_type VARCHAR(64) NOT NULL, argument MEDIUMTEXT NOT NULL) engine=CSV CHARACTER SET utf8 comment="General log"', 'SET @dummy = 0'); PREPARE stmt FROM @str; @@ -130,7 +130,8 @@ CREATE TABLE IF NOT EXISTS innodb_index_stats ( SET SESSION sql_mode=@sql_mode_orig; -set @have_innodb= (select count(engine) from information_schema.engines where engine='INNODB' and support != 'NO'); +SET @have_innodb = 'NO'; +SET @have_innodb = (SELECT @@have_innodb); SET @cmd="CREATE TABLE IF NOT EXISTS slave_relay_log_info ( Number_of_lines INTEGER UNSIGNED NOT NULL COMMENT 'Number of lines in the file or rows in the table. Used to version table definitions.', diff --git a/scripts/mysql_system_tables_data.sql b/scripts/mysql_system_tables_data.sql index 878555e9458..243d4d8d444 100644 --- a/scripts/mysql_system_tables_data.sql +++ b/scripts/mysql_system_tables_data.sql @@ -37,10 +37,10 @@ DROP TABLE tmp_db; -- from local machine if "users" table didn't exist before CREATE TEMPORARY TABLE tmp_user LIKE user; set @current_hostname= @@hostname; -INSERT INTO tmp_user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'',''); -REPLACE INTO tmp_user SELECT @current_hostname,'root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','' FROM dual WHERE LOWER( @current_hostname) != 'localhost'; -REPLACE INTO tmp_user VALUES ('127.0.0.1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'',''); -REPLACE INTO tmp_user VALUES ('::1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'',''); +INSERT INTO tmp_user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','',''); +REPLACE INTO tmp_user SELECT @current_hostname,'root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','' FROM dual WHERE LOWER( @current_hostname) != 'localhost'; +REPLACE INTO tmp_user VALUES ('127.0.0.1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','',''); +REPLACE INTO tmp_user VALUES ('::1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','',''); INSERT INTO tmp_user (host,user) VALUES ('localhost',''); INSERT INTO tmp_user (host,user) SELECT @current_hostname,'' FROM dual WHERE LOWER(@current_hostname ) != 'localhost'; INSERT INTO user SELECT * FROM tmp_user WHERE @had_user_table=0; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 9b88e45be0e..a8287d5fe43 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1808,28 +1808,133 @@ void Item_func_trim::print(String *str, enum_query_type query_type) /* Item_func_password */ +/** + Helper function for calculating a new password. Used in + Item_func_password::fix_length_and_dec() for const parameters and in + Item_func_password::val_str_ascii() for non-const parameters. + @param str The plain text password which should be digested + @param buffer a pointer to the buffer where the digest will be stored. + + @note The buffer must be of at least CRYPT_MAX_PASSWORD_SIZE size. + + @return Size of the password. +*/ + +static int calculate_password(String *str, char *buffer) +{ + DBUG_ASSERT(str); + if (str->length() == 0) // PASSWORD('') returns '' + return 0; + + int buffer_len= 0; + THD *thd= current_thd; + int old_passwords= 0; + if (thd) + old_passwords= thd->variables.old_passwords; + +#if defined(HAVE_OPENSSL) + if (old_passwords == 2) + { + my_make_scrambled_password(buffer, str->ptr(), + str->length()); + buffer_len= (int) strlen(buffer) + 1; + } + else +#endif + if (old_passwords == 0) + { + my_make_scrambled_password_sha1(buffer, str->ptr(), + str->length()); + buffer_len= SCRAMBLED_PASSWORD_CHAR_LENGTH; + } + else + if (old_passwords == 1) + { + my_make_scrambled_password_323(buffer, str->ptr(), + str->length()); + buffer_len= SCRAMBLED_PASSWORD_CHAR_LENGTH_323; + } + return buffer_len; +} + +/* Item_func_password */ +void Item_func_password::fix_length_and_dec() +{ + maybe_null= false; // PASSWORD() never returns NULL + + if (args[0]->const_item()) + { + String str; + String *res= args[0]->val_str(&str); + if (!args[0]->null_value) + { + m_hashed_password_buffer_len= + calculate_password(res, m_hashed_password_buffer); + fix_length_and_charset(m_hashed_password_buffer_len, default_charset()); + m_recalculate_password= false; + return; + } + } + + m_recalculate_password= true; + fix_length_and_charset(CRYPT_MAX_PASSWORD_SIZE, default_charset()); +} + String *Item_func_password::val_str_ascii(String *str) { DBUG_ASSERT(fixed == 1); - String *res= args[0]->val_str(str); - if ((null_value=args[0]->null_value)) - return 0; - if (res->length() == 0) + + String *res= args[0]->val_str(str); + + if (args[0]->null_value) + res= make_empty_result(); + + /* we treat NULLs as equal to empty string when calling the plugin */ + check_password_policy(res); + + null_value= 0; + if (args[0]->null_value) // PASSWORD(NULL) returns '' + return res; + + if (m_recalculate_password) + m_hashed_password_buffer_len= calculate_password(res, + m_hashed_password_buffer); + + if (m_hashed_password_buffer_len == 0) return make_empty_result(); - my_make_scrambled_password(tmp_value, res->ptr(), res->length()); - str->set(tmp_value, SCRAMBLED_PASSWORD_CHAR_LENGTH, &my_charset_latin1); + + str->set(m_hashed_password_buffer, m_hashed_password_buffer_len, + default_charset()); + return str; } -char *Item_func_password::alloc(THD *thd, const char *password, - size_t pass_len) +char *Item_func_password:: + create_password_hash_buffer(THD *thd, const char *password, size_t pass_len) { - char *buff= (char *) thd->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH+1); - if (buff) + String *password_str= new (thd->mem_root)String(password, thd->variables. + character_set_client); + check_password_policy(password_str); + + char *buff= NULL; + if (thd->variables.old_passwords == 0) + { + /* Allocate memory for the password scramble and one extra byte for \0 */ + buff= (char *) thd->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH + 1); + my_make_scrambled_password_sha1(buff, password, pass_len); + } +#if defined(HAVE_OPENSSL) + else + { + /* Allocate memory for the password scramble and one extra byte for \0 */ + buff= (char *) thd->alloc(CRYPT_MAX_PASSWORD_SIZE + 1); my_make_scrambled_password(buff, password, pass_len); + } +#endif return buff; } + /* Item_func_old_password */ String *Item_func_old_password::val_str_ascii(String *str) diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 44be352bb05..c4fdc453ccc 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -21,6 +21,8 @@ /* This file defines all string functions */ +#include "crypt_genhash_impl.h" + #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class implementation */ #endif @@ -311,16 +313,21 @@ public: class Item_func_password :public Item_str_ascii_func { - char tmp_value[SCRAMBLED_PASSWORD_CHAR_LENGTH+1]; + char m_hashed_password_buffer[CRYPT_MAX_PASSWORD_SIZE + 1]; + unsigned int m_hashed_password_buffer_len; + bool m_recalculate_password; public: - Item_func_password(Item *a) :Item_str_ascii_func(a) {} - String *val_str_ascii(String *str); - void fix_length_and_dec() + Item_func_password(Item *a) :Item_str_ascii_func(a) { - fix_length_and_charset(SCRAMBLED_PASSWORD_CHAR_LENGTH, default_charset()); + m_hashed_password_buffer_len= 0; + m_recalculate_password= false; } + String *val_str_ascii(String *str); + void fix_length_and_dec(); const char *func_name() const { return "password"; } static char *alloc(THD *thd, const char *password, size_t pass_len); + static char *create_password_hash_buffer(THD *thd, const char *password, + size_t pass_len); }; diff --git a/sql/lex.h b/sql/lex.h index 0f20df71576..06d6012b469 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -557,6 +557,9 @@ static SYMBOL symbols[] = { { "START", SYM(START_SYM)}, { "STARTING", SYM(STARTING)}, { "STARTS", SYM(STARTS_SYM)}, + { "STATS_AUTO_RECALC",SYM(STATS_AUTO_RECALC_SYM)}, + { "STATS_PERSISTENT", SYM(STATS_PERSISTENT_SYM)}, + { "STATS_SAMPLE_PAGES",SYM(STATS_SAMPLE_PAGES_SYM)}, { "STATUS", SYM(STATUS_SYM)}, { "STOP", SYM(STOP_SYM)}, { "STORAGE", SYM(STORAGE_SYM)}, diff --git a/sql/lock.cc b/sql/lock.cc index bf53a925424..22ef9b95d29 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -705,7 +705,6 @@ MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, uint flags) { TABLE *t= table_ptr[i]; - if (t->s->tmp_table != NON_TRANSACTIONAL_TMP_TABLE && t->s->tmp_table != INTERNAL_TMP_TABLE) { diff --git a/sql/log_event.cc b/sql/log_event.cc index 4983263f589..c270b83fa7e 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -5607,7 +5607,8 @@ int Load_log_event::do_apply_event(NET* net, Relay_log_info const *rli, update it inside mysql_load(). */ List<Item> tmp_list; - if (mysql_load(thd, &ex, &tables, field_list, tmp_list, tmp_list, + if (open_temporary_tables(thd, &tables) || + mysql_load(thd, &ex, &tables, field_list, tmp_list, tmp_list, handle_dup, ignore, net != 0)) thd->is_slave_error= 1; if (thd->cuted_fields) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 65cce38e788..260427c1e2b 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3630,7 +3630,9 @@ static void my_malloc_size_cb_func(long long size, my_bool is_thread_specific) DBUG_PRINT("info", ("memory_used: %lld size: %lld", (longlong) thd->status_var.memory_used, size)); thd->status_var.memory_used+= size; +#ifndef ENABLE_BEFORE_END_OF_MERGE DBUG_ASSERT((longlong) thd->status_var.memory_used >= 0); +#endif } } } diff --git a/sql/sp_head.cc b/sql/sp_head.cc index e54bd796bbb..59363a7a04a 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -3094,7 +3094,8 @@ int sp_instr::exec_open_and_lock_tables(THD *thd, TABLE_LIST *tables) Check whenever we have access to tables for this statement and open and lock them before executing instructions core function. */ - if (check_table_access(thd, SELECT_ACL, tables, FALSE, UINT_MAX, FALSE) + if (open_temporary_tables(thd, tables) || + check_table_access(thd, SELECT_ACL, tables, FALSE, UINT_MAX, FALSE) || open_and_lock_tables(thd, tables, TRUE, 0)) result= -1; else diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index a33e087fdf4..2771ee25ffd 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -4634,6 +4634,19 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, } continue; } + + if (is_temporary_table(tl)) + { + /* + If this table list element corresponds to a pre-opened temporary + table skip checking of all relevant table-level privileges for it. + Note that during creation of temporary table we still need to check + if user has CREATE_TMP_ACL. + */ + tl->grant.want_privilege= 0; + continue; + } + GRANT_TABLE *grant_table= table_hash_search(sctx->host, sctx->ip, tl->get_db_name(), sctx->priv_user, @@ -9364,3 +9377,10 @@ maria_declare_plugin(mysql_password) MariaDB_PLUGIN_MATURITY_BETA /* Maturity */ } maria_declare_plugin_end; + + +/* called when new user is created or exsisting password is changed */ +int check_password_policy(String *password) +{ + return (0); +} diff --git a/sql/sql_acl.h b/sql/sql_acl.h index 3169746419c..d519279e9c2 100644 --- a/sql/sql_acl.h +++ b/sql/sql_acl.h @@ -95,6 +95,14 @@ CREATE_ACL | DROP_ACL | ALTER_ACL | INDEX_ACL | \ TRIGGER_ACL | REFERENCES_ACL | GRANT_ACL | CREATE_VIEW_ACL | SHOW_VIEW_ACL) +/** + Table-level privileges which are automatically "granted" to everyone on + existing temporary tables (CREATE_ACL is necessary for ALTER ... RENAME). +*/ +#define TMP_TABLE_ACLS \ +(SELECT_ACL | INSERT_ACL | UPDATE_ACL | DELETE_ACL | CREATE_ACL | DROP_ACL | \ + INDEX_ACL | ALTER_ACL) + /* Defines to change the above bits to how things are stored in tables This is needed as the 'host' and 'db' table is missing a few privileges @@ -245,7 +253,7 @@ int fill_schema_schema_privileges(THD *thd, TABLE_LIST *tables, COND *cond); int fill_schema_table_privileges(THD *thd, TABLE_LIST *tables, COND *cond); int fill_schema_column_privileges(THD *thd, TABLE_LIST *tables, COND *cond); int wild_case_compare(CHARSET_INFO *cs, const char *str,const char *wildstr); - +int check_password_policy(String *password); #ifdef NO_EMBEDDED_ACCESS_CHECKS #define check_grant(A,B,C,D,E,F) 0 #define check_grant_db(A,B) 0 diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index be2a4d3df64..214cfdd0bbb 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -44,7 +44,8 @@ static bool admin_recreate_table(THD *thd, TABLE_LIST *table_list) thd->mdl_context.release_transactional_locks(); DEBUG_SYNC(thd, "ha_admin_try_alter"); tmp_disable_binlog(thd); // binlogging is done by caller if wanted - result_code= mysql_recreate_table(thd, table_list); + result_code= (open_temporary_tables(thd, table_list) || + mysql_recreate_table(thd, table_list)); reenable_binlog(thd); /* mysql_recreate_table() can push OK or ERROR. @@ -404,7 +405,8 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, da->push_warning_info(&tmp_wi); - open_error= open_and_lock_tables(thd, table, TRUE, 0); + open_error= (open_temporary_tables(thd, table) || + open_and_lock_tables(thd, table, TRUE, 0)); da->pop_warning_info(); } @@ -418,7 +420,8 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, mode. It does make sense for the user to see such errors. */ - open_error= open_and_lock_tables(thd, table, TRUE, 0); + open_error= (open_temporary_tables(thd, table) || + open_and_lock_tables(thd, table, TRUE, 0)); } thd->prepare_derived_at_open= FALSE; @@ -857,7 +860,8 @@ send_result_message: table->mdl_request.ticket= NULL; DEBUG_SYNC(thd, "ha_admin_open_ltable"); table->mdl_request.set_type(MDL_SHARED_WRITE); - if ((table->table= open_ltable(thd, table, lock_type, 0))) + if (open_temporary_tables(thd, table) || + (table->table= open_ltable(thd, table, lock_type, 0))) { result_code= table->table->file->ha_analyze(thd, check_opt); if (result_code == HA_ADMIN_ALREADY_DONE) diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 0680c8f1b23..e223b521bfb 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -4534,6 +4534,7 @@ open_and_process_table(THD *thd, LEX *lex, TABLE_LIST *tables, bool safe_to_ignore_table= FALSE; DBUG_ENTER("open_and_process_table"); DEBUG_SYNC(thd, "open_and_process_table"); + DBUG_ASSERT(!tables->table); /* Ignore placeholders for derived tables. After derived tables @@ -5172,6 +5173,14 @@ restart: for (tables= *table_to_open; tables; table_to_open= &tables->next_global, tables= tables->next_global) { + /* Ignore temporary tables, as these has already been opened */ + if (tables->table) + { + DBUG_ASSERT(is_temporary_table(tables)); + /* We have to increment the counter for lock_tables */ + (*counter)++; + continue; + } error= open_and_process_table(thd, thd->lex, tables, counter, flags, prelocking_strategy, has_prelocking_list, &ot_ctx, @@ -5206,6 +5215,10 @@ restart: if (ot_ctx.recover_from_failed_open(thd)) goto err; + /* Re-open temporary tables after close_tables_for_reopen(). */ + if (open_temporary_tables(thd, *start)) + goto err; + error= FALSE; goto restart; } @@ -5259,6 +5272,10 @@ restart: if (ot_ctx.recover_from_failed_open(thd)) goto err; + /* Re-open temporary tables after close_tables_for_reopen(). */ + if (open_temporary_tables(thd, *start)) + goto err; + error= FALSE; goto restart; } @@ -5673,6 +5690,10 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type, bool error; DBUG_ENTER("open_ltable"); + /* Ignore temporary tables as they have already ben opened*/ + if (table_list->table) + DBUG_RETURN(table_list->table); + /* should not be used in a prelocked_mode context, see NOTE above */ DBUG_ASSERT(thd->locked_tables_mode < LTM_PRELOCKED); @@ -5922,7 +5943,6 @@ bool lock_tables(THD *thd, TABLE_LIST *tables, uint count, uint flags) { TABLE_LIST *table; - DBUG_ENTER("lock_tables"); /* We can't meet statement requiring prelocking if we already @@ -6276,6 +6296,7 @@ TABLE *open_table_uncached(THD *thd, const char *path, const char *db, } tmp_table->reginfo.lock_type= TL_WRITE; // Simulate locked + tmp_table->grant.privilege= TMP_TABLE_ACLS; share->tmp_table= (tmp_table->file->has_transactions() ? TRANSACTIONAL_TMP_TABLE : NON_TRANSACTIONAL_TMP_TABLE); diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index 64b21ea6ab0..03978f3a4ba 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -294,7 +294,8 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, SQL_HANDLER *reopen) open_ltable() or open_table() because we would like to be able to open a temporary table. */ - error= open_tables(thd, &tables, &counter, 0); + error= (open_temporary_tables(thd, tables) || + open_tables(thd, &tables, &counter, 0)); if (error) goto err; diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 9b12b6dcbeb..67fa3301b6c 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -509,6 +509,7 @@ void lex_start(THD *thd) lex->use_only_table_context= FALSE; lex->parse_vcol_expr= FALSE; lex->verbose= 0; + lex->contains_plaintext_password= false; lex->name.str= 0; lex->name.length= 0; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 964acddfc23..92c78335238 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -2388,6 +2388,8 @@ struct LEX: public Query_tables_list bool sp_lex_in_use; /* Keep track on lex usage in SPs for error handling */ bool all_privileges; bool proxy_priv; + bool contains_plaintext_password; + sp_pcontext *spcont; st_sp_chistics sp_chistics; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index e80a221f3c4..e3503c171ac 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -512,7 +512,7 @@ void init_update_queries(void) DDL statements that should start with closing opened handlers. We use this flag only for statements for which open HANDLERs - have to be closed before emporary tables are pre-opened. + have to be closed before temporary tables are pre-opened. */ sql_command_flags[SQLCOM_CREATE_TABLE]|= CF_HA_CLOSE; sql_command_flags[SQLCOM_DROP_TABLE]|= CF_HA_CLOSE; @@ -1411,6 +1411,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd, thd->set_query(fields, query_length); general_log_print(thd, command, "%s %s", table_list.table_name, fields); + if (open_temporary_tables(thd, &table_list)) + break; + if (check_table_access(thd, SELECT_ACL, &table_list, TRUE, UINT_MAX, FALSE)) break; @@ -2386,6 +2389,30 @@ mysql_execute_command(THD *thd) goto error; } + /* + Close tables open by HANDLERs before executing DDL statement + which is going to affect those tables. + + This should happen before temporary tables are pre-opened as + otherwise we will get errors about attempt to re-open tables + if table to be changed is open through HANDLER. + + Note that even although this is done before any privilege + checks there is no security problem here as closing open + HANDLER doesn't require any privileges anyway. + */ + if (sql_command_flags[lex->sql_command] & CF_HA_CLOSE) + mysql_ha_rm_tables(thd, all_tables); + + /* + Pre-open temporary tables to simplify privilege checking + for statements which need this. + */ + if (sql_command_flags[lex->sql_command] & CF_PREOPEN_TMP_TABLES) + { + if (open_temporary_tables(thd, all_tables)) + goto error; + } switch (lex->sql_command) { case SQLCOM_SHOW_EVENTS: @@ -2771,7 +2798,10 @@ case SQLCOM_PREPARE: } #endif - /* Close any open handlers for the table. */ + /* + Close any open handlers for the table. We need to this extra call here + as there may have been new handlers created since the previous call. + */ mysql_ha_rm_tables(thd, create_table); if (select_lex->item_list.elements) // With select @@ -3107,6 +3137,13 @@ end_with_restore_list: else { /* + Temporary tables should be opened for SHOW CREATE TABLE, but not + for SHOW CREATE VIEW. + */ + if (open_temporary_tables(thd, all_tables)) + goto error; + + /* The fact that check_some_access() returned FALSE does not mean that access is granted. We need to check if first_table->grant.privilege contains any table-specific privilege. @@ -3284,6 +3321,18 @@ end_with_restore_list: case SQLCOM_INSERT: { DBUG_ASSERT(first_table == all_tables && first_table != 0); + + /* + Since INSERT DELAYED doesn't support temporary tables, we could + not pre-open temporary tables for SQLCOM_INSERT / SQLCOM_REPLACE. + Open them here instead. + */ + if (first_table->lock_type != TL_WRITE_DELAYED) + { + if ((res= open_temporary_tables(thd, all_tables))) + break; + } + if ((res= insert_precheck(thd, all_tables))) break; @@ -3621,6 +3670,19 @@ end_with_restore_list: thd->mdl_context.release_transactional_locks(); if (res) goto error; + + /* + Here we have to pre-open temporary tables for LOCK TABLES. + + CF_PREOPEN_TMP_TABLES is not set for this SQL statement simply + because LOCK TABLES calls close_thread_tables() as a first thing + (it's called from unlock_locked_tables() above). So even if + CF_PREOPEN_TMP_TABLES was set and the tables would be pre-opened + in a usual way, they would have been closed. + */ + if (open_temporary_tables(thd, all_tables)) + goto error; + if (check_table_access(thd, LOCK_TABLES_ACL | SELECT_ACL, all_tables, FALSE, UINT_MAX, FALSE)) goto error; @@ -5438,6 +5500,12 @@ static bool check_show_access(THD *thd, TABLE_LIST *table) DBUG_ASSERT(dst_table); + /* + Open temporary tables to be able to detect them during privilege check. + */ + if (open_temporary_tables(thd, dst_table)) + return TRUE; + if (check_access(thd, SELECT_ACL, dst_table->db, &dst_table->grant.privilege, &dst_table->grant.m_internal, diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 2460f15ab62..4649555a348 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1253,6 +1253,17 @@ static bool mysql_test_insert(Prepared_statement *stmt, List_item *values; DBUG_ENTER("mysql_test_insert"); + /* + Since INSERT DELAYED doesn't support temporary tables, we could + not pre-open temporary tables for SQLCOM_INSERT / SQLCOM_REPLACE. + Open them here instead. + */ + if (table_list->lock_type != TL_WRITE_DELAYED) + { + if (open_temporary_tables(thd, table_list)) + goto error; + } + if (insert_precheck(thd, table_list)) goto error; @@ -1819,6 +1830,13 @@ static bool mysql_test_create_view(Prepared_statement *stmt) if (create_view_precheck(thd, tables, view, lex->create_view_mode)) goto err; + /* + Since we can't pre-open temporary tables for SQLCOM_CREATE_VIEW, + (see mysql_create_view) we have to do it here instead. + */ + if (open_temporary_tables(thd, tables)) + goto err; + if (open_normal_and_derived_tables(thd, tables, MYSQL_OPEN_FORCE_SHARED_MDL, DT_PREPARE)) goto err; @@ -2056,6 +2074,19 @@ static bool check_prepared_statement(Prepared_statement *stmt) if (tables) thd->get_stmt_da()->opt_clear_warning_info(thd->query_id); + if (sql_command_flags[sql_command] & CF_HA_CLOSE) + mysql_ha_rm_tables(thd, tables); + + /* + Open temporary tables that are known now. Temporary tables added by + prelocking will be opened afterwards (during open_tables()). + */ + if (sql_command_flags[sql_command] & CF_PREOPEN_TMP_TABLES) + { + if (open_temporary_tables(thd, tables)) + goto error; + } + switch (sql_command) { case SQLCOM_REPLACE: case SQLCOM_INSERT: diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 1fc24b61c47..f3cb797226c 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1880,6 +1880,22 @@ int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet, packet->append(STRING_WITH_LEN(" PACK_KEYS=1")); if (create_info.options & HA_OPTION_NO_PACK_KEYS) packet->append(STRING_WITH_LEN(" PACK_KEYS=0")); + if (share->db_create_options & HA_OPTION_STATS_PERSISTENT) + packet->append(STRING_WITH_LEN(" STATS_PERSISTENT=1")); + if (share->db_create_options & HA_OPTION_NO_STATS_PERSISTENT) + packet->append(STRING_WITH_LEN(" STATS_PERSISTENT=0")); + if (share->stats_auto_recalc == HA_STATS_AUTO_RECALC_ON) + packet->append(STRING_WITH_LEN(" STATS_AUTO_RECALC=1")); + else if (share->stats_auto_recalc == HA_STATS_AUTO_RECALC_OFF) + packet->append(STRING_WITH_LEN(" STATS_AUTO_RECALC=0")); + if (share->stats_sample_pages != 0) + { + char *end; + packet->append(STRING_WITH_LEN(" STATS_SAMPLE_PAGES=")); + end= longlong10_to_str(share->stats_sample_pages, buff, 10); + packet->append(buff, (uint) (end - buff)); + } + /* We use CHECKSUM, instead of TABLE_CHECKSUM, for backward compability */ if (create_info.options & HA_OPTION_CHECKSUM) packet->append(STRING_WITH_LEN(" CHECKSUM=1")); @@ -4059,12 +4075,13 @@ fill_schema_table_by_open(THD *thd, bool is_show_fields_or_keys, 'only_view_structure()'. */ lex->sql_command= SQLCOM_SHOW_FIELDS; - result= open_normal_and_derived_tables(thd, table_list, - (MYSQL_OPEN_IGNORE_FLUSH | - MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL | - (can_deadlock ? - MYSQL_OPEN_FAIL_ON_MDL_CONFLICT : 0)), - DT_PREPARE | DT_CREATE); + result= (open_temporary_tables(thd, table_list) || + open_normal_and_derived_tables(thd, table_list, + (MYSQL_OPEN_IGNORE_FLUSH | + MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL | + (can_deadlock ? + MYSQL_OPEN_FAIL_ON_MDL_CONFLICT : 0)), + DT_PREPARE | DT_CREATE)); /* Restore old value of sql_command back as it is being looked at in process_table() function. @@ -4898,7 +4915,7 @@ static int get_schema_tables_record(THD *thd, TABLE_LIST *tables, } else { - char option_buff[350]; + char option_buff[512]; String str(option_buff,sizeof(option_buff), system_charset_info); TABLE *show_table= tables->table; TABLE_SHARE *share= show_table->s; @@ -4963,6 +4980,23 @@ static int get_schema_tables_record(THD *thd, TABLE_LIST *tables, if (share->db_create_options & HA_OPTION_NO_PACK_KEYS) str.qs_append(STRING_WITH_LEN(" pack_keys=0")); + if (share->db_create_options & HA_OPTION_STATS_PERSISTENT) + str.qs_append(STRING_WITH_LEN(" stats_persistent=1")); + + if (share->db_create_options & HA_OPTION_NO_STATS_PERSISTENT) + str.qs_append(STRING_WITH_LEN(" stats_persistent=0")); + + if (share->stats_auto_recalc == HA_STATS_AUTO_RECALC_ON) + str.qs_append(STRING_WITH_LEN(" stats_auto_recalc=1")); + else if (share->stats_auto_recalc == HA_STATS_AUTO_RECALC_OFF) + str.qs_append(STRING_WITH_LEN(" stats_auto_recalc=0")); + + if (share->stats_sample_pages != 0) + { + str.qs_append(STRING_WITH_LEN(" stats_sample_pages=")); + str.qs_append(share->stats_sample_pages); + } + /* We use CHECKSUM, instead of TABLE_CHECKSUM, for backward compability */ if (share->db_create_options & HA_OPTION_CHECKSUM) str.qs_append(STRING_WITH_LEN(" checksum=1")); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 733d5f51071..e5860b1ab9a 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -609,9 +609,9 @@ uint build_tmptable_filename(THD* thd, char *buff, size_t bufflen) DBUG_ENTER("build_tmptable_filename"); char *p= strnmov(buff, mysql_tmpdir, bufflen); - my_snprintf(p, bufflen - (p - buff), "/%s%lx_%lx_%x%s", + my_snprintf(p, bufflen - (p - buff), "/%s%lx_%lx_%x", tmp_file_prefix, current_pid, - thd->thread_id, thd->tmp_table++, reg_ext); + thd->thread_id, thd->tmp_table++); if (lower_case_table_names) { @@ -2083,15 +2083,18 @@ bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists, MYSQL_OPEN_SKIP_TEMPORARY)) DBUG_RETURN(true); for (table= tables; table; table= table->next_local) - + { + if (is_temporary_table(table)) + continue; tdc_remove_table(thd, TDC_RT_REMOVE_ALL, table->db, table->table_name, false); + } } else { for (table= tables; table; table= table->next_local) - if (table->open_type != OT_BASE_ONLY && - find_temporary_table(thd, table)) + { + if (is_temporary_table(table)) { /* A temporary table. @@ -2123,6 +2126,7 @@ bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists, DBUG_RETURN(true); table->mdl_request.ticket= table->table->mdl_ticket; } + } } } @@ -4760,14 +4764,16 @@ bool mysql_create_table(THD *thd, TABLE_LIST *create_table, result= mysql_create_table_no_lock(thd, create_table->db, create_table->table_name, create_info, alter_info, &is_trans, create_table_mode); + if (result) + DBUG_RETURN(result); /* In RBR we don't need to log CREATE TEMPORARY TABLE */ if (thd->is_current_stmt_binlog_format_row() && create_info->tmp_table()) DBUG_RETURN(0); - if (!result) - result= write_bin_log(thd, TRUE, thd->query(), thd->query_length(), - is_trans); + result= write_bin_log(thd, TRUE, thd->query(), thd->query_length(), is_trans); + thd->abort_on_warning= false; + end: DBUG_RETURN(result); } @@ -6438,8 +6444,16 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, table->file->info(HA_STATUS_AUTO); create_info->auto_increment_value= table->file->stats.auto_increment_value; } + if (!(used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE)) create_info->key_block_size= table->s->key_block_size; + + if (!(used_fields & HA_CREATE_USED_STATS_SAMPLE_PAGES)) + create_info->stats_sample_pages= table->s->stats_sample_pages; + + if (!(used_fields & HA_CREATE_USED_STATS_AUTO_RECALC)) + create_info->stats_auto_recalc= table->s->stats_auto_recalc; + if (!(used_fields & HA_CREATE_USED_TRANSACTIONAL)) create_info->transactional= table->s->transactional; @@ -6824,6 +6838,11 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, (HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS)) || (used_fields & HA_CREATE_USED_PACK_KEYS)) db_create_options&= ~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS); + if ((create_info->table_options & + (HA_OPTION_STATS_PERSISTENT | HA_OPTION_NO_STATS_PERSISTENT)) || + (used_fields & HA_CREATE_USED_STATS_PERSISTENT)) + db_create_options&= ~(HA_OPTION_STATS_PERSISTENT | HA_OPTION_NO_STATS_PERSISTENT); + if (create_info->table_options & (HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM)) db_create_options&= ~(HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM); diff --git a/sql/sql_update.cc b/sql/sql_update.cc index eab8b3af84c..1dd83fa8865 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -932,7 +932,7 @@ int mysql_update(THD *thd, char buff[MYSQL_ERRMSG_SIZE]; my_snprintf(buff, sizeof(buff), ER(ER_UPDATE_INFO), (ulong) found, (ulong) updated, - (ulong) thd->get_stmt_da()->statement_warn_count()); + (ulong) thd->get_stmt_da()->current_statement_warn_count()); my_ok(thd, (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated, id, buff); DBUG_PRINT("info",("%ld records updated", (long) updated)); diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 38d6b41d92b..036c04bf2f6 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -437,7 +437,8 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, lex->link_first_table_back(view, link_to_local); view->open_type= OT_BASE_ONLY; - if (open_and_lock_tables(thd, lex->query_tables, TRUE, 0)) + if (open_temporary_tables(thd, lex->query_tables) || + open_and_lock_tables(thd, lex->query_tables, TRUE, 0)) { view= lex->unlink_first_table(&link_to_local); res= TRUE; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 8e5ec870ac3..521aed2e04a 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1497,6 +1497,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token STARTING %token STARTS_SYM %token START_SYM /* SQL-2003-R */ +%token STATS_AUTO_RECALC_SYM +%token STATS_PERSISTENT_SYM +%token STATS_SAMPLE_PAGES_SYM %token STATUS_SYM %token STDDEV_SAMP_SYM /* SQL-2003-N */ %token STD_SYM @@ -2135,6 +2138,7 @@ master_def: | MASTER_PASSWORD_SYM EQ TEXT_STRING_sys { Lex->mi.password = $3.str; + Lex->contains_plaintext_password= true; } | MASTER_PORT_SYM EQ ulong_num { @@ -2445,6 +2449,7 @@ server_option: | PASSWORD TEXT_STRING_sys { Lex->server_options.password= $2.str; + Lex->contains_plaintext_password= true; } | SOCKET_SYM TEXT_STRING_sys { @@ -5531,6 +5536,70 @@ create_table_option: ~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS); Lex->create_info.used_fields|= HA_CREATE_USED_PACK_KEYS; } + | STATS_AUTO_RECALC_SYM opt_equal ulong_num + { + switch($3) { + case 0: + Lex->create_info.stats_auto_recalc= HA_STATS_AUTO_RECALC_OFF; + break; + case 1: + Lex->create_info.stats_auto_recalc= HA_STATS_AUTO_RECALC_ON; + break; + default: + my_parse_error(ER(ER_SYNTAX_ERROR)); + MYSQL_YYABORT; + } + Lex->create_info.used_fields|= HA_CREATE_USED_STATS_AUTO_RECALC; + } + | STATS_AUTO_RECALC_SYM opt_equal DEFAULT + { + Lex->create_info.stats_auto_recalc= HA_STATS_AUTO_RECALC_DEFAULT; + Lex->create_info.used_fields|= HA_CREATE_USED_STATS_AUTO_RECALC; + } + | STATS_PERSISTENT_SYM opt_equal ulong_num + { + switch($3) { + case 0: + Lex->create_info.table_options|= HA_OPTION_NO_STATS_PERSISTENT; + break; + case 1: + Lex->create_info.table_options|= HA_OPTION_STATS_PERSISTENT; + break; + default: + my_parse_error(ER(ER_SYNTAX_ERROR)); + MYSQL_YYABORT; + } + Lex->create_info.used_fields|= HA_CREATE_USED_STATS_PERSISTENT; + } + | STATS_PERSISTENT_SYM opt_equal DEFAULT + { + Lex->create_info.table_options&= + ~(HA_OPTION_STATS_PERSISTENT | HA_OPTION_NO_STATS_PERSISTENT); + Lex->create_info.used_fields|= HA_CREATE_USED_STATS_PERSISTENT; + } + | STATS_SAMPLE_PAGES_SYM opt_equal ulong_num + { + /* From user point of view STATS_SAMPLE_PAGES can be specified as + STATS_SAMPLE_PAGES=N (where 0<N<=65535, it does not make sense to + scan 0 pages) or STATS_SAMPLE_PAGES=default. Internally we record + =default as 0. See create_frm() in sql/table.cc, we use only two + bytes for stats_sample_pages and this is why we do not allow + larger values. 65535 pages, 16kb each means to sample 1GB, which + is impractical. If at some point this needs to be extended, then + we can store the higher bits from stats_sample_pages in .frm too. */ + if ($3 == 0 || $3 > 0xffff) + { + my_parse_error(ER(ER_SYNTAX_ERROR)); + MYSQL_YYABORT; + } + Lex->create_info.stats_sample_pages=$3; + Lex->create_info.used_fields|= HA_CREATE_USED_STATS_SAMPLE_PAGES; + } + | STATS_SAMPLE_PAGES_SYM opt_equal DEFAULT + { + Lex->create_info.stats_sample_pages=0; + Lex->create_info.used_fields|= HA_CREATE_USED_STATS_SAMPLE_PAGES; + } | CHECKSUM_SYM opt_equal ulong_num { Lex->create_info.table_options|= $3 ? HA_OPTION_CHECKSUM : HA_OPTION_NO_CHECKSUM; @@ -9531,6 +9600,7 @@ function_call_conflict: | OLD_PASSWORD '(' expr ')' { $$= new (YYTHD->mem_root) Item_func_old_password($3); + Lex->contains_plaintext_password= true; if ($$ == NULL) MYSQL_YYABORT; } @@ -9538,7 +9608,8 @@ function_call_conflict: { THD *thd= YYTHD; Item* i1; - if (thd->variables.old_passwords) + Lex->contains_plaintext_password= true; + if (thd->variables.old_passwords == 1) i1= new (thd->mem_root) Item_func_old_password($3); else i1= new (thd->mem_root) Item_func_password($3); @@ -14432,24 +14503,33 @@ text_or_password: TEXT_STRING { $$=$1.str;} | PASSWORD '(' TEXT_STRING ')' { - $$= $3.length ? YYTHD->variables.old_passwords ? - Item_func_old_password::alloc(YYTHD, $3.str, $3.length) : - Item_func_password::alloc(YYTHD, $3.str, $3.length) : - $3.str; + if ($3.length == 0) + $$= $3.str; + else + switch (YYTHD->variables.old_passwords) { + case 1: $$= Item_func_old_password:: + alloc(YYTHD, $3.str, $3.length); + break; + case 0: + case 2: $$= Item_func_password:: + create_password_hash_buffer(YYTHD, $3.str, $3.length); + break; + } if ($$ == NULL) MYSQL_YYABORT; + Lex->contains_plaintext_password= true; } | OLD_PASSWORD '(' TEXT_STRING ')' { - $$= $3.length ? Item_func_old_password::alloc(YYTHD, $3.str, - $3.length) : + $$= $3.length ? Item_func_old_password:: + alloc(YYTHD, $3.str, $3.length) : $3.str; if ($$ == NULL) MYSQL_YYABORT; + Lex->contains_plaintext_password= true; } ; - set_expr_or_default: expr { $$=$1; } | DEFAULT { $$=0; } @@ -14930,9 +15010,11 @@ grant_user: user IDENTIFIED_SYM BY TEXT_STRING { $$=$1; $1->password=$4; + if (Lex->sql_command == SQLCOM_REVOKE) + MYSQL_YYABORT; if ($4.length) { - if (YYTHD->variables.old_passwords) + if (YYTHD->variables.old_passwords == 1) { char *buff= (char *) YYTHD->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH_323+1); @@ -14948,7 +15030,7 @@ grant_user: (char *) YYTHD->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH+1); if (buff == NULL) MYSQL_YYABORT; - my_make_scrambled_password(buff, $4.str, $4.length); + my_make_scrambled_password_sha1(buff, $4.str, $4.length); $1->password.str= buff; $1->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH; } |