Commit be269e56 authored by monty@mysql.com's avatar monty@mysql.com

SHOW STATUS does not anymore change local status variables (except...

SHOW STATUS does not anymore change local status variables (except com_show_status). Global status variables are still updated.
SHOW STATUS are not anymore put in slow query log because of no index usage.

Implemntation done by removing orig_sql_command and moving logic of SHOW STATUS to mysql_excute_command()
This simplifies code and allows us to remove some if statements all over the code.

Upgraded uc_update_queries[] to sql_command_flags and added more bitmaps to better categorize commands.
This allowed some overall simplifaction when testing sql_command.

Fixes bugs:
Bug#10210: running SHOW STATUS increments counters it shouldn't
Bug#19764: SHOW commands end up in the slow log as table scans
parent 49a33348
...@@ -60,7 +60,7 @@ Variable_name Value ...@@ -60,7 +60,7 @@ Variable_name Value
Qcache_hits 0 Qcache_hits 0
show status like "Qcache_not_cached"; show status like "Qcache_not_cached";
Variable_name Value Variable_name Value
Qcache_not_cached 5 Qcache_not_cached 0
select "user1"; select "user1";
user1 user1
user1 user1
...@@ -72,7 +72,7 @@ Variable_name Value ...@@ -72,7 +72,7 @@ Variable_name Value
Qcache_hits 0 Qcache_hits 0
show status like "Qcache_not_cached"; show status like "Qcache_not_cached";
Variable_name Value Variable_name Value
Qcache_not_cached 9 Qcache_not_cached 1
select * from t1; select * from t1;
a b c a b c
1 1 1 1 1 1
...@@ -85,7 +85,7 @@ Variable_name Value ...@@ -85,7 +85,7 @@ Variable_name Value
Qcache_hits 1 Qcache_hits 1
show status like "Qcache_not_cached"; show status like "Qcache_not_cached";
Variable_name Value Variable_name Value
Qcache_not_cached 12 Qcache_not_cached 1
select a from t1 ; select a from t1 ;
a a
1 1
...@@ -98,7 +98,7 @@ Variable_name Value ...@@ -98,7 +98,7 @@ Variable_name Value
Qcache_hits 2 Qcache_hits 2
show status like "Qcache_not_cached"; show status like "Qcache_not_cached";
Variable_name Value Variable_name Value
Qcache_not_cached 15 Qcache_not_cached 1
select c from t1; select c from t1;
c c
1 1
...@@ -111,7 +111,7 @@ Variable_name Value ...@@ -111,7 +111,7 @@ Variable_name Value
Qcache_hits 3 Qcache_hits 3
show status like "Qcache_not_cached"; show status like "Qcache_not_cached";
Variable_name Value Variable_name Value
Qcache_not_cached 18 Qcache_not_cached 1
show grants for current_user(); show grants for current_user();
Grants for @localhost Grants for @localhost
GRANT USAGE ON *.* TO ''@'localhost' GRANT USAGE ON *.* TO ''@'localhost'
...@@ -144,7 +144,7 @@ Variable_name Value ...@@ -144,7 +144,7 @@ Variable_name Value
Qcache_hits 7 Qcache_hits 7
show status like "Qcache_not_cached"; show status like "Qcache_not_cached";
Variable_name Value Variable_name Value
Qcache_not_cached 22 Qcache_not_cached 2
select "user3"; select "user3";
user3 user3
user3 user3
...@@ -168,7 +168,7 @@ Variable_name Value ...@@ -168,7 +168,7 @@ Variable_name Value
Qcache_hits 7 Qcache_hits 7
show status like "Qcache_not_cached"; show status like "Qcache_not_cached";
Variable_name Value Variable_name Value
Qcache_not_cached 30 Qcache_not_cached 7
select "user4"; select "user4";
user4 user4
user4 user4
...@@ -198,7 +198,7 @@ Variable_name Value ...@@ -198,7 +198,7 @@ Variable_name Value
Qcache_hits 8 Qcache_hits 8
show status like "Qcache_not_cached"; show status like "Qcache_not_cached";
Variable_name Value Variable_name Value
Qcache_not_cached 34 Qcache_not_cached 8
set names binary; set names binary;
delete from mysql.user where user in ("mysqltest_1","mysqltest_2","mysqltest_3"); delete from mysql.user where user in ("mysqltest_1","mysqltest_2","mysqltest_3");
delete from mysql.db where user in ("mysqltest_1","mysqltest_2","mysqltest_3"); delete from mysql.db where user in ("mysqltest_1","mysqltest_2","mysqltest_3");
......
...@@ -199,6 +199,8 @@ select table_name, column_name, privileges from information_schema.columns ...@@ -199,6 +199,8 @@ select table_name, column_name, privileges from information_schema.columns
where table_schema = 'mysqltest' and table_name = 'v1'; where table_schema = 'mysqltest' and table_name = 'v1';
table_name column_name privileges table_name column_name privileges
v1 c select v1 c select
explain select * from v1;
ERROR HY000: EXPLAIN/SHOW can not be issued; lacking privileges for underlying table
drop view v1, mysqltest.v1; drop view v1, mysqltest.v1;
drop tables mysqltest.t4, mysqltest.t1, t2, t3, t5; drop tables mysqltest.t4, mysqltest.t1, t2, t3, t5;
drop database mysqltest; drop database mysqltest;
......
...@@ -1050,6 +1050,7 @@ Qcache_hits 1 ...@@ -1050,6 +1050,7 @@ Qcache_hits 1
drop table t1; drop table t1;
create table t1 (a int); create table t1 (a int);
insert into t1 values (1),(2); insert into t1 values (1),(2);
drop procedure if exists p1;
CREATE PROCEDURE `p1`() CREATE PROCEDURE `p1`()
begin begin
Declare c1 cursor for select a from t1; Declare c1 cursor for select a from t1;
......
...@@ -23,6 +23,32 @@ select 1; ...@@ -23,6 +23,32 @@ select 1;
show status like 'last_query_cost'; show status like 'last_query_cost';
Variable_name Value Variable_name Value
Last_query_cost 0.000000 Last_query_cost 0.000000
create table t1 (a int);
insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
select * from t1 where a=6;
a
6
6
6
6
6
show status like 'last_query_cost';
Variable_name Value
Last_query_cost 12.084449
show status like 'last_query_cost';
Variable_name Value
Last_query_cost 12.084449
select 1;
1
1
show status like 'last_query_cost';
Variable_name Value
Last_query_cost 0.000000
drop table t1;
FLUSH STATUS; FLUSH STATUS;
SHOW STATUS LIKE 'max_used_connections'; SHOW STATUS LIKE 'max_used_connections';
Variable_name Value Variable_name Value
...@@ -43,3 +69,27 @@ SHOW STATUS LIKE 'max_used_connections'; ...@@ -43,3 +69,27 @@ SHOW STATUS LIKE 'max_used_connections';
Variable_name Value Variable_name Value
Max_used_connections 5 Max_used_connections 5
SET GLOBAL thread_cache_size=@save_thread_cache_size; SET GLOBAL thread_cache_size=@save_thread_cache_size;
show status like 'com_show_status';
Variable_name Value
Com_show_status 3
show status like 'hand%write%';
Variable_name Value
Handler_write 0
show status like '%tmp%';
Variable_name Value
Created_tmp_disk_tables 0
Created_tmp_files 0
Created_tmp_tables 0
show status like 'hand%write%';
Variable_name Value
Handler_write 0
show status like '%tmp%';
Variable_name Value
Created_tmp_disk_tables 0
Created_tmp_files 0
Created_tmp_tables 0
show status like 'com_show_status';
Variable_name Value
Com_show_status 8
rnd_diff tmp_table_diff
20 8
...@@ -98,7 +98,7 @@ d ...@@ -98,7 +98,7 @@ d
show status like "created_tmp%tables"; show status like "created_tmp%tables";
Variable_name Value Variable_name Value
Created_tmp_disk_tables 0 Created_tmp_disk_tables 0
Created_tmp_tables 2 Created_tmp_tables 1
drop table t1; drop table t1;
create temporary table v1 as select 'This is temp. table' A; create temporary table v1 as select 'This is temp. table' A;
create view v1 as select 'This is view' A; create view v1 as select 'This is view' A;
......
...@@ -836,27 +836,27 @@ count(*) ...@@ -836,27 +836,27 @@ count(*)
26 26
show status like 'Slow_queries'; show status like 'Slow_queries';
Variable_name Value Variable_name Value
Slow_queries 1 Slow_queries 0
select count(*) from t1 where b=13; select count(*) from t1 where b=13;
count(*) count(*)
10 10
show status like 'Slow_queries'; show status like 'Slow_queries';
Variable_name Value Variable_name Value
Slow_queries 3 Slow_queries 1
select count(*) from t1 where b=13 union select count(*) from t1 where a=7; select count(*) from t1 where b=13 union select count(*) from t1 where a=7;
count(*) count(*)
10 10
26 26
show status like 'Slow_queries'; show status like 'Slow_queries';
Variable_name Value Variable_name Value
Slow_queries 5 Slow_queries 2
select count(*) from t1 where a=7 union select count(*) from t1 where b=13; select count(*) from t1 where a=7 union select count(*) from t1 where b=13;
count(*) count(*)
26 26
10 10
show status like 'Slow_queries'; show status like 'Slow_queries';
Variable_name Value Variable_name Value
Slow_queries 7 Slow_queries 3
flush status; flush status;
select a from t1 where b not in (1,2,3) union select a from t1 where b not in (4,5,6); select a from t1 where b not in (1,2,3) union select a from t1 where b not in (4,5,6);
a a
......
--disable_warnings
create database if not exists events_test; create database if not exists events_test;
--enable_warnings
use events_test; use events_test;
--error ER_NOT_SUPPORTED_YET --error ER_NOT_SUPPORTED_YET
......
...@@ -80,6 +80,8 @@ connect (user4,localhost,mysqltest_3,,mysqltest); ...@@ -80,6 +80,8 @@ connect (user4,localhost,mysqltest_3,,mysqltest);
connection user4; connection user4;
select table_name, column_name, privileges from information_schema.columns select table_name, column_name, privileges from information_schema.columns
where table_schema = 'mysqltest' and table_name = 'v1'; where table_schema = 'mysqltest' and table_name = 'v1';
--error 1345
explain select * from v1;
connection default; connection default;
drop view v1, mysqltest.v1; drop view v1, mysqltest.v1;
......
...@@ -765,6 +765,9 @@ drop table t1; ...@@ -765,6 +765,9 @@ drop table t1;
create table t1 (a int); create table t1 (a int);
insert into t1 values (1),(2); insert into t1 values (1),(2);
--disable_warnings
drop procedure if exists p1;
--enable_warnings
delimiter //; delimiter //;
CREATE PROCEDURE `p1`() CREATE PROCEDURE `p1`()
begin begin
......
...@@ -48,6 +48,19 @@ connection default; ...@@ -48,6 +48,19 @@ connection default;
select 1; select 1;
show status like 'last_query_cost'; show status like 'last_query_cost';
create table t1 (a int);
insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
select * from t1 where a=6;
show status like 'last_query_cost';
# Ensure value dosn't change by second status call
show status like 'last_query_cost';
select 1;
show status like 'last_query_cost';
drop table t1;
# #
# Test for Bug #15933 max_used_connections is wrong after FLUSH STATUS # Test for Bug #15933 max_used_connections is wrong after FLUSH STATUS
...@@ -144,3 +157,24 @@ disconnect con2; ...@@ -144,3 +157,24 @@ disconnect con2;
disconnect con1; disconnect con1;
# End of 5.0 tests # End of 5.0 tests
#
# Ensure that SHOW STATUS only changes global status variables
#
connect (con1,localhost,root,,);
let $rnd_next = `show global status like 'handler_read_rnd_next'`;
let $tmp_table = `show global status like 'Created_tmp_tables'`;
show status like 'com_show_status';
show status like 'hand%write%';
show status like '%tmp%';
show status like 'hand%write%';
show status like '%tmp%';
show status like 'com_show_status';
let $rnd_next2 = `show global status like 'handler_read_rnd_next'`;
let $tmp_table2 = `show global status like 'Created_tmp_tables'`;
--disable_query_log
eval select substring_index('$rnd_next2',0x9,-1)-substring_index('$rnd_next',0x9,-1) as rnd_diff, substring_index('$tmp_table2',0x9,-1)-substring_index('$tmp_table',0x9,-1) as tmp_table_diff;
--enable_query_log
# End of 5.1 tests
...@@ -1582,6 +1582,7 @@ extern TABLE *unused_tables; ...@@ -1582,6 +1582,7 @@ extern TABLE *unused_tables;
extern const char* any_db; extern const char* any_db;
extern struct my_option my_long_options[]; extern struct my_option my_long_options[];
extern const LEX_STRING view_type; extern const LEX_STRING view_type;
extern uint sql_command_flags[];
/* optional things, have_* variables */ /* optional things, have_* variables */
......
...@@ -516,6 +516,31 @@ void add_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var) ...@@ -516,6 +516,31 @@ void add_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var)
/* it doesn't make sense to add last_query_cost values */ /* it doesn't make sense to add last_query_cost values */
} }
/*
Add the difference between two status variable arrays to another one.
SYNOPSIS
add_diff_to_status
to_var add to this array
from_var from this array
dec_var minus this array
NOTE
This function assumes that all variables are long/ulong.
*/
void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var,
STATUS_VAR *dec_var)
{
ulong *end= (ulong*) ((byte*) to_var + offsetof(STATUS_VAR,
last_system_status_var) +
sizeof(ulong));
ulong *to= (ulong*) to_var, *from= (ulong*) from_var, *dec= (ulong*) dec_var;
while (to != end)
*(to++)+= *(from++) - *(dec++);
}
void THD::awake(THD::killed_state state_to_set) void THD::awake(THD::killed_state state_to_set)
{ {
......
...@@ -343,7 +343,6 @@ typedef struct system_status_var ...@@ -343,7 +343,6 @@ typedef struct system_status_var
#define last_system_status_var com_stmt_close #define last_system_status_var com_stmt_close
#ifdef MYSQL_SERVER #ifdef MYSQL_SERVER
void free_tmp_table(THD *thd, TABLE *entry); void free_tmp_table(THD *thd, TABLE *entry);
...@@ -833,6 +832,7 @@ class THD :public Statement, ...@@ -833,6 +832,7 @@ class THD :public Statement,
struct rand_struct rand; // used for authentication struct rand_struct rand; // used for authentication
struct system_variables variables; // Changeable local variables struct system_variables variables; // Changeable local variables
struct system_status_var status_var; // Per thread statistic vars struct system_status_var status_var; // Per thread statistic vars
struct system_status_var *initial_status_var; /* used by show status */
THR_LOCK_INFO lock_info; // Locking info of this thread THR_LOCK_INFO lock_info; // Locking info of this thread
THR_LOCK_OWNER main_lock_id; // To use for conventional queries THR_LOCK_OWNER main_lock_id; // To use for conventional queries
THR_LOCK_OWNER *lock_id; // If not main_lock_id, points to THR_LOCK_OWNER *lock_id; // If not main_lock_id, points to
...@@ -1306,6 +1306,10 @@ class THD :public Statement, ...@@ -1306,6 +1306,10 @@ class THD :public Statement,
{ {
return !stmt_arena->is_stmt_prepare() && !lex->only_view_structure(); return !stmt_arena->is_stmt_prepare() && !lex->only_view_structure();
} }
inline bool fill_information_schema_tables()
{
return !stmt_arena->is_stmt_prepare();
}
inline gptr trans_alloc(unsigned int size) inline gptr trans_alloc(unsigned int size)
{ {
return alloc_root(&transaction.mem_root,size); return alloc_root(&transaction.mem_root,size);
...@@ -1952,8 +1956,16 @@ class select_dumpvar :public select_result_interceptor { ...@@ -1952,8 +1956,16 @@ class select_dumpvar :public select_result_interceptor {
void cleanup(); void cleanup();
}; };
/* Bits in sql_command_flags */
#define CF_CHANGES_DATA 1
#define CF_HAS_ROW_COUNT 2
#define CF_STATUS_COMMAND 4
#define CF_SHOW_TABLE_COMMAND 8
/* Functions in sql_class.cc */ /* Functions in sql_class.cc */
void add_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var); void add_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var);
void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var,
STATUS_VAR *dec_var);
#endif /* MYSQL_SERVER */ #endif /* MYSQL_SERVER */
...@@ -168,7 +168,7 @@ void lex_start(THD *thd, const uchar *buf, uint length) ...@@ -168,7 +168,7 @@ void lex_start(THD *thd, const uchar *buf, uint length)
lex->select_lex.group_list.empty(); lex->select_lex.group_list.empty();
lex->select_lex.order_list.empty(); lex->select_lex.order_list.empty();
lex->ignore_space=test(thd->variables.sql_mode & MODE_IGNORE_SPACE); lex->ignore_space=test(thd->variables.sql_mode & MODE_IGNORE_SPACE);
lex->sql_command= lex->orig_sql_command= SQLCOM_END; lex->sql_command= SQLCOM_END;
lex->duplicates= DUP_ERROR; lex->duplicates= DUP_ERROR;
lex->ignore= 0; lex->ignore= 0;
lex->sphead= NULL; lex->sphead= NULL;
......
...@@ -934,7 +934,7 @@ typedef struct st_lex : public Query_tables_list ...@@ -934,7 +934,7 @@ typedef struct st_lex : public Query_tables_list
the variable can contain 0 or 1 for each nest level. the variable can contain 0 or 1 for each nest level.
*/ */
nesting_map allow_sum_func; nesting_map allow_sum_func;
enum_sql_command sql_command, orig_sql_command; enum_sql_command sql_command;
thr_lock_type lock_option; thr_lock_type lock_option;
enum SSL_type ssl_type; /* defined in violite.h */ enum SSL_type ssl_type; /* defined in violite.h */
enum my_lex_states next_state; enum my_lex_states next_state;
......
...@@ -68,6 +68,7 @@ static void decrease_user_connections(USER_CONN *uc); ...@@ -68,6 +68,7 @@ static void decrease_user_connections(USER_CONN *uc);
static bool check_db_used(THD *thd,TABLE_LIST *tables); static bool check_db_used(THD *thd,TABLE_LIST *tables);
static bool check_multi_update_lock(THD *thd); static bool check_multi_update_lock(THD *thd);
static void remove_escape(char *name); static void remove_escape(char *name);
static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables);
const char *any_db="*any*"; // Special symbol for check_access const char *any_db="*any*"; // Special symbol for check_access
...@@ -626,50 +627,79 @@ void free_max_user_conn(void) ...@@ -626,50 +627,79 @@ void free_max_user_conn(void)
sql_command is actually set to SQLCOM_END sometimes sql_command is actually set to SQLCOM_END sometimes
so we need the +1 to include it in the array. so we need the +1 to include it in the array.
numbers are: See COMMAND_FLAG_xxx for different type of commands
0 - read-only query
!= 0 - query that may change a table
2 - query that returns meaningful ROW_COUNT() - 2 - query that returns meaningful ROW_COUNT() -
a number of modified rows a number of modified rows
*/ */
char uc_update_queries[SQLCOM_END+1]; uint sql_command_flags[SQLCOM_END+1];
void init_update_queries(void) void init_update_queries(void)
{ {
bzero((gptr) &uc_update_queries, sizeof(uc_update_queries)); bzero((gptr) &sql_command_flags, sizeof(sql_command_flags));
uc_update_queries[SQLCOM_CREATE_TABLE]=1; sql_command_flags[SQLCOM_CREATE_TABLE]= CF_CHANGES_DATA;
uc_update_queries[SQLCOM_CREATE_INDEX]=1; sql_command_flags[SQLCOM_CREATE_INDEX]= CF_CHANGES_DATA;
uc_update_queries[SQLCOM_ALTER_TABLE]=1; sql_command_flags[SQLCOM_ALTER_TABLE]= CF_CHANGES_DATA;
uc_update_queries[SQLCOM_UPDATE]=2; sql_command_flags[SQLCOM_TRUNCATE]= CF_CHANGES_DATA;
uc_update_queries[SQLCOM_UPDATE_MULTI]=2; sql_command_flags[SQLCOM_DROP_TABLE]= CF_CHANGES_DATA;
uc_update_queries[SQLCOM_INSERT]=2; sql_command_flags[SQLCOM_LOAD]= CF_CHANGES_DATA;
uc_update_queries[SQLCOM_INSERT_SELECT]=2; sql_command_flags[SQLCOM_CREATE_DB]= CF_CHANGES_DATA;
uc_update_queries[SQLCOM_DELETE]=2; sql_command_flags[SQLCOM_DROP_DB]= CF_CHANGES_DATA;
uc_update_queries[SQLCOM_DELETE_MULTI]=2; sql_command_flags[SQLCOM_RENAME_TABLE]= CF_CHANGES_DATA;
uc_update_queries[SQLCOM_TRUNCATE]=1; sql_command_flags[SQLCOM_BACKUP_TABLE]= CF_CHANGES_DATA;
uc_update_queries[SQLCOM_DROP_TABLE]=1; sql_command_flags[SQLCOM_RESTORE_TABLE]= CF_CHANGES_DATA;
uc_update_queries[SQLCOM_LOAD]=1; sql_command_flags[SQLCOM_DROP_INDEX]= CF_CHANGES_DATA;
uc_update_queries[SQLCOM_CREATE_DB]=1; sql_command_flags[SQLCOM_CREATE_VIEW]= CF_CHANGES_DATA;
uc_update_queries[SQLCOM_DROP_DB]=1; sql_command_flags[SQLCOM_DROP_VIEW]= CF_CHANGES_DATA;
uc_update_queries[SQLCOM_REPLACE]=2; sql_command_flags[SQLCOM_CREATE_EVENT]= CF_CHANGES_DATA;
uc_update_queries[SQLCOM_REPLACE_SELECT]=2; sql_command_flags[SQLCOM_ALTER_EVENT]= CF_CHANGES_DATA;
uc_update_queries[SQLCOM_RENAME_TABLE]=1; sql_command_flags[SQLCOM_DROP_EVENT]= CF_CHANGES_DATA;
uc_update_queries[SQLCOM_BACKUP_TABLE]=1;
uc_update_queries[SQLCOM_RESTORE_TABLE]=1; sql_command_flags[SQLCOM_UPDATE]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
uc_update_queries[SQLCOM_DROP_INDEX]=1; sql_command_flags[SQLCOM_UPDATE_MULTI]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
uc_update_queries[SQLCOM_CREATE_VIEW]=1; sql_command_flags[SQLCOM_INSERT]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
uc_update_queries[SQLCOM_DROP_VIEW]=1; sql_command_flags[SQLCOM_INSERT_SELECT]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
uc_update_queries[SQLCOM_CREATE_EVENT]=1; sql_command_flags[SQLCOM_DELETE]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
uc_update_queries[SQLCOM_ALTER_EVENT]=1; sql_command_flags[SQLCOM_DELETE_MULTI]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
uc_update_queries[SQLCOM_DROP_EVENT]=1; sql_command_flags[SQLCOM_REPLACE]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
sql_command_flags[SQLCOM_REPLACE_SELECT]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
sql_command_flags[SQLCOM_SHOW_STATUS_PROC]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_STATUS_FUNC]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_STATUS]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_DATABASES]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_TRIGGERS]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_EVENTS]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_OPEN_TABLES]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_PLUGINS]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_FIELDS]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_KEYS]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_VARIABLES]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_CHARSETS]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_COLLATIONS]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_STATUS_PROC]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_TABLES]= (CF_STATUS_COMMAND |
CF_SHOW_TABLE_COMMAND);
sql_command_flags[SQLCOM_SHOW_TABLE_STATUS]= (CF_STATUS_COMMAND |
CF_SHOW_TABLE_COMMAND);
/*
The following is used to preserver CF_ROW_COUNT during the
a CALL or EXECUTE statement, so the value generated by the
last called (or executed) statement is preserved.
See mysql_execute_command() for how CF_ROW_COUNT is used.
*/
sql_command_flags[SQLCOM_CALL]= CF_HAS_ROW_COUNT;
sql_command_flags[SQLCOM_EXECUTE]= CF_HAS_ROW_COUNT;
} }
bool is_update_query(enum enum_sql_command command) bool is_update_query(enum enum_sql_command command)
{ {
DBUG_ASSERT(command >= 0 && command <= SQLCOM_END); DBUG_ASSERT(command >= 0 && command <= SQLCOM_END);
return uc_update_queries[command] != 0; return (sql_command_flags[command] & CF_CHANGES_DATA) == 0;
} }
/* /*
...@@ -733,7 +763,8 @@ static bool check_mqh(THD *thd, uint check_command) ...@@ -733,7 +763,8 @@ static bool check_mqh(THD *thd, uint check_command)
if (check_command < (uint) SQLCOM_END) if (check_command < (uint) SQLCOM_END)
{ {
/* Check that we have not done too many updates / hour */ /* Check that we have not done too many updates / hour */
if (uc->user_resources.updates && uc_update_queries[check_command] && if (uc->user_resources.updates &&
(sql_command_flags[check_command] & CF_CHANGES_DATA) &&
uc->updates++ >= uc->user_resources.updates) uc->updates++ >= uc->user_resources.updates)
{ {
net_printf_error(thd, ER_USER_LIMIT_REACHED, uc->user, "max_updates", net_printf_error(thd, ER_USER_LIMIT_REACHED, uc->user, "max_updates",
...@@ -2290,8 +2321,6 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident, ...@@ -2290,8 +2321,6 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
TABLE_LIST *table_list= (TABLE_LIST*) select_lex->table_list.first; TABLE_LIST *table_list= (TABLE_LIST*) select_lex->table_list.first;
table_list->schema_select_lex= sel; table_list->schema_select_lex= sel;
table_list->schema_table_reformed= 1; table_list->schema_table_reformed= 1;
statistic_increment(thd->status_var.com_stat[lex->orig_sql_command],
&LOCK_status);
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -2458,7 +2487,7 @@ mysql_execute_command(THD *thd) ...@@ -2458,7 +2487,7 @@ mysql_execute_command(THD *thd)
*/ */
if (opt_readonly && if (opt_readonly &&
!(thd->security_ctx->master_access & SUPER_ACL) && !(thd->security_ctx->master_access & SUPER_ACL) &&
uc_update_queries[lex->sql_command] && (sql_command_flags[lex->sql_command] & CF_CHANGES_DATA) &&
!((lex->sql_command == SQLCOM_CREATE_TABLE) && !((lex->sql_command == SQLCOM_CREATE_TABLE) &&
(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE)) && (lex->create_info.options & HA_LEX_CREATE_TMP_TABLE)) &&
((lex->sql_command != SQLCOM_UPDATE_MULTI) && ((lex->sql_command != SQLCOM_UPDATE_MULTI) &&
...@@ -2470,7 +2499,6 @@ mysql_execute_command(THD *thd) ...@@ -2470,7 +2499,6 @@ mysql_execute_command(THD *thd)
#ifdef HAVE_REPLICATION #ifdef HAVE_REPLICATION
} /* endif unlikely slave */ } /* endif unlikely slave */
#endif #endif
if(lex->orig_sql_command == SQLCOM_END)
statistic_increment(thd->status_var.com_stat[lex->sql_command], statistic_increment(thd->status_var.com_stat[lex->sql_command],
&LOCK_status); &LOCK_status);
...@@ -2480,77 +2508,61 @@ mysql_execute_command(THD *thd) ...@@ -2480,77 +2508,61 @@ mysql_execute_command(THD *thd)
#endif /*HAVE_ROW_BASED_REPLICATION*/ #endif /*HAVE_ROW_BASED_REPLICATION*/
switch (lex->sql_command) { switch (lex->sql_command) {
case SQLCOM_SELECT: case SQLCOM_SHOW_EVENTS:
{ if ((res= check_access(thd, EVENT_ACL, thd->lex->select_lex.db, 0, 0, 0,
/* assign global limit variable if limit is not given */ is_schema_db(thd->lex->select_lex.db))))
break;
/* fall through */
case SQLCOM_SHOW_STATUS_PROC:
case SQLCOM_SHOW_STATUS_FUNC:
res= execute_sqlcom_select(thd, all_tables);
break;
case SQLCOM_SHOW_STATUS:
{ {
SELECT_LEX *param= lex->unit.global_parameters; system_status_var old_status_var= thd->status_var;
if (!param->explicit_limit) thd->initial_status_var= &old_status_var;
param->select_limit= res= execute_sqlcom_select(thd, all_tables);
new Item_int((ulonglong)thd->variables.select_limit); /* Don't log SHOW STATUS commands to slow query log */
} thd->server_status&= ~(SERVER_QUERY_NO_INDEX_USED |
SERVER_QUERY_NO_GOOD_INDEX_USED);
select_result *result=lex->result; /*
restore status variables, as we don't want 'show status' to cause
changes
*/
pthread_mutex_lock(&LOCK_status);
add_diff_to_status(&global_status_var, &thd->status_var,
&old_status_var);
thd->status_var= old_status_var;
pthread_mutex_unlock(&LOCK_status);
break;
}
case SQLCOM_SHOW_DATABASES:
case SQLCOM_SHOW_TABLES:
case SQLCOM_SHOW_TRIGGERS:
case SQLCOM_SHOW_TABLE_STATUS:
case SQLCOM_SHOW_OPEN_TABLES:
case SQLCOM_SHOW_PLUGINS:
case SQLCOM_SHOW_FIELDS:
case SQLCOM_SHOW_KEYS:
case SQLCOM_SHOW_VARIABLES:
case SQLCOM_SHOW_CHARSETS:
case SQLCOM_SHOW_COLLATIONS:
case SQLCOM_SELECT:
thd->status_var.last_query_cost= 0.0;
if (all_tables) if (all_tables)
{ {
if (lex->orig_sql_command != SQLCOM_SHOW_STATUS_PROC &&
lex->orig_sql_command != SQLCOM_SHOW_STATUS_FUNC &&
lex->orig_sql_command != SQLCOM_SHOW_EVENTS)
res= check_table_access(thd, res= check_table_access(thd,
lex->exchange ? SELECT_ACL | FILE_ACL : lex->exchange ? SELECT_ACL | FILE_ACL :
SELECT_ACL, SELECT_ACL,
all_tables, 0); all_tables, 0);
else if (lex->orig_sql_command == SQLCOM_SHOW_EVENTS)
res= check_access(thd, EVENT_ACL, thd->lex->select_lex.db, 0, 0, 0,
is_schema_db(thd->lex->select_lex.db));
} }
else else
res= check_access(thd, res= check_access(thd,
lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL, lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL,
any_db, 0, 0, 0, 0); any_db, 0, 0, 0, 0);
if (res) if (!res)
goto error; res= execute_sqlcom_select(thd, all_tables);
if (!(res= open_and_lock_tables(thd, all_tables)))
{
if (lex->describe)
{
/*
We always use select_send for EXPLAIN, even if it's an EXPLAIN
for SELECT ... INTO OUTFILE: a user application should be able
to prepend EXPLAIN to any query and receive output for it,
even if the query itself redirects the output.
*/
if (!(result= new select_send()))
goto error;
else
thd->send_explain_fields(result);
res= mysql_explain_union(thd, &thd->lex->unit, result);
if (lex->describe & DESCRIBE_EXTENDED)
{
char buff[1024];
String str(buff,(uint32) sizeof(buff), system_charset_info);
str.length(0);
thd->lex->unit.print(&str);
str.append('\0');
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_YES, str.ptr());
}
result->send_eof();
delete result;
}
else
{
if (!result && !(result= new select_send()))
goto error;
query_cache_store_query(thd, all_tables);
res= handle_select(thd, lex, result, 0);
if (result != lex->result)
delete result;
}
}
break; break;
}
case SQLCOM_PREPARE: case SQLCOM_PREPARE:
{ {
mysql_sql_stmt_prepare(thd); mysql_sql_stmt_prepare(thd);
...@@ -4826,6 +4838,7 @@ mysql_execute_command(THD *thd) ...@@ -4826,6 +4838,7 @@ mysql_execute_command(THD *thd)
} }
break; break;
} }
#ifdef NOT_USED
case SQLCOM_SHOW_STATUS_PROC: case SQLCOM_SHOW_STATUS_PROC:
{ {
res= sp_show_status_procedure(thd, (lex->wild ? res= sp_show_status_procedure(thd, (lex->wild ?
...@@ -4838,6 +4851,7 @@ mysql_execute_command(THD *thd) ...@@ -4838,6 +4851,7 @@ mysql_execute_command(THD *thd)
lex->wild->ptr() : NullS)); lex->wild->ptr() : NullS));
break; break;
} }
#endif
#ifndef DBUG_OFF #ifndef DBUG_OFF
case SQLCOM_SHOW_PROC_CODE: case SQLCOM_SHOW_PROC_CODE:
case SQLCOM_SHOW_FUNC_CODE: case SQLCOM_SHOW_FUNC_CODE:
...@@ -5162,13 +5176,10 @@ mysql_execute_command(THD *thd) ...@@ -5162,13 +5176,10 @@ mysql_execute_command(THD *thd)
/* /*
The return value for ROW_COUNT() is "implementation dependent" if the The return value for ROW_COUNT() is "implementation dependent" if the
statement is not DELETE, INSERT or UPDATE, but -1 is what JDBC and ODBC statement is not DELETE, INSERT or UPDATE, but -1 is what JDBC and ODBC
wants. wants. We also keep the last value in case of SQLCOM_CALL or
SQLCOM_EXECUTE.
We do not change the value for a CALL or EXECUTE statement, so the value
generated by the last called (or executed) statement is preserved.
*/ */
if (lex->sql_command != SQLCOM_CALL && lex->sql_command != SQLCOM_EXECUTE && if (!(sql_command_flags[lex->sql_command] & CF_HAS_ROW_COUNT))
uc_update_queries[lex->sql_command]<2)
thd->row_count_func= -1; thd->row_count_func= -1;
DBUG_RETURN(res || thd->net.report_error); DBUG_RETURN(res || thd->net.report_error);
...@@ -5178,6 +5189,59 @@ mysql_execute_command(THD *thd) ...@@ -5178,6 +5189,59 @@ mysql_execute_command(THD *thd)
} }
static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables)
{
LEX *lex= thd->lex;
select_result *result=lex->result;
bool res;
/* assign global limit variable if limit is not given */
{
SELECT_LEX *param= lex->unit.global_parameters;
if (!param->explicit_limit)
param->select_limit=
new Item_int((ulonglong) thd->variables.select_limit);
}
if (!(res= open_and_lock_tables(thd, all_tables)))
{
if (lex->describe)
{
/*
We always use select_send for EXPLAIN, even if it's an EXPLAIN
for SELECT ... INTO OUTFILE: a user application should be able
to prepend EXPLAIN to any query and receive output for it,
even if the query itself redirects the output.
*/
if (!(result= new select_send()))
return 1;
thd->send_explain_fields(result);
res= mysql_explain_union(thd, &thd->lex->unit, result);
if (lex->describe & DESCRIBE_EXTENDED)
{
char buff[1024];
String str(buff,(uint32) sizeof(buff), system_charset_info);
str.length(0);
thd->lex->unit.print(&str);
str.append('\0');
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_YES, str.ptr());
}
result->send_eof();
delete result;
}
else
{
if (!result && !(result= new select_send()))
return 1;
query_cache_store_query(thd, all_tables);
res= handle_select(thd, lex, result, 0);
if (result != lex->result)
delete result;
}
}
return res;
}
/* /*
Check grants for commands which work only with one table and all other Check grants for commands which work only with one table and all other
tables belonging to subselects or implicitly opened tables. tables belonging to subselects or implicitly opened tables.
...@@ -6283,7 +6347,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, ...@@ -6283,7 +6347,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
ST_SCHEMA_TABLE *schema_table= find_schema_table(thd, ptr->table_name); ST_SCHEMA_TABLE *schema_table= find_schema_table(thd, ptr->table_name);
if (!schema_table || if (!schema_table ||
(schema_table->hidden && (schema_table->hidden &&
lex->orig_sql_command == SQLCOM_END)) // not a 'show' command (sql_command_flags[lex->sql_command] & CF_STATUS_COMMAND) == 0))
{ {
my_error(ER_UNKNOWN_TABLE, MYF(0), my_error(ER_UNKNOWN_TABLE, MYF(0),
ptr->table_name, information_schema_name.str); ptr->table_name, information_schema_name.str);
......
...@@ -1727,22 +1727,17 @@ static bool check_prepared_statement(Prepared_statement *stmt, ...@@ -1727,22 +1727,17 @@ static bool check_prepared_statement(Prepared_statement *stmt,
res= mysql_test_insert_select(stmt, tables); res= mysql_test_insert_select(stmt, tables);
break; break;
case SQLCOM_SHOW_DATABASES: /*
Note that we don't need to have cases in this list if they are
marked with CF_STATUS_COMMAND in sql_command_flags
*/
case SQLCOM_SHOW_PROCESSLIST: case SQLCOM_SHOW_PROCESSLIST:
case SQLCOM_SHOW_STORAGE_ENGINES: case SQLCOM_SHOW_STORAGE_ENGINES:
case SQLCOM_SHOW_PRIVILEGES: case SQLCOM_SHOW_PRIVILEGES:
case SQLCOM_SHOW_COLUMN_TYPES: case SQLCOM_SHOW_COLUMN_TYPES:
case SQLCOM_SHOW_STATUS:
case SQLCOM_SHOW_VARIABLES:
case SQLCOM_SHOW_ENGINE_LOGS: case SQLCOM_SHOW_ENGINE_LOGS:
case SQLCOM_SHOW_ENGINE_STATUS: case SQLCOM_SHOW_ENGINE_STATUS:
case SQLCOM_SHOW_ENGINE_MUTEX: case SQLCOM_SHOW_ENGINE_MUTEX:
case SQLCOM_SHOW_TABLES:
case SQLCOM_SHOW_OPEN_TABLES:
case SQLCOM_SHOW_CHARSETS:
case SQLCOM_SHOW_COLLATIONS:
case SQLCOM_SHOW_FIELDS:
case SQLCOM_SHOW_KEYS:
case SQLCOM_SHOW_CREATE_DB: case SQLCOM_SHOW_CREATE_DB:
case SQLCOM_SHOW_GRANTS: case SQLCOM_SHOW_GRANTS:
case SQLCOM_DROP_TABLE: case SQLCOM_DROP_TABLE:
...@@ -1762,10 +1757,18 @@ static bool check_prepared_statement(Prepared_statement *stmt, ...@@ -1762,10 +1757,18 @@ static bool check_prepared_statement(Prepared_statement *stmt,
break; break;
default: default:
/*
Trivial check of all status commands. This is easier than having
things in the above case list, as it's less chance for mistakes.
*/
if (!(sql_command_flags[sql_command] & CF_STATUS_COMMAND))
{
/* All other statements are not supported yet. */ /* All other statements are not supported yet. */
my_message(ER_UNSUPPORTED_PS, ER(ER_UNSUPPORTED_PS), MYF(0)); my_message(ER_UNSUPPORTED_PS, ER(ER_UNSUPPORTED_PS), MYF(0));
goto error; goto error;
} }
break;
}
if (res == 0) if (res == 0)
DBUG_RETURN(text_protocol? FALSE : (send_prep_stmt(stmt, 0) || DBUG_RETURN(text_protocol? FALSE : (send_prep_stmt(stmt, 0) ||
thd->protocol->flush())); thd->protocol->flush()));
......
...@@ -551,9 +551,6 @@ JOIN::optimize() ...@@ -551,9 +551,6 @@ JOIN::optimize()
DBUG_RETURN(0); DBUG_RETURN(0);
optimized= 1; optimized= 1;
if (thd->lex->orig_sql_command != SQLCOM_SHOW_STATUS)
thd->status_var.last_query_cost= 0.0;
row_limit= ((select_distinct || order || group_list) ? HA_POS_ERROR : row_limit= ((select_distinct || order || group_list) ? HA_POS_ERROR :
unit->select_limit_cnt); unit->select_limit_cnt);
/* select_limit is used to decide if we are likely to scan the whole table */ /* select_limit is used to decide if we are likely to scan the whole table */
...@@ -3875,9 +3872,7 @@ choose_plan(JOIN *join, table_map join_tables) ...@@ -3875,9 +3872,7 @@ choose_plan(JOIN *join, table_map join_tables)
/* /*
Store the cost of this query into a user variable Store the cost of this query into a user variable
Don't update last_query_cost for 'show status' command
*/ */
if (join->thd->lex->orig_sql_command != SQLCOM_SHOW_STATUS)
join->thd->status_var.last_query_cost= join->best_read; join->thd->status_var.last_query_cost= join->best_read;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
......
...@@ -2143,7 +2143,7 @@ bool schema_table_store_record(THD *thd, TABLE *table) ...@@ -2143,7 +2143,7 @@ bool schema_table_store_record(THD *thd, TABLE *table)
void get_index_field_values(LEX *lex, INDEX_FIELD_VALUES *index_field_values) void get_index_field_values(LEX *lex, INDEX_FIELD_VALUES *index_field_values)
{ {
const char *wild= lex->wild ? lex->wild->ptr() : NullS; const char *wild= lex->wild ? lex->wild->ptr() : NullS;
switch (lex->orig_sql_command) { switch (lex->sql_command) {
case SQLCOM_SHOW_DATABASES: case SQLCOM_SHOW_DATABASES:
index_field_values->db_value= wild; index_field_values->db_value= wild;
break; break;
...@@ -2332,10 +2332,9 @@ int make_db_list(THD *thd, List<char> *files, ...@@ -2332,10 +2332,9 @@ int make_db_list(THD *thd, List<char> *files,
/* /*
This part of code is for SHOW TABLES, SHOW TABLE STATUS commands. This part of code is for SHOW TABLES, SHOW TABLE STATUS commands.
idx_field_vals->db_value can't be 0 (see get_index_field_values() idx_field_vals->db_value can't be 0 (see get_index_field_values()
function). lex->orig_sql_command can be not equal to SQLCOM_END function).
only in case of executing of SHOW commands.
*/ */
if (lex->orig_sql_command != SQLCOM_END) if (sql_command_flags[lex->sql_command] & CF_STATUS_COMMAND)
{ {
if (!my_strcasecmp(system_charset_info, information_schema_name.str, if (!my_strcasecmp(system_charset_info, information_schema_name.str,
idx_field_vals->db_value)) idx_field_vals->db_value))
...@@ -2414,12 +2413,6 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) ...@@ -2414,12 +2413,6 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
LINT_INIT(end); LINT_INIT(end);
LINT_INIT(len); LINT_INIT(len);
/*
Let us set fake sql_command so views won't try to merge
themselves into main statement.
*/
lex->sql_command= SQLCOM_SHOW_FIELDS;
lex->reset_n_backup_query_tables_list(&query_tables_list_backup); lex->reset_n_backup_query_tables_list(&query_tables_list_backup);
/* /*
...@@ -2442,8 +2435,16 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) ...@@ -2442,8 +2435,16 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
I_S tables will be done. I_S tables will be done.
*/ */
thd->temporary_tables= open_tables_state_backup.temporary_tables; thd->temporary_tables= open_tables_state_backup.temporary_tables;
/*
Let us set fake sql_command so views won't try to merge
themselves into main statement. If we don't do this,
SELECT * from information_schema.xxxx will cause problems.
SQLCOM_SHOW_FIELDS is used because it satisfies 'only_view_structure()'
*/
lex->sql_command= SQLCOM_SHOW_FIELDS;
res= open_normal_and_derived_tables(thd, show_table_list, res= open_normal_and_derived_tables(thd, show_table_list,
MYSQL_LOCK_IGNORE_FLUSH); MYSQL_LOCK_IGNORE_FLUSH);
lex->sql_command= save_sql_command;
/* /*
get_all_tables() returns 1 on failure and 0 on success thus get_all_tables() returns 1 on failure and 0 on success thus
return only these and not the result code of ::process_table() return only these and not the result code of ::process_table()
...@@ -2474,13 +2475,13 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) ...@@ -2474,13 +2475,13 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
partial_cond= make_cond_for_info_schema(cond, tables); partial_cond= make_cond_for_info_schema(cond, tables);
it.rewind(); /* To get access to new elements in basis list */ it.rewind(); /* To get access to new elements in basis list */
while ((orig_base_name= base_name= it++) ||
/* /*
generate error for non existing database. Below we generate error for non existing database.
(to save old behaviour for SHOW TABLES FROM db) (to save old behaviour for SHOW TABLES FROM db)
*/ */
((lex->orig_sql_command == SQLCOM_SHOW_TABLES || while ((orig_base_name= base_name= it++) ||
lex->orig_sql_command == SQLCOM_SHOW_TABLE_STATUS) && ((sql_command_flags[save_sql_command] & CF_SHOW_TABLE_COMMAND) &&
(base_name= select_lex->db) && !bases.elements)) (base_name= select_lex->db) && !bases.elements))
{ {
#ifndef NO_EMBEDDED_ACCESS_CHECKS #ifndef NO_EMBEDDED_ACCESS_CHECKS
...@@ -2521,7 +2522,8 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) ...@@ -2521,7 +2522,8 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
{ {
if (schema_table_idx == SCH_TABLE_NAMES) if (schema_table_idx == SCH_TABLE_NAMES)
{ {
if (lex->verbose || lex->orig_sql_command == SQLCOM_END) if (lex->verbose ||
(sql_command_flags[save_sql_command] & CF_STATUS_COMMAND) == 0)
{ {
if (with_i_schema) if (with_i_schema)
{ {
...@@ -2565,8 +2567,10 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) ...@@ -2565,8 +2567,10 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
TABLE_LIST *show_table_list= (TABLE_LIST*) sel.table_list.first; TABLE_LIST *show_table_list= (TABLE_LIST*) sel.table_list.first;
lex->all_selects_list= &sel; lex->all_selects_list= &sel;
lex->derived_tables= 0; lex->derived_tables= 0;
lex->sql_command= SQLCOM_SHOW_FIELDS;
res= open_normal_and_derived_tables(thd, show_table_list, res= open_normal_and_derived_tables(thd, show_table_list,
MYSQL_LOCK_IGNORE_FLUSH); MYSQL_LOCK_IGNORE_FLUSH);
lex->sql_command= save_sql_command;
/* /*
We should use show_table_list->alias instead of We should use show_table_list->alias instead of
show_table_list->table_name because table_name show_table_list->table_name because table_name
...@@ -2876,7 +2880,7 @@ static int get_schema_column_record(THD *thd, struct st_table_list *tables, ...@@ -2876,7 +2880,7 @@ static int get_schema_column_record(THD *thd, struct st_table_list *tables,
if (res) if (res)
{ {
if (lex->orig_sql_command != SQLCOM_SHOW_FIELDS) if (lex->sql_command != SQLCOM_SHOW_FIELDS)
{ {
/* /*
I.e. we are in SELECT FROM INFORMATION_SCHEMA.COLUMS I.e. we are in SELECT FROM INFORMATION_SCHEMA.COLUMS
...@@ -2927,7 +2931,7 @@ static int get_schema_column_record(THD *thd, struct st_table_list *tables, ...@@ -2927,7 +2931,7 @@ static int get_schema_column_record(THD *thd, struct st_table_list *tables,
col_access= get_column_grant(thd, &tables->grant, col_access= get_column_grant(thd, &tables->grant,
base_name, file_name, base_name, file_name,
field->field_name) & COL_ACLS; field->field_name) & COL_ACLS;
if (lex->orig_sql_command != SQLCOM_SHOW_FIELDS && if (lex->sql_command != SQLCOM_SHOW_FIELDS &&
!tables->schema_table && !col_access) !tables->schema_table && !col_access)
continue; continue;
end= tmp; end= tmp;
...@@ -2972,7 +2976,7 @@ static int get_schema_column_record(THD *thd, struct st_table_list *tables, ...@@ -2972,7 +2976,7 @@ static int get_schema_column_record(THD *thd, struct st_table_list *tables,
table->field[5]->set_notnull(); table->field[5]->set_notnull();
} }
else if (field->unireg_check == Field::NEXT_NUMBER || else if (field->unireg_check == Field::NEXT_NUMBER ||
lex->orig_sql_command != SQLCOM_SHOW_FIELDS || lex->sql_command != SQLCOM_SHOW_FIELDS ||
field->maybe_null()) field->maybe_null())
table->field[5]->set_null(); // Null as default table->field[5]->set_null(); // Null as default
else else
...@@ -3242,16 +3246,18 @@ bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table, ...@@ -3242,16 +3246,18 @@ bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table,
get_field(thd->mem_root, proc_table->field[11], &definer); get_field(thd->mem_root, proc_table->field[11], &definer);
if (!full_access) if (!full_access)
full_access= !strcmp(sp_user, definer.ptr()); full_access= !strcmp(sp_user, definer.ptr());
if (!full_access && check_some_routine_access(thd, sp_db.ptr(), sp_name.ptr(), if (!full_access && check_some_routine_access(thd, sp_db.ptr(),
proc_table->field[2]->val_int() == sp_name.ptr(),
proc_table->field[2]->
val_int() ==
TYPE_ENUM_PROCEDURE)) TYPE_ENUM_PROCEDURE))
return 0; return 0;
if (lex->orig_sql_command == SQLCOM_SHOW_STATUS_PROC && if (lex->sql_command == SQLCOM_SHOW_STATUS_PROC &&
proc_table->field[2]->val_int() == TYPE_ENUM_PROCEDURE || proc_table->field[2]->val_int() == TYPE_ENUM_PROCEDURE ||
lex->orig_sql_command == SQLCOM_SHOW_STATUS_FUNC && lex->sql_command == SQLCOM_SHOW_STATUS_FUNC &&
proc_table->field[2]->val_int() == TYPE_ENUM_FUNCTION || proc_table->field[2]->val_int() == TYPE_ENUM_FUNCTION ||
lex->orig_sql_command == SQLCOM_END) (sql_command_flags[lex->sql_command] & CF_STATUS_COMMAND) == 0)
{ {
restore_record(table, s->default_values); restore_record(table, s->default_values);
if (!wild || !wild[0] || !wild_compare(sp_name.ptr(), wild, 0)) if (!wild || !wild[0] || !wild_compare(sp_name.ptr(), wild, 0))
...@@ -3362,7 +3368,7 @@ static int get_schema_stat_record(THD *thd, struct st_table_list *tables, ...@@ -3362,7 +3368,7 @@ static int get_schema_stat_record(THD *thd, struct st_table_list *tables,
DBUG_ENTER("get_schema_stat_record"); DBUG_ENTER("get_schema_stat_record");
if (res) if (res)
{ {
if (thd->lex->orig_sql_command != SQLCOM_SHOW_KEYS) if (thd->lex->sql_command != SQLCOM_SHOW_KEYS)
{ {
/* /*
I.e. we are in SELECT FROM INFORMATION_SCHEMA.STATISTICS I.e. we are in SELECT FROM INFORMATION_SCHEMA.STATISTICS
...@@ -4153,7 +4159,7 @@ copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table) ...@@ -4153,7 +4159,7 @@ copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
optimized. It's guaranteed in case of SHOW EVENTS that the user optimized. It's guaranteed in case of SHOW EVENTS that the user
has access. has access.
*/ */
if (thd->lex->orig_sql_command != SQLCOM_SHOW_EVENTS && if (thd->lex->sql_command != SQLCOM_SHOW_EVENTS &&
check_access(thd, EVENT_ACL, et.dbname.str, 0, 0, 1, check_access(thd, EVENT_ACL, et.dbname.str, 0, 0, 1,
is_schema_db(et.dbname.str))) is_schema_db(et.dbname.str)))
DBUG_RETURN(0); DBUG_RETURN(0);
...@@ -4383,7 +4389,7 @@ int fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */) ...@@ -4383,7 +4389,7 @@ int fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */)
If it's SHOW EVENTS then thd->lex->select_lex.db is guaranteed not to If it's SHOW EVENTS then thd->lex->select_lex.db is guaranteed not to
be NULL. Let's do an assert anyway. be NULL. Let's do an assert anyway.
*/ */
if (thd->lex->orig_sql_command == SQLCOM_SHOW_EVENTS) if (thd->lex->sql_command == SQLCOM_SHOW_EVENTS)
{ {
DBUG_ASSERT(thd->lex->select_lex.db); DBUG_ASSERT(thd->lex->select_lex.db);
if (check_access(thd, EVENT_ACL, thd->lex->select_lex.db, 0, 0, 0, if (check_access(thd, EVENT_ACL, thd->lex->select_lex.db, 0, 0, 0,
...@@ -4411,7 +4417,7 @@ int fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */) ...@@ -4411,7 +4417,7 @@ int fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */)
will save use from doing a table scan and comparing will save use from doing a table scan and comparing
every single row's `db` with the schema which we show. every single row's `db` with the schema which we show.
*/ */
if (thd->lex->orig_sql_command == SQLCOM_SHOW_EVENTS) if (thd->lex->sql_command == SQLCOM_SHOW_EVENTS)
ret= events_table_index_read_for_db(thd, schema_table, event_table); ret= events_table_index_read_for_db(thd, schema_table, event_table);
else else
ret= events_table_scan_all(thd, schema_table, event_table); ret= events_table_scan_all(thd, schema_table, event_table);
...@@ -4477,7 +4483,7 @@ int fill_status(THD *thd, TABLE_LIST *tables, COND *cond) ...@@ -4477,7 +4483,7 @@ int fill_status(THD *thd, TABLE_LIST *tables, COND *cond)
(SHOW_VAR *)all_status_vars.buffer, (SHOW_VAR *)all_status_vars.buffer,
OPT_GLOBAL, OPT_GLOBAL,
(lex->option_type == OPT_GLOBAL ? (lex->option_type == OPT_GLOBAL ?
&tmp: &thd->status_var), "",tables->table); &tmp: thd->initial_status_var), "",tables->table);
pthread_mutex_unlock(&LOCK_status); pthread_mutex_unlock(&LOCK_status);
DBUG_RETURN(res); DBUG_RETURN(res);
} }
...@@ -4670,7 +4676,7 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list) ...@@ -4670,7 +4676,7 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list)
schema_table pointer to 'schema_tables' element schema_table pointer to 'schema_tables' element
RETURN RETURN
-1 errror 1 error
0 success 0 success
*/ */
...@@ -4994,7 +5000,7 @@ bool get_schema_tables_result(JOIN *join) ...@@ -4994,7 +5000,7 @@ bool get_schema_tables_result(JOIN *join)
break; break;
TABLE_LIST *table_list= tab->table->pos_in_table_list; TABLE_LIST *table_list= tab->table->pos_in_table_list;
if (table_list->schema_table && thd->fill_derived_tables()) if (table_list->schema_table && thd->fill_information_schema_tables())
{ {
bool is_subselect= (&lex->unit != lex->current_select->master_unit() && bool is_subselect= (&lex->unit != lex->current_select->master_unit() &&
lex->current_select->master_unit()->item); lex->current_select->master_unit()->item);
......
...@@ -2058,16 +2058,19 @@ sp_cursor_stmt: ...@@ -2058,16 +2058,19 @@ sp_cursor_stmt:
{ {
Lex->sphead->reset_lex(YYTHD); Lex->sphead->reset_lex(YYTHD);
/* We use statement here just be able to get a better /*
We use statement here just be able to get a better
error message. Using 'select' works too, but will then error message. Using 'select' works too, but will then
result in a generic "syntax error" if a non-select result in a generic "syntax error" if a non-select
statement is given. */ statement is given.
*/
} }
statement statement
{ {
LEX *lex= Lex; LEX *lex= Lex;
if (lex->sql_command != SQLCOM_SELECT) if (lex->sql_command != SQLCOM_SELECT &&
!(sql_command_flags[lex->sql_command] & CF_STATUS_COMMAND))
{ {
my_message(ER_SP_BAD_CURSOR_QUERY, ER(ER_SP_BAD_CURSOR_QUERY), my_message(ER_SP_BAD_CURSOR_QUERY, ER(ER_SP_BAD_CURSOR_QUERY),
MYF(0)); MYF(0));
...@@ -8062,16 +8065,14 @@ show_param: ...@@ -8062,16 +8065,14 @@ show_param:
DATABASES wild_and_where DATABASES wild_and_where
{ {
LEX *lex= Lex; LEX *lex= Lex;
lex->sql_command= SQLCOM_SELECT; lex->sql_command= SQLCOM_SHOW_DATABASES;
lex->orig_sql_command= SQLCOM_SHOW_DATABASES;
if (prepare_schema_table(YYTHD, lex, 0, SCH_SCHEMATA)) if (prepare_schema_table(YYTHD, lex, 0, SCH_SCHEMATA))
YYABORT; YYABORT;
} }
| opt_full TABLES opt_db wild_and_where | opt_full TABLES opt_db wild_and_where
{ {
LEX *lex= Lex; LEX *lex= Lex;
lex->sql_command= SQLCOM_SELECT; lex->sql_command= SQLCOM_SHOW_TABLES;
lex->orig_sql_command= SQLCOM_SHOW_TABLES;
lex->select_lex.db= $3; lex->select_lex.db= $3;
if (prepare_schema_table(YYTHD, lex, 0, SCH_TABLE_NAMES)) if (prepare_schema_table(YYTHD, lex, 0, SCH_TABLE_NAMES))
YYABORT; YYABORT;
...@@ -8079,8 +8080,7 @@ show_param: ...@@ -8079,8 +8080,7 @@ show_param:
| opt_full TRIGGERS_SYM opt_db wild_and_where | opt_full TRIGGERS_SYM opt_db wild_and_where
{ {
LEX *lex= Lex; LEX *lex= Lex;
lex->sql_command= SQLCOM_SELECT; lex->sql_command= SQLCOM_SHOW_TRIGGERS;
lex->orig_sql_command= SQLCOM_SHOW_TRIGGERS;
lex->select_lex.db= $3; lex->select_lex.db= $3;
if (prepare_schema_table(YYTHD, lex, 0, SCH_TRIGGERS)) if (prepare_schema_table(YYTHD, lex, 0, SCH_TRIGGERS))
YYABORT; YYABORT;
...@@ -8088,8 +8088,7 @@ show_param: ...@@ -8088,8 +8088,7 @@ show_param:
| EVENTS_SYM opt_db wild_and_where | EVENTS_SYM opt_db wild_and_where
{ {
LEX *lex= Lex; LEX *lex= Lex;
lex->sql_command= SQLCOM_SELECT; lex->sql_command= SQLCOM_SHOW_EVENTS;
lex->orig_sql_command= SQLCOM_SHOW_EVENTS;
lex->select_lex.db= $2; lex->select_lex.db= $2;
if (prepare_schema_table(YYTHD, lex, 0, SCH_EVENTS)) if (prepare_schema_table(YYTHD, lex, 0, SCH_EVENTS))
YYABORT; YYABORT;
...@@ -8106,8 +8105,7 @@ show_param: ...@@ -8106,8 +8105,7 @@ show_param:
| TABLE_SYM STATUS_SYM opt_db wild_and_where | TABLE_SYM STATUS_SYM opt_db wild_and_where
{ {
LEX *lex= Lex; LEX *lex= Lex;
lex->sql_command= SQLCOM_SELECT; lex->sql_command= SQLCOM_SHOW_TABLE_STATUS;
lex->orig_sql_command= SQLCOM_SHOW_TABLE_STATUS;
lex->select_lex.db= $3; lex->select_lex.db= $3;
if (prepare_schema_table(YYTHD, lex, 0, SCH_TABLES)) if (prepare_schema_table(YYTHD, lex, 0, SCH_TABLES))
YYABORT; YYABORT;
...@@ -8115,8 +8113,7 @@ show_param: ...@@ -8115,8 +8113,7 @@ show_param:
| OPEN_SYM TABLES opt_db wild_and_where | OPEN_SYM TABLES opt_db wild_and_where
{ {
LEX *lex= Lex; LEX *lex= Lex;
lex->sql_command= SQLCOM_SELECT; lex->sql_command= SQLCOM_SHOW_OPEN_TABLES;
lex->orig_sql_command= SQLCOM_SHOW_OPEN_TABLES;
lex->select_lex.db= $3; lex->select_lex.db= $3;
if (prepare_schema_table(YYTHD, lex, 0, SCH_OPEN_TABLES)) if (prepare_schema_table(YYTHD, lex, 0, SCH_OPEN_TABLES))
YYABORT; YYABORT;
...@@ -8125,16 +8122,14 @@ show_param: ...@@ -8125,16 +8122,14 @@ show_param:
{ {
LEX *lex= Lex; LEX *lex= Lex;
WARN_DEPRECATED(yythd, "5.2", "SHOW PLUGIN", "'SHOW PLUGINS'"); WARN_DEPRECATED(yythd, "5.2", "SHOW PLUGIN", "'SHOW PLUGINS'");
lex->sql_command= SQLCOM_SELECT; lex->sql_command= SQLCOM_SHOW_PLUGINS;
lex->orig_sql_command= SQLCOM_SHOW_PLUGINS;
if (prepare_schema_table(YYTHD, lex, 0, SCH_PLUGINS)) if (prepare_schema_table(YYTHD, lex, 0, SCH_PLUGINS))
YYABORT; YYABORT;
} }
| PLUGINS_SYM | PLUGINS_SYM
{ {
LEX *lex= Lex; LEX *lex= Lex;
lex->sql_command= SQLCOM_SELECT; lex->sql_command= SQLCOM_SHOW_PLUGINS;
lex->orig_sql_command= SQLCOM_SHOW_PLUGINS;
if (prepare_schema_table(YYTHD, lex, 0, SCH_PLUGINS)) if (prepare_schema_table(YYTHD, lex, 0, SCH_PLUGINS))
YYABORT; YYABORT;
} }
...@@ -8147,8 +8142,7 @@ show_param: ...@@ -8147,8 +8142,7 @@ show_param:
| opt_full COLUMNS from_or_in table_ident opt_db wild_and_where | opt_full COLUMNS from_or_in table_ident opt_db wild_and_where
{ {
LEX *lex= Lex; LEX *lex= Lex;
lex->sql_command= SQLCOM_SELECT; lex->sql_command= SQLCOM_SHOW_FIELDS;
lex->orig_sql_command= SQLCOM_SHOW_FIELDS;
if ($5) if ($5)
$4->change_db($5); $4->change_db($5);
if (prepare_schema_table(YYTHD, lex, $4, SCH_COLUMNS)) if (prepare_schema_table(YYTHD, lex, $4, SCH_COLUMNS))
...@@ -8180,8 +8174,7 @@ show_param: ...@@ -8180,8 +8174,7 @@ show_param:
| keys_or_index from_or_in table_ident opt_db where_clause | keys_or_index from_or_in table_ident opt_db where_clause
{ {
LEX *lex= Lex; LEX *lex= Lex;
lex->sql_command= SQLCOM_SELECT; lex->sql_command= SQLCOM_SHOW_KEYS;
lex->orig_sql_command= SQLCOM_SHOW_KEYS;
if ($4) if ($4)
$3->change_db($4); $3->change_db($4);
if (prepare_schema_table(YYTHD, lex, $3, SCH_STATISTICS)) if (prepare_schema_table(YYTHD, lex, $3, SCH_STATISTICS))
...@@ -8202,7 +8195,6 @@ show_param: ...@@ -8202,7 +8195,6 @@ show_param:
{ {
LEX *lex=Lex; LEX *lex=Lex;
lex->sql_command= SQLCOM_SHOW_STORAGE_ENGINES; lex->sql_command= SQLCOM_SHOW_STORAGE_ENGINES;
lex->orig_sql_command= SQLCOM_SHOW_AUTHORS;
if (prepare_schema_table(YYTHD, lex, 0, SCH_ENGINES)) if (prepare_schema_table(YYTHD, lex, 0, SCH_ENGINES))
YYABORT; YYABORT;
} }
...@@ -8232,8 +8224,7 @@ show_param: ...@@ -8232,8 +8224,7 @@ show_param:
| opt_var_type STATUS_SYM wild_and_where | opt_var_type STATUS_SYM wild_and_where
{ {
LEX *lex= Lex; LEX *lex= Lex;
lex->sql_command= SQLCOM_SELECT; lex->sql_command= SQLCOM_SHOW_STATUS;
lex->orig_sql_command= SQLCOM_SHOW_STATUS;
lex->option_type= $1; lex->option_type= $1;
if (prepare_schema_table(YYTHD, lex, 0, SCH_STATUS)) if (prepare_schema_table(YYTHD, lex, 0, SCH_STATUS))
YYABORT; YYABORT;
...@@ -8267,8 +8258,7 @@ show_param: ...@@ -8267,8 +8258,7 @@ show_param:
| opt_var_type VARIABLES wild_and_where | opt_var_type VARIABLES wild_and_where
{ {
LEX *lex= Lex; LEX *lex= Lex;
lex->sql_command= SQLCOM_SELECT; lex->sql_command= SQLCOM_SHOW_VARIABLES;
lex->orig_sql_command= SQLCOM_SHOW_VARIABLES;
lex->option_type= $1; lex->option_type= $1;
if (prepare_schema_table(YYTHD, lex, 0, SCH_VARIABLES)) if (prepare_schema_table(YYTHD, lex, 0, SCH_VARIABLES))
YYABORT; YYABORT;
...@@ -8276,16 +8266,14 @@ show_param: ...@@ -8276,16 +8266,14 @@ show_param:
| charset wild_and_where | charset wild_and_where
{ {
LEX *lex= Lex; LEX *lex= Lex;
lex->sql_command= SQLCOM_SELECT; lex->sql_command= SQLCOM_SHOW_CHARSETS;
lex->orig_sql_command= SQLCOM_SHOW_CHARSETS;
if (prepare_schema_table(YYTHD, lex, 0, SCH_CHARSETS)) if (prepare_schema_table(YYTHD, lex, 0, SCH_CHARSETS))
YYABORT; YYABORT;
} }
| COLLATION_SYM wild_and_where | COLLATION_SYM wild_and_where
{ {
LEX *lex= Lex; LEX *lex= Lex;
lex->sql_command= SQLCOM_SELECT; lex->sql_command= SQLCOM_SHOW_COLLATIONS;
lex->orig_sql_command= SQLCOM_SHOW_COLLATIONS;
if (prepare_schema_table(YYTHD, lex, 0, SCH_COLLATIONS)) if (prepare_schema_table(YYTHD, lex, 0, SCH_COLLATIONS))
YYABORT; YYABORT;
} }
...@@ -8391,8 +8379,7 @@ show_param: ...@@ -8391,8 +8379,7 @@ show_param:
| PROCEDURE STATUS_SYM wild_and_where | PROCEDURE STATUS_SYM wild_and_where
{ {
LEX *lex= Lex; LEX *lex= Lex;
lex->sql_command= SQLCOM_SELECT; lex->sql_command= SQLCOM_SHOW_STATUS_PROC;
lex->orig_sql_command= SQLCOM_SHOW_STATUS_PROC;
if (!sp_add_to_query_tables(YYTHD, lex, "mysql", "proc", TL_READ)) if (!sp_add_to_query_tables(YYTHD, lex, "mysql", "proc", TL_READ))
YYABORT; YYABORT;
if (prepare_schema_table(YYTHD, lex, 0, SCH_PROCEDURES)) if (prepare_schema_table(YYTHD, lex, 0, SCH_PROCEDURES))
...@@ -8401,8 +8388,7 @@ show_param: ...@@ -8401,8 +8388,7 @@ show_param:
| FUNCTION_SYM STATUS_SYM wild_and_where | FUNCTION_SYM STATUS_SYM wild_and_where
{ {
LEX *lex= Lex; LEX *lex= Lex;
lex->sql_command= SQLCOM_SELECT; lex->sql_command= SQLCOM_SHOW_STATUS_FUNC;
lex->orig_sql_command= SQLCOM_SHOW_STATUS_FUNC;
if (!sp_add_to_query_tables(YYTHD, lex, "mysql", "proc", TL_READ)) if (!sp_add_to_query_tables(YYTHD, lex, "mysql", "proc", TL_READ))
YYABORT; YYABORT;
if (prepare_schema_table(YYTHD, lex, 0, SCH_PROCEDURES)) if (prepare_schema_table(YYTHD, lex, 0, SCH_PROCEDURES))
...@@ -8497,8 +8483,7 @@ describe: ...@@ -8497,8 +8483,7 @@ describe:
lex->lock_option= TL_READ; lex->lock_option= TL_READ;
mysql_init_select(lex); mysql_init_select(lex);
lex->current_select->parsing_place= SELECT_LIST; lex->current_select->parsing_place= SELECT_LIST;
lex->sql_command= SQLCOM_SELECT; lex->sql_command= SQLCOM_SHOW_FIELDS;
lex->orig_sql_command= SQLCOM_SHOW_FIELDS;
lex->select_lex.db= 0; lex->select_lex.db= 0;
lex->verbose= 0; lex->verbose= 0;
if (prepare_schema_table(YYTHD, lex, $2, SCH_COLUMNS)) if (prepare_schema_table(YYTHD, lex, $2, SCH_COLUMNS))
......
...@@ -180,7 +180,7 @@ typedef struct user_resources { ...@@ -180,7 +180,7 @@ typedef struct user_resources {
uint questions; uint questions;
/* /*
Maximum number of updating statements per hour (which statements are Maximum number of updating statements per hour (which statements are
updating is defined by uc_update_queries array). updating is defined by sql_command_flags array).
*/ */
uint updates; uint updates;
/* Maximum number of connections established per hour. */ /* Maximum number of connections established per hour. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment