2011-06-30 17:46:53 +02:00
|
|
|
/* Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
|
2010-03-31 16:05:33 +02:00
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation; version 2 of the License.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
2019-05-11 20:29:06 +02:00
|
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
|
2010-03-31 16:05:33 +02:00
|
|
|
|
|
|
|
#ifndef SQL_PARSE_INCLUDED
|
|
|
|
#define SQL_PARSE_INCLUDED
|
|
|
|
|
|
|
|
#include "sql_acl.h" /* GLOBAL_ACLS */
|
|
|
|
|
|
|
|
class Comp_creator;
|
|
|
|
class Item;
|
|
|
|
class Object_creation_ctx;
|
|
|
|
class Parser_state;
|
2010-04-12 15:17:37 +02:00
|
|
|
struct TABLE_LIST;
|
2010-03-31 16:05:33 +02:00
|
|
|
class THD;
|
|
|
|
class Table_ident;
|
|
|
|
struct LEX;
|
|
|
|
|
|
|
|
enum enum_mysql_completiontype {
|
|
|
|
ROLLBACK_RELEASE=-2, ROLLBACK=1, ROLLBACK_AND_CHAIN=7,
|
|
|
|
COMMIT_RELEASE=-1, COMMIT=0, COMMIT_AND_CHAIN=6
|
|
|
|
};
|
|
|
|
|
2017-02-20 19:53:12 +01:00
|
|
|
extern "C" int path_starts_from_data_home_dir(const char *dir);
|
|
|
|
int test_if_data_home_dir(const char *dir);
|
2013-04-09 16:18:37 +02:00
|
|
|
int error_if_data_home_dir(const char *path, const char *what);
|
2016-01-05 20:44:45 +01:00
|
|
|
my_bool net_allocate_new_packet(NET *net, void *thd, uint my_flags);
|
2010-03-31 16:05:33 +02:00
|
|
|
|
|
|
|
bool multi_update_precheck(THD *thd, TABLE_LIST *tables);
|
|
|
|
bool multi_delete_precheck(THD *thd, TABLE_LIST *tables);
|
|
|
|
int mysql_multi_update_prepare(THD *thd);
|
|
|
|
int mysql_multi_delete_prepare(THD *thd);
|
2020-09-13 14:45:41 +02:00
|
|
|
int mysql_insert_select_prepare(THD *thd,select_result *sel_res);
|
2010-03-31 16:05:33 +02:00
|
|
|
bool update_precheck(THD *thd, TABLE_LIST *tables);
|
|
|
|
bool delete_precheck(THD *thd, TABLE_LIST *tables);
|
|
|
|
bool insert_precheck(THD *thd, TABLE_LIST *tables);
|
|
|
|
bool create_table_precheck(THD *thd, TABLE_LIST *tables,
|
|
|
|
TABLE_LIST *create_table);
|
2014-09-10 07:20:17 +02:00
|
|
|
bool check_fk_parent_table_access(THD *thd,
|
|
|
|
HA_CREATE_INFO *create_info,
|
2016-04-07 09:47:46 +02:00
|
|
|
Alter_info *alter_info,
|
|
|
|
const char* create_db);
|
2010-03-31 16:05:33 +02:00
|
|
|
|
2013-07-14 19:44:37 +02:00
|
|
|
bool parse_sql(THD *thd, Parser_state *parser_state,
|
|
|
|
Object_creation_ctx *creation_ctx, bool do_pfs_digest=false);
|
2010-03-31 16:05:33 +02:00
|
|
|
|
|
|
|
void free_items(Item *item);
|
|
|
|
void cleanup_items(Item *item);
|
|
|
|
|
|
|
|
Comp_creator *comp_eq_creator(bool invert);
|
|
|
|
Comp_creator *comp_ge_creator(bool invert);
|
|
|
|
Comp_creator *comp_gt_creator(bool invert);
|
|
|
|
Comp_creator *comp_le_creator(bool invert);
|
|
|
|
Comp_creator *comp_lt_creator(bool invert);
|
|
|
|
Comp_creator *comp_ne_creator(bool invert);
|
|
|
|
|
|
|
|
int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
|
|
|
|
enum enum_schema_tables schema_table_idx);
|
2013-10-18 21:17:49 +02:00
|
|
|
void get_default_definer(THD *thd, LEX_USER *definer, bool role);
|
|
|
|
LEX_USER *create_default_definer(THD *thd, bool role);
|
2017-04-23 18:39:57 +02:00
|
|
|
LEX_USER *create_definer(THD *thd, LEX_CSTRING *user_name, LEX_CSTRING *host_name);
|
2013-10-18 21:17:49 +02:00
|
|
|
LEX_USER *get_current_user(THD *thd, LEX_USER *user, bool lock=true);
|
2013-10-18 20:46:30 +02:00
|
|
|
bool sp_process_definer(THD *thd);
|
2017-08-04 12:41:05 +02:00
|
|
|
bool check_string_byte_length(const LEX_CSTRING *str, uint err_msg,
|
2018-02-06 13:55:58 +01:00
|
|
|
size_t max_byte_length);
|
2017-08-04 12:41:05 +02:00
|
|
|
bool check_string_char_length(const LEX_CSTRING *str, uint err_msg,
|
2018-02-06 13:55:58 +01:00
|
|
|
size_t max_char_length, CHARSET_INFO *cs,
|
2010-03-31 16:05:33 +02:00
|
|
|
bool no_error);
|
2017-08-04 12:41:05 +02:00
|
|
|
bool check_ident_length(const LEX_CSTRING *ident);
|
2017-04-23 18:39:57 +02:00
|
|
|
bool check_host_name(LEX_CSTRING *str);
|
|
|
|
bool check_identifier_name(LEX_CSTRING *str, uint max_char_length,
|
2010-03-31 16:05:33 +02:00
|
|
|
uint err_code, const char *param_for_err_msg);
|
|
|
|
bool mysql_test_parse_for_slave(THD *thd,char *inBuf,uint length);
|
2010-06-02 01:25:08 +02:00
|
|
|
bool sqlcom_can_generate_row_events(const THD *thd);
|
2018-05-06 22:46:56 +02:00
|
|
|
bool stmt_causes_implicit_commit(THD *thd, uint mask);
|
2010-03-31 16:05:33 +02:00
|
|
|
bool is_update_query(enum enum_sql_command command);
|
|
|
|
bool is_log_table_write_query(enum enum_sql_command command);
|
2018-02-06 13:55:58 +01:00
|
|
|
bool alloc_query(THD *thd, const char *packet, size_t packet_length);
|
2010-07-29 05:24:35 +02:00
|
|
|
void mysql_parse(THD *thd, char *rawbuf, uint length,
|
2020-07-08 18:31:00 +02:00
|
|
|
Parser_state *parser_state);
|
2017-03-14 11:52:00 +01:00
|
|
|
bool mysql_new_select(LEX *lex, bool move_down, SELECT_LEX *sel);
|
2017-06-19 05:34:38 +02:00
|
|
|
void create_select_for_variable(THD *thd, LEX_CSTRING *var_name);
|
2010-03-31 16:05:33 +02:00
|
|
|
void create_table_set_open_action_and_adjust_tables(LEX *lex);
|
|
|
|
void mysql_init_multi_delete(LEX *lex);
|
|
|
|
bool multi_delete_set_locks_and_link_aux_tables(LEX *lex);
|
|
|
|
void create_table_set_open_action_and_adjust_tables(LEX *lex);
|
2019-02-12 20:07:51 +01:00
|
|
|
int bootstrap(MYSQL_FILE *file);
|
MDEV-24860: Incorrect behaviour of SET STATEMENT in case it is executed as a prepared statement
Running statements with SET STATEMENT FOR clause is handled incorrectly in
case the whole statement is executed in prepared statement mode.
For example, running of the following statement
SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR CREATE TABLE t1 AS SELECT CONCAT('abc') AS c1;
results in different definition of the table t1 depending on whether
the statement is executed as a prepared or as a regular statement.
In first case the column c1 is defined as
`c1` varchar(3) DEFAULT NULL
in the last case the column c1 is defined as
`c1` varchar(3) NOT NULL
Different definition for the column c1 arise due to the fact that
a value of the data memeber Item_func_concat::maybe_null depends on
whether strict mode is on or off. Below is definition of the method
fix_fields() of the class Item_str_func that is base class for the
class Item_func_concat that is created on parsing the
SET STATEMENT FOR clause.
bool Item_str_func::fix_fields(THD *thd, Item **ref)
{
bool res= Item_func::fix_fields(thd, ref);
/*
In Item_str_func::check_well_formed_result() we may set null_value
flag on the same condition as in test() below.
*/
maybe_null= maybe_null || thd->is_strict_mode();
return res;
}
Although the clause SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR
is parsed on PREPARE phase during processing of the prepared statement,
real setting of the sql_mode system variable is done on EXECUTION phase.
On the other hand, the method Item_str_func::fix_fields is called on PREPARE
phase. In result, thd->is_strict_mode() returns true during calling the method
Item_str_func::fix_fields(), the data member maybe_null is assigned the value
true and column c1 is defined as DEFAULT NULL.
To fix the issue the system variables listed in the SET STATEMENT FOR clause
are set at the beginning of handling the PREPARE phase just right before
calling the function check_prepared_statement() and their original values
restored immediate after return from this function.
Additionally, to avoid code duplication the source code used in the function
mysql_execute_command for setting variables, specified by SET STATEMENT
clause, were extracted to the standalone functions
run_set_statement_if_requested(). This new function is called from
the function mysql_execute_command() and the method
Prepared_statement::prepare().
2021-02-25 08:20:11 +01:00
|
|
|
bool run_set_statement_if_requested(THD *thd, LEX *lex);
|
MDEV-16708: Unsupported commands for prepared statements
Withing this task the following changes were made:
- Added sending of metadata info in prepare phase for the admin related
command (check table, checksum table, repair, optimize, analyze).
- Refactored implmentation of HELP command to support its execution in
PS mode
- Added support for execution of LOAD INTO and XA- related statements
in PS mode
- Modified mysqltest.cc to run statements in PS mode unconditionally
in case the option --ps-protocol is set. Formerly, only those statements
were executed using PS protocol that matched the hard-coded regular expression
- Fixed the following issues:
The statement
explain select (select 2)
executed in regular and PS mode produces different results:
MariaDB [test]> prepare stmt from "explain select (select 2)";
Query OK, 0 rows affected (0,000 sec)
Statement prepared
MariaDB [test]> execute stmt;
+------+-------------+-------+------+---------------+------+---------+------+------+----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+------+---------------+------+---------+------+------+----------------+
| 1 | PRIMARY | NULL | NULL | NULL | NULL | NULL | NULL | NULL | No tables used |
| 2 | SUBQUERY | NULL | NULL | NULL | NULL | NULL | NULL | NULL | No tables used |
+------+-------------+-------+------+---------------+------+---------+------+------+----------------+
2 rows in set (0,000 sec)
MariaDB [test]> explain select (select 2);
+------+-------------+-------+------+---------------+------+---------+------+------+----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+------+---------------+------+---------+------+------+----------------+
| 1 | SIMPLE | NULL | NULL | NULL | NULL | NULL | NULL | NULL | No tables used |
+------+-------------+-------+------+---------------+------+---------+------+------+----------------+
1 row in set, 1 warning (0,000 sec)
In case the statement
CREATE TABLE t1 SELECT * FROM (SELECT 1 AS a, (SELECT a+0)) a
is run in PS mode it fails with the error
ERROR 1054 (42S22): Unknown column 'a' in 'field list'.
- Uniform handling of read-only variables both in case the SET var=val
statement is executed as regular or prepared statememt.
- Fixed assertion firing on handling LOAD DATA statement for temporary tables
- Relaxed assert condition in the function lex_end_stage1() by adding
the commands SQLCOM_ALTER_EVENT, SQLCOM_CREATE_PACKAGE,
SQLCOM_CREATE_PACKAGE_BODY to a list of supported command
- Removed raising of the error ER_UNSUPPORTED_PS in the function
check_prepared_statement() for the ALTER VIEW command
- Added initialization of the data memember st_select_lex_unit::last_procedure
(assign NULL value) in the constructor
Without this change the test case main.ctype_utf8 fails with the following
report in case it is run with the optoin --ps-protocol.
mysqltest: At line 2278: query 'VALUES (_latin1 0xDF) UNION VALUES(_utf8'a' COLLATE utf8_bin)' failed: 2013: Lost connection
- The following bug reports were fixed:
MDEV-24460: Multiple rows result set returned from stored
routine over prepared statement binary protocol is
handled incorrectly
CONC-519: mariadb client library doesn't handle server_status and
warnign_count fields received in the packet
COM_STMT_EXECUTE_RESPONSE.
Reasons for these bug reports have the same nature and caused by
missing loop iteration on results sent by server in response to
COM_STMT_EXECUTE packet.
Enclosing of statements for processing of COM_STMT_EXECUTE response
in the construct like
do
{
...
} while (!mysql_stmt_next_result());
fixes the above mentioned bug reports.
2021-04-22 09:52:19 +02:00
|
|
|
int mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt=false);
|
2021-02-14 18:30:39 +01:00
|
|
|
enum dispatch_command_return
|
|
|
|
{
|
|
|
|
DISPATCH_COMMAND_SUCCESS=0,
|
|
|
|
DISPATCH_COMMAND_CLOSE_CONNECTION= 1,
|
|
|
|
DISPATCH_COMMAND_WOULDBLOCK= 2
|
|
|
|
};
|
|
|
|
|
|
|
|
dispatch_command_return do_command(THD *thd, bool blocking = true);
|
|
|
|
dispatch_command_return dispatch_command(enum enum_server_command command, THD *thd,
|
|
|
|
char* packet, uint packet_length, bool blocking = true);
|
2010-03-31 16:05:33 +02:00
|
|
|
void log_slow_statement(THD *thd);
|
|
|
|
bool append_file_to_dir(THD *thd, const char **filename_ptr,
|
2018-01-07 17:03:44 +01:00
|
|
|
const LEX_CSTRING *table_name);
|
2010-03-31 16:05:33 +02:00
|
|
|
void execute_init_command(THD *thd, LEX_STRING *init_command,
|
|
|
|
mysql_rwlock_t *var_lock);
|
2010-06-11 03:30:49 +02:00
|
|
|
bool add_to_list(THD *thd, SQL_I_List<ORDER> &list, Item *group, bool asc);
|
2015-08-11 09:18:38 +02:00
|
|
|
void add_join_on(THD *thd, TABLE_LIST *b, Item *expr);
|
2010-03-31 16:05:33 +02:00
|
|
|
void add_join_natural(TABLE_LIST *a,TABLE_LIST *b,List<String> *using_fields,
|
|
|
|
SELECT_LEX *lex);
|
|
|
|
bool add_proc_to_list(THD *thd, Item *item);
|
|
|
|
bool push_new_name_resolution_context(THD *thd,
|
|
|
|
TABLE_LIST *left_op,
|
|
|
|
TABLE_LIST *right_op);
|
|
|
|
void init_update_queries(void);
|
2015-08-11 09:18:38 +02:00
|
|
|
Item *normalize_cond(THD *thd, Item *cond);
|
2010-03-31 16:05:33 +02:00
|
|
|
Item *negate_expression(THD *thd, Item *expr);
|
|
|
|
bool check_stack_overrun(THD *thd, long margin, uchar *dummy);
|
|
|
|
|
|
|
|
/* Variables */
|
|
|
|
|
2021-04-12 11:24:02 +02:00
|
|
|
extern const LEX_CSTRING any_db;
|
2010-03-31 16:05:33 +02:00
|
|
|
extern uint sql_command_flags[];
|
|
|
|
extern uint server_command_flags[];
|
2018-01-08 14:33:23 +01:00
|
|
|
extern const LEX_CSTRING command_name[];
|
2010-03-31 16:05:33 +02:00
|
|
|
extern uint server_command_flags[];
|
|
|
|
|
|
|
|
/* Inline functions */
|
2017-04-23 18:39:57 +02:00
|
|
|
inline bool check_identifier_name(LEX_CSTRING *str, uint err_code)
|
2010-03-31 16:05:33 +02:00
|
|
|
{
|
|
|
|
return check_identifier_name(str, NAME_CHAR_LEN, err_code, "");
|
|
|
|
}
|
|
|
|
|
2017-04-23 18:39:57 +02:00
|
|
|
inline bool check_identifier_name(LEX_CSTRING *str)
|
2010-03-31 16:05:33 +02:00
|
|
|
{
|
|
|
|
return check_identifier_name(str, NAME_CHAR_LEN, 0, "");
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
2020-02-09 18:53:11 +01:00
|
|
|
bool check_one_table_access(THD *thd, privilege_t privilege, TABLE_LIST *tables);
|
|
|
|
bool check_single_table_access(THD *thd, privilege_t privilege,
|
|
|
|
TABLE_LIST *tables, bool no_errors);
|
|
|
|
bool check_routine_access(THD *thd, privilege_t want_access,
|
2018-01-07 17:03:44 +01:00
|
|
|
const LEX_CSTRING *db,
|
|
|
|
const LEX_CSTRING *name,
|
2017-07-31 21:00:02 +02:00
|
|
|
const Sp_handler *sph, bool no_errors);
|
2020-02-09 18:53:11 +01:00
|
|
|
bool check_some_access(THD *thd, privilege_t want_access, TABLE_LIST *table);
|
2017-07-31 21:00:02 +02:00
|
|
|
bool check_some_routine_access(THD *thd, const char *db, const char *name,
|
|
|
|
const Sp_handler *sph);
|
2020-02-09 18:53:11 +01:00
|
|
|
bool check_table_access(THD *thd, privilege_t requirements,TABLE_LIST *tables,
|
2010-03-31 16:05:33 +02:00
|
|
|
bool any_combination_of_privileges_will_do,
|
|
|
|
uint number,
|
|
|
|
bool no_errors);
|
|
|
|
#else
|
2020-02-09 18:53:11 +01:00
|
|
|
inline bool check_one_table_access(THD *thd, privilege_t privilege, TABLE_LIST *tables)
|
2010-03-31 16:05:33 +02:00
|
|
|
{ return false; }
|
2020-02-09 18:53:11 +01:00
|
|
|
inline bool check_single_table_access(THD *thd, privilege_t privilege,
|
|
|
|
TABLE_LIST *tables, bool no_errors)
|
2010-03-31 16:05:33 +02:00
|
|
|
{ return false; }
|
2020-02-09 18:53:11 +01:00
|
|
|
inline bool check_routine_access(THD *thd, privilege_t want_access,
|
2018-01-07 17:03:44 +01:00
|
|
|
const LEX_CSTRING *db,
|
|
|
|
const LEX_CSTRING *name,
|
2017-07-31 21:00:02 +02:00
|
|
|
const Sp_handler *sph, bool no_errors)
|
2010-03-31 16:05:33 +02:00
|
|
|
{ return false; }
|
2020-02-09 18:53:11 +01:00
|
|
|
inline bool check_some_access(THD *thd, privilege_t want_access, TABLE_LIST *table)
|
2010-04-07 13:58:40 +02:00
|
|
|
{
|
|
|
|
table->grant.privilege= want_access;
|
|
|
|
return false;
|
|
|
|
}
|
2010-03-31 16:05:33 +02:00
|
|
|
inline bool check_some_routine_access(THD *thd, const char *db,
|
2017-07-31 21:00:02 +02:00
|
|
|
const char *name,
|
|
|
|
const Sp_handler *sph)
|
2010-03-31 16:05:33 +02:00
|
|
|
{ return false; }
|
|
|
|
inline bool
|
2020-02-09 18:53:11 +01:00
|
|
|
check_table_access(THD *thd, privilege_t requirements,TABLE_LIST *tables,
|
2010-03-31 16:05:33 +02:00
|
|
|
bool any_combination_of_privileges_will_do,
|
|
|
|
uint number,
|
|
|
|
bool no_errors)
|
|
|
|
{ return false; }
|
|
|
|
#endif /*NO_EMBEDDED_ACCESS_CHECKS*/
|
|
|
|
|
|
|
|
#endif /* SQL_PARSE_INCLUDED */
|