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
This commit is contained in:
Michael Widenius 2013-06-18 02:01:34 +03:00
commit 2534521f9a
24 changed files with 473 additions and 62 deletions

View file

@ -552,7 +552,7 @@ sub main {
} }
} }
if ( not defined @$completed ) { if ( not @$completed ) {
mtr_error("Test suite aborted"); mtr_error("Test suite aborted");
} }

View file

@ -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 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. -- 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'); 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; PREPARE stmt FROM @str;
@ -130,7 +130,8 @@ CREATE TABLE IF NOT EXISTS innodb_index_stats (
SET SESSION sql_mode=@sql_mode_orig; 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 ( 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.', Number_of_lines INTEGER UNSIGNED NOT NULL COMMENT 'Number of lines in the file or rows in the table. Used to version table definitions.',

View file

@ -37,10 +37,10 @@ DROP TABLE tmp_db;
-- from local machine if "users" table didn't exist before -- from local machine if "users" table didn't exist before
CREATE TEMPORARY TABLE tmp_user LIKE user; CREATE TEMPORARY TABLE tmp_user LIKE user;
set @current_hostname= @@hostname; 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,'',''); 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 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 ('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,'',''); 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) VALUES ('localhost','');
INSERT INTO tmp_user (host,user) SELECT @current_hostname,'' FROM dual WHERE LOWER(@current_hostname ) != '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; INSERT INTO user SELECT * FROM tmp_user WHERE @had_user_table=0;

View file

@ -1808,28 +1808,133 @@ void Item_func_trim::print(String *str, enum_query_type query_type)
/* Item_func_password */ /* 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) String *Item_func_password::val_str_ascii(String *str)
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
String *res= args[0]->val_str(str);
if ((null_value=args[0]->null_value)) String *res= args[0]->val_str(str);
return 0;
if (res->length() == 0) 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(); 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; return str;
} }
char *Item_func_password::alloc(THD *thd, const char *password, char *Item_func_password::
size_t pass_len) create_password_hash_buffer(THD *thd, const char *password, size_t pass_len)
{ {
char *buff= (char *) thd->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH+1); String *password_str= new (thd->mem_root)String(password, thd->variables.
if (buff) 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); my_make_scrambled_password(buff, password, pass_len);
}
#endif
return buff; return buff;
} }
/* Item_func_old_password */ /* Item_func_old_password */
String *Item_func_old_password::val_str_ascii(String *str) String *Item_func_old_password::val_str_ascii(String *str)

View file

@ -21,6 +21,8 @@
/* This file defines all string functions */ /* This file defines all string functions */
#include "crypt_genhash_impl.h"
#ifdef USE_PRAGMA_INTERFACE #ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */ #pragma interface /* gcc class implementation */
#endif #endif
@ -311,16 +313,21 @@ public:
class Item_func_password :public Item_str_ascii_func 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: public:
Item_func_password(Item *a) :Item_str_ascii_func(a) {} Item_func_password(Item *a) :Item_str_ascii_func(a)
String *val_str_ascii(String *str);
void fix_length_and_dec()
{ {
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"; } const char *func_name() const { return "password"; }
static char *alloc(THD *thd, const char *password, size_t pass_len); 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);
}; };

View file

@ -557,6 +557,9 @@ static SYMBOL symbols[] = {
{ "START", SYM(START_SYM)}, { "START", SYM(START_SYM)},
{ "STARTING", SYM(STARTING)}, { "STARTING", SYM(STARTING)},
{ "STARTS", SYM(STARTS_SYM)}, { "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)}, { "STATUS", SYM(STATUS_SYM)},
{ "STOP", SYM(STOP_SYM)}, { "STOP", SYM(STOP_SYM)},
{ "STORAGE", SYM(STORAGE_SYM)}, { "STORAGE", SYM(STORAGE_SYM)},

View file

@ -705,7 +705,6 @@ MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, uint flags)
{ {
TABLE *t= table_ptr[i]; TABLE *t= table_ptr[i];
if (t->s->tmp_table != NON_TRANSACTIONAL_TMP_TABLE && if (t->s->tmp_table != NON_TRANSACTIONAL_TMP_TABLE &&
t->s->tmp_table != INTERNAL_TMP_TABLE) t->s->tmp_table != INTERNAL_TMP_TABLE)
{ {

View file

@ -5607,7 +5607,8 @@ int Load_log_event::do_apply_event(NET* net, Relay_log_info const *rli,
update it inside mysql_load(). update it inside mysql_load().
*/ */
List<Item> tmp_list; 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)) handle_dup, ignore, net != 0))
thd->is_slave_error= 1; thd->is_slave_error= 1;
if (thd->cuted_fields) if (thd->cuted_fields)

View file

@ -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", DBUG_PRINT("info", ("memory_used: %lld size: %lld",
(longlong) thd->status_var.memory_used, size)); (longlong) thd->status_var.memory_used, size));
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); DBUG_ASSERT((longlong) thd->status_var.memory_used >= 0);
#endif
} }
} }
} }

View file

@ -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 Check whenever we have access to tables for this statement
and open and lock them before executing instructions core function. 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)) || open_and_lock_tables(thd, tables, TRUE, 0))
result= -1; result= -1;
else else

View file

@ -4634,6 +4634,19 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
} }
continue; 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, GRANT_TABLE *grant_table= table_hash_search(sctx->host, sctx->ip,
tl->get_db_name(), tl->get_db_name(),
sctx->priv_user, sctx->priv_user,
@ -9364,3 +9377,10 @@ maria_declare_plugin(mysql_password)
MariaDB_PLUGIN_MATURITY_BETA /* Maturity */ MariaDB_PLUGIN_MATURITY_BETA /* Maturity */
} }
maria_declare_plugin_end; maria_declare_plugin_end;
/* called when new user is created or exsisting password is changed */
int check_password_policy(String *password)
{
return (0);
}

View file

@ -95,6 +95,14 @@
CREATE_ACL | DROP_ACL | ALTER_ACL | INDEX_ACL | \ CREATE_ACL | DROP_ACL | ALTER_ACL | INDEX_ACL | \
TRIGGER_ACL | REFERENCES_ACL | GRANT_ACL | CREATE_VIEW_ACL | SHOW_VIEW_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 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 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_table_privileges(THD *thd, TABLE_LIST *tables, COND *cond);
int fill_schema_column_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 wild_case_compare(CHARSET_INFO *cs, const char *str,const char *wildstr);
int check_password_policy(String *password);
#ifdef NO_EMBEDDED_ACCESS_CHECKS #ifdef NO_EMBEDDED_ACCESS_CHECKS
#define check_grant(A,B,C,D,E,F) 0 #define check_grant(A,B,C,D,E,F) 0
#define check_grant_db(A,B) 0 #define check_grant_db(A,B) 0

View file

@ -44,7 +44,8 @@ static bool admin_recreate_table(THD *thd, TABLE_LIST *table_list)
thd->mdl_context.release_transactional_locks(); thd->mdl_context.release_transactional_locks();
DEBUG_SYNC(thd, "ha_admin_try_alter"); DEBUG_SYNC(thd, "ha_admin_try_alter");
tmp_disable_binlog(thd); // binlogging is done by caller if wanted 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); reenable_binlog(thd);
/* /*
mysql_recreate_table() can push OK or ERROR. 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); 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(); 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. 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; thd->prepare_derived_at_open= FALSE;
@ -857,7 +860,8 @@ send_result_message:
table->mdl_request.ticket= NULL; table->mdl_request.ticket= NULL;
DEBUG_SYNC(thd, "ha_admin_open_ltable"); DEBUG_SYNC(thd, "ha_admin_open_ltable");
table->mdl_request.set_type(MDL_SHARED_WRITE); 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); result_code= table->table->file->ha_analyze(thd, check_opt);
if (result_code == HA_ADMIN_ALREADY_DONE) if (result_code == HA_ADMIN_ALREADY_DONE)

View file

@ -4534,6 +4534,7 @@ open_and_process_table(THD *thd, LEX *lex, TABLE_LIST *tables,
bool safe_to_ignore_table= FALSE; bool safe_to_ignore_table= FALSE;
DBUG_ENTER("open_and_process_table"); DBUG_ENTER("open_and_process_table");
DEBUG_SYNC(thd, "open_and_process_table"); DEBUG_SYNC(thd, "open_and_process_table");
DBUG_ASSERT(!tables->table);
/* /*
Ignore placeholders for derived tables. After derived tables Ignore placeholders for derived tables. After derived tables
@ -5172,6 +5173,14 @@ restart:
for (tables= *table_to_open; tables; for (tables= *table_to_open; tables;
table_to_open= &tables->next_global, tables= tables->next_global) 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, error= open_and_process_table(thd, thd->lex, tables, counter,
flags, prelocking_strategy, flags, prelocking_strategy,
has_prelocking_list, &ot_ctx, has_prelocking_list, &ot_ctx,
@ -5206,6 +5215,10 @@ restart:
if (ot_ctx.recover_from_failed_open(thd)) if (ot_ctx.recover_from_failed_open(thd))
goto err; goto err;
/* Re-open temporary tables after close_tables_for_reopen(). */
if (open_temporary_tables(thd, *start))
goto err;
error= FALSE; error= FALSE;
goto restart; goto restart;
} }
@ -5259,6 +5272,10 @@ restart:
if (ot_ctx.recover_from_failed_open(thd)) if (ot_ctx.recover_from_failed_open(thd))
goto err; goto err;
/* Re-open temporary tables after close_tables_for_reopen(). */
if (open_temporary_tables(thd, *start))
goto err;
error= FALSE; error= FALSE;
goto restart; goto restart;
} }
@ -5673,6 +5690,10 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type,
bool error; bool error;
DBUG_ENTER("open_ltable"); 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 */ /* should not be used in a prelocked_mode context, see NOTE above */
DBUG_ASSERT(thd->locked_tables_mode < LTM_PRELOCKED); DBUG_ASSERT(thd->locked_tables_mode < LTM_PRELOCKED);
@ -5922,7 +5943,6 @@ bool lock_tables(THD *thd, TABLE_LIST *tables, uint count,
uint flags) uint flags)
{ {
TABLE_LIST *table; TABLE_LIST *table;
DBUG_ENTER("lock_tables"); DBUG_ENTER("lock_tables");
/* /*
We can't meet statement requiring prelocking if we already 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->reginfo.lock_type= TL_WRITE; // Simulate locked
tmp_table->grant.privilege= TMP_TABLE_ACLS;
share->tmp_table= (tmp_table->file->has_transactions() ? share->tmp_table= (tmp_table->file->has_transactions() ?
TRANSACTIONAL_TMP_TABLE : NON_TRANSACTIONAL_TMP_TABLE); TRANSACTIONAL_TMP_TABLE : NON_TRANSACTIONAL_TMP_TABLE);

View file

@ -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 open_ltable() or open_table() because we would like to be able
to open a temporary table. 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) if (error)
goto err; goto err;

View file

@ -509,6 +509,7 @@ void lex_start(THD *thd)
lex->use_only_table_context= FALSE; lex->use_only_table_context= FALSE;
lex->parse_vcol_expr= FALSE; lex->parse_vcol_expr= FALSE;
lex->verbose= 0; lex->verbose= 0;
lex->contains_plaintext_password= false;
lex->name.str= 0; lex->name.str= 0;
lex->name.length= 0; lex->name.length= 0;

View file

@ -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 sp_lex_in_use; /* Keep track on lex usage in SPs for error handling */
bool all_privileges; bool all_privileges;
bool proxy_priv; bool proxy_priv;
bool contains_plaintext_password;
sp_pcontext *spcont; sp_pcontext *spcont;
st_sp_chistics sp_chistics; st_sp_chistics sp_chistics;

View file

@ -512,7 +512,7 @@ void init_update_queries(void)
DDL statements that should start with closing opened handlers. DDL statements that should start with closing opened handlers.
We use this flag only for statements for which open 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_CREATE_TABLE]|= CF_HA_CLOSE;
sql_command_flags[SQLCOM_DROP_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); thd->set_query(fields, query_length);
general_log_print(thd, command, "%s %s", table_list.table_name, fields); 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, if (check_table_access(thd, SELECT_ACL, &table_list,
TRUE, UINT_MAX, FALSE)) TRUE, UINT_MAX, FALSE))
break; break;
@ -2386,6 +2389,30 @@ mysql_execute_command(THD *thd)
goto error; 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) { switch (lex->sql_command) {
case SQLCOM_SHOW_EVENTS: case SQLCOM_SHOW_EVENTS:
@ -2771,7 +2798,10 @@ case SQLCOM_PREPARE:
} }
#endif #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); mysql_ha_rm_tables(thd, create_table);
if (select_lex->item_list.elements) // With select if (select_lex->item_list.elements) // With select
@ -3106,6 +3136,13 @@ end_with_restore_list:
} }
else 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 The fact that check_some_access() returned FALSE does not mean that
access is granted. We need to check if first_table->grant.privilege access is granted. We need to check if first_table->grant.privilege
@ -3284,6 +3321,18 @@ end_with_restore_list:
case SQLCOM_INSERT: case SQLCOM_INSERT:
{ {
DBUG_ASSERT(first_table == all_tables && first_table != 0); 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))) if ((res= insert_precheck(thd, all_tables)))
break; break;
@ -3621,6 +3670,19 @@ end_with_restore_list:
thd->mdl_context.release_transactional_locks(); thd->mdl_context.release_transactional_locks();
if (res) if (res)
goto error; 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, if (check_table_access(thd, LOCK_TABLES_ACL | SELECT_ACL, all_tables,
FALSE, UINT_MAX, FALSE)) FALSE, UINT_MAX, FALSE))
goto error; goto error;
@ -5438,6 +5500,12 @@ static bool check_show_access(THD *thd, TABLE_LIST *table)
DBUG_ASSERT(dst_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, if (check_access(thd, SELECT_ACL, dst_table->db,
&dst_table->grant.privilege, &dst_table->grant.privilege,
&dst_table->grant.m_internal, &dst_table->grant.m_internal,

View file

@ -1253,6 +1253,17 @@ static bool mysql_test_insert(Prepared_statement *stmt,
List_item *values; List_item *values;
DBUG_ENTER("mysql_test_insert"); 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)) if (insert_precheck(thd, table_list))
goto error; 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)) if (create_view_precheck(thd, tables, view, lex->create_view_mode))
goto err; 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, if (open_normal_and_derived_tables(thd, tables, MYSQL_OPEN_FORCE_SHARED_MDL,
DT_PREPARE)) DT_PREPARE))
goto err; goto err;
@ -2056,6 +2074,19 @@ static bool check_prepared_statement(Prepared_statement *stmt)
if (tables) if (tables)
thd->get_stmt_da()->opt_clear_warning_info(thd->query_id); 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) { switch (sql_command) {
case SQLCOM_REPLACE: case SQLCOM_REPLACE:
case SQLCOM_INSERT: case SQLCOM_INSERT:

View file

@ -1880,6 +1880,22 @@ int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
packet->append(STRING_WITH_LEN(" PACK_KEYS=1")); packet->append(STRING_WITH_LEN(" PACK_KEYS=1"));
if (create_info.options & HA_OPTION_NO_PACK_KEYS) if (create_info.options & HA_OPTION_NO_PACK_KEYS)
packet->append(STRING_WITH_LEN(" PACK_KEYS=0")); 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 */ /* We use CHECKSUM, instead of TABLE_CHECKSUM, for backward compability */
if (create_info.options & HA_OPTION_CHECKSUM) if (create_info.options & HA_OPTION_CHECKSUM)
packet->append(STRING_WITH_LEN(" CHECKSUM=1")); 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()'. 'only_view_structure()'.
*/ */
lex->sql_command= SQLCOM_SHOW_FIELDS; lex->sql_command= SQLCOM_SHOW_FIELDS;
result= open_normal_and_derived_tables(thd, table_list, result= (open_temporary_tables(thd, table_list) ||
(MYSQL_OPEN_IGNORE_FLUSH | open_normal_and_derived_tables(thd, table_list,
MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL | (MYSQL_OPEN_IGNORE_FLUSH |
(can_deadlock ? MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL |
MYSQL_OPEN_FAIL_ON_MDL_CONFLICT : 0)), (can_deadlock ?
DT_PREPARE | DT_CREATE); 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 Restore old value of sql_command back as it is being looked at in
process_table() function. process_table() function.
@ -4898,7 +4915,7 @@ static int get_schema_tables_record(THD *thd, TABLE_LIST *tables,
} }
else else
{ {
char option_buff[350]; char option_buff[512];
String str(option_buff,sizeof(option_buff), system_charset_info); String str(option_buff,sizeof(option_buff), system_charset_info);
TABLE *show_table= tables->table; TABLE *show_table= tables->table;
TABLE_SHARE *share= show_table->s; 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) if (share->db_create_options & HA_OPTION_NO_PACK_KEYS)
str.qs_append(STRING_WITH_LEN(" pack_keys=0")); 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 */ /* We use CHECKSUM, instead of TABLE_CHECKSUM, for backward compability */
if (share->db_create_options & HA_OPTION_CHECKSUM) if (share->db_create_options & HA_OPTION_CHECKSUM)
str.qs_append(STRING_WITH_LEN(" checksum=1")); str.qs_append(STRING_WITH_LEN(" checksum=1"));

View file

@ -609,9 +609,9 @@ uint build_tmptable_filename(THD* thd, char *buff, size_t bufflen)
DBUG_ENTER("build_tmptable_filename"); DBUG_ENTER("build_tmptable_filename");
char *p= strnmov(buff, mysql_tmpdir, bufflen); 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, tmp_file_prefix, current_pid,
thd->thread_id, thd->tmp_table++, reg_ext); thd->thread_id, thd->tmp_table++);
if (lower_case_table_names) 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)) MYSQL_OPEN_SKIP_TEMPORARY))
DBUG_RETURN(true); DBUG_RETURN(true);
for (table= tables; table; table= table->next_local) 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, tdc_remove_table(thd, TDC_RT_REMOVE_ALL, table->db, table->table_name,
false); false);
}
} }
else else
{ {
for (table= tables; table; table= table->next_local) 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. A temporary table.
@ -2123,6 +2126,7 @@ bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
DBUG_RETURN(true); DBUG_RETURN(true);
table->mdl_request.ticket= table->table->mdl_ticket; 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, result= mysql_create_table_no_lock(thd, create_table->db,
create_table->table_name, create_info, create_table->table_name, create_info,
alter_info, &is_trans, create_table_mode); alter_info, &is_trans, create_table_mode);
if (result)
DBUG_RETURN(result);
/* In RBR we don't need to log CREATE TEMPORARY TABLE */ /* In RBR we don't need to log CREATE TEMPORARY TABLE */
if (thd->is_current_stmt_binlog_format_row() && create_info->tmp_table()) if (thd->is_current_stmt_binlog_format_row() && create_info->tmp_table())
DBUG_RETURN(0); 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(), thd->abort_on_warning= false;
is_trans);
end: end:
DBUG_RETURN(result); DBUG_RETURN(result);
} }
@ -6438,8 +6444,16 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
table->file->info(HA_STATUS_AUTO); table->file->info(HA_STATUS_AUTO);
create_info->auto_increment_value= table->file->stats.auto_increment_value; create_info->auto_increment_value= table->file->stats.auto_increment_value;
} }
if (!(used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE)) if (!(used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE))
create_info->key_block_size= table->s->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)) if (!(used_fields & HA_CREATE_USED_TRANSACTIONAL))
create_info->transactional= table->s->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)) || (HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS)) ||
(used_fields & HA_CREATE_USED_PACK_KEYS)) (used_fields & HA_CREATE_USED_PACK_KEYS))
db_create_options&= ~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_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 & if (create_info->table_options &
(HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM)) (HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM))
db_create_options&= ~(HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM); db_create_options&= ~(HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM);

View file

@ -932,7 +932,7 @@ int mysql_update(THD *thd,
char buff[MYSQL_ERRMSG_SIZE]; char buff[MYSQL_ERRMSG_SIZE];
my_snprintf(buff, sizeof(buff), ER(ER_UPDATE_INFO), (ulong) found, my_snprintf(buff, sizeof(buff), ER(ER_UPDATE_INFO), (ulong) found,
(ulong) updated, (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, my_ok(thd, (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated,
id, buff); id, buff);
DBUG_PRINT("info",("%ld records updated", (long) updated)); DBUG_PRINT("info",("%ld records updated", (long) updated));

View file

@ -437,7 +437,8 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
lex->link_first_table_back(view, link_to_local); lex->link_first_table_back(view, link_to_local);
view->open_type= OT_BASE_ONLY; 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); view= lex->unlink_first_table(&link_to_local);
res= TRUE; res= TRUE;

View file

@ -1497,6 +1497,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token STARTING %token STARTING
%token STARTS_SYM %token STARTS_SYM
%token START_SYM /* SQL-2003-R */ %token START_SYM /* SQL-2003-R */
%token STATS_AUTO_RECALC_SYM
%token STATS_PERSISTENT_SYM
%token STATS_SAMPLE_PAGES_SYM
%token STATUS_SYM %token STATUS_SYM
%token STDDEV_SAMP_SYM /* SQL-2003-N */ %token STDDEV_SAMP_SYM /* SQL-2003-N */
%token STD_SYM %token STD_SYM
@ -2135,6 +2138,7 @@ master_def:
| MASTER_PASSWORD_SYM EQ TEXT_STRING_sys | MASTER_PASSWORD_SYM EQ TEXT_STRING_sys
{ {
Lex->mi.password = $3.str; Lex->mi.password = $3.str;
Lex->contains_plaintext_password= true;
} }
| MASTER_PORT_SYM EQ ulong_num | MASTER_PORT_SYM EQ ulong_num
{ {
@ -2445,6 +2449,7 @@ server_option:
| PASSWORD TEXT_STRING_sys | PASSWORD TEXT_STRING_sys
{ {
Lex->server_options.password= $2.str; Lex->server_options.password= $2.str;
Lex->contains_plaintext_password= true;
} }
| SOCKET_SYM TEXT_STRING_sys | SOCKET_SYM TEXT_STRING_sys
{ {
@ -5531,6 +5536,70 @@ create_table_option:
~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS); ~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS);
Lex->create_info.used_fields|= HA_CREATE_USED_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 | CHECKSUM_SYM opt_equal ulong_num
{ {
Lex->create_info.table_options|= $3 ? HA_OPTION_CHECKSUM : HA_OPTION_NO_CHECKSUM; Lex->create_info.table_options|= $3 ? HA_OPTION_CHECKSUM : HA_OPTION_NO_CHECKSUM;
@ -9531,6 +9600,7 @@ function_call_conflict:
| OLD_PASSWORD '(' expr ')' | OLD_PASSWORD '(' expr ')'
{ {
$$= new (YYTHD->mem_root) Item_func_old_password($3); $$= new (YYTHD->mem_root) Item_func_old_password($3);
Lex->contains_plaintext_password= true;
if ($$ == NULL) if ($$ == NULL)
MYSQL_YYABORT; MYSQL_YYABORT;
} }
@ -9538,7 +9608,8 @@ function_call_conflict:
{ {
THD *thd= YYTHD; THD *thd= YYTHD;
Item* i1; 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); i1= new (thd->mem_root) Item_func_old_password($3);
else else
i1= new (thd->mem_root) Item_func_password($3); i1= new (thd->mem_root) Item_func_password($3);
@ -14432,24 +14503,33 @@ text_or_password:
TEXT_STRING { $$=$1.str;} TEXT_STRING { $$=$1.str;}
| PASSWORD '(' TEXT_STRING ')' | PASSWORD '(' TEXT_STRING ')'
{ {
$$= $3.length ? YYTHD->variables.old_passwords ? if ($3.length == 0)
Item_func_old_password::alloc(YYTHD, $3.str, $3.length) : $$= $3.str;
Item_func_password::alloc(YYTHD, $3.str, $3.length) : else
$3.str; 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) if ($$ == NULL)
MYSQL_YYABORT; MYSQL_YYABORT;
Lex->contains_plaintext_password= true;
} }
| OLD_PASSWORD '(' TEXT_STRING ')' | OLD_PASSWORD '(' TEXT_STRING ')'
{ {
$$= $3.length ? Item_func_old_password::alloc(YYTHD, $3.str, $$= $3.length ? Item_func_old_password::
$3.length) : alloc(YYTHD, $3.str, $3.length) :
$3.str; $3.str;
if ($$ == NULL) if ($$ == NULL)
MYSQL_YYABORT; MYSQL_YYABORT;
Lex->contains_plaintext_password= true;
} }
; ;
set_expr_or_default: set_expr_or_default:
expr { $$=$1; } expr { $$=$1; }
| DEFAULT { $$=0; } | DEFAULT { $$=0; }
@ -14930,9 +15010,11 @@ grant_user:
user IDENTIFIED_SYM BY TEXT_STRING user IDENTIFIED_SYM BY TEXT_STRING
{ {
$$=$1; $1->password=$4; $$=$1; $1->password=$4;
if (Lex->sql_command == SQLCOM_REVOKE)
MYSQL_YYABORT;
if ($4.length) if ($4.length)
{ {
if (YYTHD->variables.old_passwords) if (YYTHD->variables.old_passwords == 1)
{ {
char *buff= char *buff=
(char *) YYTHD->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH_323+1); (char *) YYTHD->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH_323+1);
@ -14948,7 +15030,7 @@ grant_user:
(char *) YYTHD->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH+1); (char *) YYTHD->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH+1);
if (buff == NULL) if (buff == NULL)
MYSQL_YYABORT; 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.str= buff;
$1->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH; $1->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH;
} }